Vue基础(环境配置、内部指令、全局API、选项、内置组件)
1、环境配置
安装VsCode
安装包管理工具:直接下载 NodeJS 进行安装即可,NodeJS自带 Npm 包管理工具,下载地址:https://nodejs.org/en/download/
安装完成后在命令行执行以下命令查看npm包管理器版本
npm -v
npm中文文档:https://www.npmjs.cn/
配置淘宝镜像
npm install cnpm -g --registry=https://registry.npm.taobao.org
然后执行 cnpm -v 查看版本信息
下载vue.js(包含完整的警告和调试模式)与vue.min.js(删除了警告,30.96KB min+gzip)
安装live-server 作为服务器
用npm进行全局安装(-g参数)
cnpm install -g live-server
然后在任何一个Html页面文件路径下执行 live-server 就会打开
然后执行 cnpm init 进行初始化
会在主文件夹下生成 package.json 文件来存储初始化信息配置
package.json:
{ "name": "vue", "version": "1.0.0", "description": "Vue Demo", "main": "index.js", "directories": { "example": "example" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" }
2、Vue内部指令
2.1、hello world
编写第一个HelloWorld代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Helloworld</title> <script type="text/javascript" src="js/vue.js"></script> </head> <body> <h1>Hello World</h1> <hr> <div id="app"> {{message}} </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { message: "hello Vue!!!!" } }) </script> </body> </html>
2.2、v-if v-else v-show 指令
-
v-if的使用
v-if:是vue 的一个内部指令,指令用在我们的html中。
v-if用来判断是否加载html的DOM,比如我们模拟一个用户登录状态,在用户登录后现实用户名称。
关键代码:
<div v-if="isLogin">你好</div>
-
v-show的使用
调整css中display属性,DOM已经加载,只是CSS控制没有显示出来。
<div v-show="isLogin">你好</div>
-
完整html代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>v-if&v-else&v-show</title> <script type="text/javascript" src="js/vue.js"></script> </head> <body> <h1>v-if&v-else&v-show</h1> <hr> <div id="app"> <div v-if="isLogin">你好v-if</div> <div v-else>你好v-else</div> <div v-show="isLogin">你好v-show</div> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { isLogin:false } }) </script> </body> </html>
-
v-if 和v-show的区别:
- v-if: 判断是否加载,可以减轻服务器的压力,在需要时加载。
- v-show:调整css dispaly属性,可以使客户端操作更加流畅。
2.3、v-for指令 :解决模板循环问题
模板写法
<li v-for="item in items"> {{item}} </li>
- js写法
var app=new Vue({ el:'#app', data:{ items:[20,23,18,65,32,19,54,56,41] } })
- 完整代码:
<!DOCTYPE html> <html lang="en"> <head> <title>v-for</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>v-for 实例</h1> <hr> <div id="app"> <ul> <li v-for="item in sortItems">{{item}}</li> </ul> <ul> <li v-for="(student,index) in srotStudents"> {{index+1}}:{{student.name}}-{{student.age}} </li> </ul> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { items: [20, 23, 18, 7, 32, 19, 54, 56, 41], students: [{ name: "JS", age: 33 }, { name: "Panda", age: 28 }, { name: "Panpan", age: 23 }, { name: "King", age: 14 }, ] }, computed: { sortItems: function () { return this.items.sort(SortNumber); }, srotStudents: function () { return sortByKey(this.students,'age') } }, }) function SortNumber(a, b) { return a - b; } //数组对象方法排序: function sortByKey(array, key) { return array.sort(function (a, b) { var x = a[key]; var y = b[key]; return ((x < y) ? -1 : ((x > y) ? 1 : 0)); }); } </script> </body> </html>
2.4、v-text & v-html
我们已经会在html中输出data中的值了,我们已经用的是{{xxx}},这种情况是有弊端的,就是当我们网速很慢或者javascript出错时,会暴露我们的{{xxx}}。Vue给我们提供的 v-text ,就是解决这个问题的。我们来看代码:
<span>{{ message }}</span>=<span v-text="message"></span><br/>
如果在javascript中写有html标签,用v-text是输出不出来的,这时候我们就需要用 v-html 标签了。
<span v-html="msgHtml"></span>
双大括号会将数据解释为纯文本,而非HTML。为了输出真正的HTML,你就需要使用v-html 指令。 需要注意的是:在生产环境中动态渲染HTML是非常危险的,因为容易导致XSS
攻击。所以只能在可信的内容上使用v-html,永远不要在用户提交和可操作的网页上使用。 完整代码:
<!DOCTYPE html> <html lang="en"> <head> <title>v-text & v-html 实例</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>v-text & v-html 实例</h1> <hr> <div id="app"> <span>{{message}}</span> <span v-text="message"></span> <br> <span>{{dodo}}</span> <span v-html="dodo"></span> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { message: "hello Vue!", dodo:"<h2>hello Vue!</h2>" } }) </script> </body> </html>
2.5、v-on:绑定事件监听器
使用绑定事件监听器,编写一个加分减分的程序。
程序代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>v-on 实例</title> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>v-on 实例</h1> <hr> <div id="app"> 本厂比赛得分:{{score}} <p> <button v-on:click="scoreIncrease">加分</button> <button @click="scoreDecrease">减分</button> <br /> <input type="text" v-on:keyup.enter="onEnter" v-model="score2"> </p> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { score: 0, score2: 1 }, methods: { scoreIncrease: function () { this.score++; }, scoreDecrease: function () { if (this.score > 0) { this.score--; } }, onEnter: function () { this.score +=parseInt(this.score2); } } }) </script> </body> </html>
我们的v-on 还有一种简单的写法,就是用@代替。
<button @click="jianfen">减分</button>
我们除了绑定click之外,我们还可以绑定其它事件,比如键盘回车事件v-on:keyup.enter,现在我们增加一个输入框,然后绑定回车事件,回车后把文本框里的值加到我们的count上。 绑定事件写法:
<input type="text" v-on:keyup.enter="onEnter" v-model="secondCount">
javascript代码:
onEnter:function(){ this.count=this.count+parseInt(this.secondCount); }
因为文本框的数字会默认转变成字符串,所以我们需要用 parseInt() 函数
进行整数转换。
你也可以根据键值表来定义键盘事件:
2.6、v-model指令
v-model指令,我理解为绑定数据源。就是把数据绑定在特定的表单元素上,可以很容易的实现双向数据绑定。
- 我们来看一个最简单的双向数据绑定代码
html文件:
<div id="app"> <p>原始文本信息:{{message}}</p> <h3>文本框</h3> <p>v-model:<input type="text" v-model="message"></p> </div>
javascript代码:
var app=new Vue({ el:'#app', data:{ message:'hello Vue!' } })
-
修饰符
- .lazy:取代 imput 监听 change 事件。
- .number:输入字符串转为数字。
- .trim:输入去掉首尾空格。
- 文本区域加入数据绑定
<textarea cols="30" rows="10" v-model="message"></textarea>
- 多选按钮绑定一个值
<h3>多选按钮绑定一个值</h3> <input type="checkbox" id="isTrue" v-model="isTrue"> <label for='isTrue'>{{isTrue}}</label>
- 多选绑定一个数组
<h3>多选绑定一个数组</h3> <p> <input type="checkbox" id="JS" value="JS" v-model="web_Names"> <label for="JS">JS</label><br /> <input type="checkbox" id="Panda" value="Panda" v-model="web_Names"> <label for="Panda">Panda</label><br /> <input type="checkbox" id="PanPan" value="PanPan" v-model="web_Names"> <label for="PanPan">PanPan</label> <p>{{web_Names}}</p> </p>
- 单选按钮绑定
<h3>单选按钮绑定</h3> <input type="radio" id="one" value="男" v-model="sex"> <label for="one">男</label> <input type="radio" id="two" value="女" v-model="sex"> <label for="two">女</label> <p>{{sex}}</p>
- 完整代码:
<!DOCTYPE html> <html lang="en"> <head> <title>v-model 实例</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>v-model 实例</h1> <hr> <div id="app"> <p>原始文本信息:{{message}}</p> <h3>文本框</h3> <p>v-model:<input type="text" v-model="message"></p> <p>v-model.lazy:<input type="text" v-model.lazy="message"></p> <p>v-model.number:<input type="text" v-model.number="message"></p> <p>v-model.trim<input type="text" v-model.trim="message"></p> <hr> <h3>文本域</h3> <textarea cols="30" rows="10" v-model="message"></textarea> <hr> <h3>多选按钮绑定一个值</h3> <input type="checkbox" id="isTrue" v-model="isTrue"> <label for='isTrue'>{{isTrue}}</label> <hr> <h3>多选绑定一个数组</h3> <p> <input type="checkbox" id="JS" value="JS" v-model="web_Names"> <label for="JS">JS</label><br /> <input type="checkbox" id="Panda" value="Panda" v-model="web_Names"> <label for="Panda">Panda</label><br /> <input type="checkbox" id="PanPan" value="PanPan" v-model="web_Names"> <label for="PanPan">PanPan</label> <p>{{web_Names}}</p> </p> <hr> <h3>单选按钮绑定</h3> <input type="radio" id="one" value="男" v-model="sex"> <label for="one">男</label> <input type="radio" id="two" value="女" v-model="sex"> <label for="two">女</label> <p>{{sex}}</p> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { message: "hello Vue!!!!", isTrue: true, web_Names: [], sex:"男" } }) </script> </body> </html>
2.7、v-bind 指令
v-bind是处理HTML中的标签属性的,例如
就是一个标签,也是一个标签,我们绑定上的src进行动态赋值。
html文件:
<div id="app"> <img v-bind:src="imgSrc" width="200px"> </div>
在html中我们用v-bind:src=”imgSrc”的动态绑定了src的值,这个值是在vue构造器里的data属性中找到的。
js文件:
var app = new Vue({ el: '#app', data: { imgSrc: "https://www.baidu.com/img/baidu_jgylogo3.gif", } })
我们在data对象在中增加了imgSrc属性来供html调用。
- v-bind 缩写
<!-- 完整语法 --> <a v-bind:href="url"></a> <!-- 缩写 --> <a :href="url"></a>
-
绑定CSS样式
在工作中我们经常使用v-bind来绑定css样式:
在绑定CSS样式是,绑定的值必须在vue中的data属性中进行声明。
直接绑定class样式
<div :class="className">1、绑定classA</div>
绑定classA并进行判断,在isOK为true时显示样式,在isOk为false时不显示样式。
<div :class="{classA:isOk}">2、绑定class中的判断</div>
绑定class中的数组
<div :class="[classA,classB]">3、绑定class中的数组</div>
绑定class中使用三元表达式判断
<div :class="isOk?classA:classB">4、绑定class中的三元表达式判断</div>
绑定style
<div :style="{color:red,fontSize:font}">5、绑定style</div>
用对象绑定style样式
<div :style="styleObject">6、用对象绑定style样式</div>
el:'#app', data:{ styleObject:{ fontSize:'24px', color:'green' } } })
2.8、其他内部指令(v-pre & v-cloak & v-once)
- v-pre指令
在模板中跳过vue的编译,直接输出原始值。就是在标签中加入v-pre就不会输出vue中的data值了。
<div v-pre>{{message}}</div>
-
这时并不会输出我们的message值,而是直接在网页中显示{{message}}
-
v-cloak指令
在vue渲染完指定的整个DOM后才进行显示。它必须和CSS样式一起使用,
[v-cloak] { display: none; }
<div v-cloak> {{ message }} </div>
v-once指令
在第一次DOM时进行渲染,渲染完成后视为静态内容,跳出以后的渲染过程。
<div v-once>第一次绑定的值:{{message}}</div> <div><input type="text" v-model="message"></div>
3、全局API
什么是全局API?
全局API并不在构造器里,而是先声明全局变量或者直接在Vue上定义一些新功能,Vue内置了一些全局API,比如我们今天要学习的指令Vue.directive。说的简单些就是,在构造器外部用Vue提供给我们的API函数来定义新的功能。
3.1、Vue.directive自定义指令
在自定义指令前我们写一个小功能,在页面上有一个数字为10,数字的下面有一个按钮,我们每点击一次按钮后,数字加1.
我们这里使用 Vue.directive( ) 自己定义一个全局的指令
Vue.directive('jsdirective',function(el,binding,vnode){ el.style='color:'+binding.value; });
- 自定义指令中传递的三个参数
- el: 指令所绑定的元素,可以用来直接操作DOM。
- binding: 一个对象,包含指令的很多信息。
- vnode: Vue编译生成的虚拟节点。
- 自定义指令的生命周期
自定义指令有五个生命周期(也叫钩子函数),分别是 bind,inserted,update,componentUpdated,unbind
- bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个绑定时执行一次的初始化动作。
- inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于document中)
- update:被绑定于元素所在的模板更新时调用,而无论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。
- componentUpdated:被绑定元素所在模板完成一次更新周期时调用。
- unbind:只调用一次,指令与元素解绑时调用。
bind:function(){//被绑定 console.log('1 - bind'); }, inserted:function(){//绑定到节点 console.log('2 - inserted'); }, update:function(){//组件更新 console.log('3 - update'); }, componentUpdated:function(){//组件更新完成 console.log('4 - componentUpdated'); }, unbind:function(){//解绑 console.log('5 - unbind'); }
3.2、Vue.extend构造器的延伸
Vue.extend 返回的是一个“扩展实例构造器”,也就是预设了部分选项的Vue实例构造器。经常服务于Vue.component用来生成组件,可以简单理解为当在模板中遇到该组件名称作为标签的自定义元素时,会自动调用“扩展实例构造器”来生产组件实例,并挂载到自定义元素上。
由于我们还没有学习Vue的自定义组件,所以我们先看跟组件无关的用途。
-
自定义无参数标签
我们想象一个需求,需求是这样的,要在博客页面多处显示作者的网名,并在网名上直接有链接地址。我们希望在html中只需要写 ,这和自定义组件很像,但是他没有传递任何参数,只是个静态标签。
我们的Vue.extend该登场了,我们先用它来编写一个扩展实例构造器。代码如下:
html:<author></author>
javascript:
-
var authorExtend=Vue.extend({ template:"<p><a :href='authorUrl'>{{authorName}}</a></p>", data() { //data()=data:function(){} return { authorName:"进击的辣条", authorUrl:"https://www.cnblogs.com/wyt007" } }, })
-
这时html中的标签还是不起作用的,因为扩展实例构造器是需要挂载的,我们再进行一次挂载。
还可以通过HTML标签上的id或者class来生成扩展实例构造器,Vue.extend里的代码是一样的,只是在挂载的时候,我们用类似jquery的选择器的方法,来进行挂载就可以了。new authorExtend().$mount('author');
全部代码:
-
<!DOCTYPE html> <html lang="en"> <head> <title>Vue.extend 扩展实例构造器</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>Vue.extend 扩展实例构造器</h1> <hr> <author></author> <script type="text/javascript"> var authorExtend=Vue.extend({ template:"<p><a :href='authorUrl'>{{authorName}}</a></p>", data() { //data()=data:function(){} return { authorName:"进击的辣条", authorUrl:"https://www.cnblogs.com/wyt007" } }, }) new authorExtend().$mount('author'); </script> </body> </html>
-
效果演示:
3.3、Vue.set全局操作
Vue.set 的作用就是在构造器外部操作构造器内部的数据、属性或者方法。比如在vue构造器内部定义了一个count为1的数据,我们在构造器外部定义了一个方法,要每次点击按钮给值加1.就需要用到 Vue.set
-
引用构造器外部数据
什么是外部数据,就是不在Vue构造器里里的data处声明,而是在构造器外部声明,然后在data处引用就可以了。外部数据的加入让程序更加灵活,我们可以在外部获取任何想要的数据形式,然后让data引用。 看一个简单的代码: -
//在构造器外部声明数据 var outData={ count:1, goodName:'car' }; var app=new Vue({ el:'#app', //引用外部数据 data:outData })
- 在外部改变数据的三种方法
- 用Vue.set改变
function add(){ Vue.set(outData,'count',4); }
- 用Vue对象的方法添加
app.count++;
- 直接操作外部数据
outData.count++;
其实这三种方式都可以操作外部的数据,Vue也给我们增加了一种操作外部数据的方法。
- 用Vue.set改变
-
为什么要有Vue.set的存在?
由于Javascript的限制,Vue不能自动检测以下变动的数组。
- 当你利用索引直接设置一个项时,vue不会为我们自动更新。
- 当你修改数组的长度时,vue不会为我们自动更新。
- 全部代码:
-
<!DOCTYPE html> <html lang="en"> <head> <title>Vue.set 全局操作</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>Vue.set 全局操作</h1> <hr> <div id="app"> {{count}} <ul> <li v-for="item in arr">{{item}}</li> </ul> </div> <p><button onclick="add()">add</button></p> <script type="text/javascript"> function add(params) { //Vue.set(outData, "count",++outData.count); //app.count++; //outData.count++; //outData.arr[1]="ddd";//不行,js天生的弱点 Vue.set(outData.arr, 1,"dd"); } var outData = { count: 1, goods: "car", arr:["aaa","bbb","ccc"] } var app = new Vue({ el: '#app', data: outData }) </script> </body> </html>
- 效果展示:
3.4、Vue的生命周期(钩子函数)
Vue一共有10个生命周期函数,我们可以利用这些函数在vue的每个阶段都进行操作数据或者改变内容。
- 示例代码:
-
<!DOCTYPE html> <html lang="en"> <head> <title>Vue生命周期</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>Vue生命周期</h1> <hr> <div id="app"> {{count}} <p><button @click="add">Add</button></p> </div> <button onclick="app.$destroy()">销毁</button> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { count: 1 }, methods: { add() { this.count++; } }, beforeCreate: function () { console.log('1-beforeCreate 初始化之前'); }, created: function () { console.log('2-created 创建完成'); }, beforeMount: function () { console.log('3-beforeMount 挂载之前'); }, mounted: function () { console.log('4-mounted 挂载之后'); }, beforeUpdate: function () { console.log('5-beforeUpdate 数据更新前'); }, updated: function () { console.log('6-updated 被更新后'); }, activated: function () { console.log('7-activated'); }, deactivated: function () { console.log('8-deactivated'); }, beforeDestroy: function () { console.log('9-beforeDestroy 销毁之前'); }, destroyed: function () { console.log('10-destroyed 销毁之后') } }) </script> </body> </html>
- 效果演示:
3.5、Template 制作模版
-
直接写在选项里的模板
直接在构造器里的template选项后边编写。这种写法比较直观,但是如果模板html代码太多,不建议这么写。 -
var app=new Vue({ el:'#app', data:{ message:'hello Vue!' }, template:` <h1 style="color:red">我是选项模板</h1> ` })
-
这里需要注意的是模板的标识不是单引号和双引号,而是,就是Tab上面的键。
-
写在template标签里的模板
这种写法更像是在写HTML代码,就算不会写Vue的人,也可以制作页面 -
<template id="dd2"> <h2 style="color:red">我是Template标签模板</h2> </template> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { message: "hello world!" }, template:"#dd2" }) </script>
-
写在script标签里的模板
这种写模板的方法,可以让模板文件从外部引入。 -
<script type="x-template" id="dd3"> <h2 style="color:red">我是script标签模板</h2> </script> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { message: "hello world!" }, template: "#dd3" }) </script>
- 代码示例:
-
<!DOCTYPE html> <html lang="en"> <head> <title>Template 三种写法</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>Template 三种写法</h1> <hr> <div id="app"> {{message}} </div> <template id="dd2"> <h2 style="color:red">我是Template标签模板</h2> </template> <script type="x-template" id="dd3"> <h2 style="color:red">我是script标签模板</h2> </script> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { message: "hello world!" }, //template: `<h2 style="color:red">我是选项模板</h2>` //template:"#dd2" template: "#dd3" }) </script> </body> </html>
- 运行效果:
3.6、Component 初识组件
-
全局化注册组件
全局化就是在构造器的外部用Vue.component来注册,我们注册现在就注册一个的组件来体验一下。 -
<!DOCTYPE html> <html lang="en"> <head> <title>component-1</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>component-1</h1> <hr> <div id="app"> <jscomponent></jsComponent> <panda></panda> </div> <script type="text/javascript"> Vue.component('jscomponent', { //组件名称必须全部小写 我是猪,调试了半天 template: `<div style="color:red">我是全局的自定义jscomponent组件</div>` }) var app = new Vue({ el: '#app', }) </script> </body> </html>
-
我们在javascript里注册了一个组件,在HTML中调用了他。这就是最简单的一个组件的编写方法,并且它可以放到多个构造器的作用域里。
-
局部注册组件局部
局部注册组件局部注册组件和全局注册组件是向对应的,局部注册的组件只能在组件注册的作用域里进行使用,其他作用域使用无效。 -
<!DOCTYPE html> <html lang="en"> <head> <title>component-1</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>component-1</h1> <hr> <div id="app"> <jscomponent></jsComponent> <panda></panda> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', components: { //局部组件可以定义多个,所以使用components,全局组件只能一个一个定义,所以使用component "panda": { template: `<div style="color:green">我是局部的自定义panda组件</div>` } } }) </script> </body> </html>
-
从代码中你可以看出局部注册其实就是写在构造器里,但是你需要注意的是,构造器里的components 是加s的,而全局注册是不加s的。
-
组件和指令的区别
组件注册的是一个标签,而指令注册的是已有标签里的一个属性。在实际开发中我们还是用组件比较多,指令用的比较少。因为指令看起来封装的没那么好,这只是个人观点。 - 示例代码:
-
<!DOCTYPE html> <html lang="en"> <head> <title>component-1</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>component-1</h1> <hr> <div id="app"> <jscomponent></jsComponent> <panda></panda> </div> <script type="text/javascript"> Vue.component('jscomponent', { //组件名称必须全部小写 我是猪,调试了半天 template: `<div style="color:red">我是全局的自定义jscomponent组件</div>` }) var app = new Vue({ el: '#app', components: { //局部组件可以定义多个,所以使用components,全局组件只能一个一个定义,所以使用component "panda": { template: `<div style="color:green">我是局部的自定义panda组件</div>` } } }) </script> </body> </html>
- 效果演示:
3.7、Component 组件props 属性设置
props选项就是设置和获取标签上的属性值的,例如我们有一个自定义的组件,这时我们想给他加个标签属性写成 意思就是熊猫来自中国,当然这里的China可以换成任何值。定义属性的选项是props。
-
定义属性并获取属性值
定义属性我们需要用props选项,加上数组形式的属性名称,例如:props:[‘here’]。在组件的模板里读出属性值只需要用插值的形式,例如{{ here }}. -
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="../assets/js/vue.js"></script> <title>component-2</title> </head> <body> <h1>component-2</h1> <hr> <div id="app"> <panda here="China"></panda> </div> <script type="text/javascript"> var app=new Vue({ el:'#app', components:{ "panda":{ template:`<div style="color:red;">Panda from {{ here }}.</div>`, props:['here'] } } }) </script> </body> </html>
-
上面的代码定义了panda的组件,并用props设置了here的属性值,在here属性值里传递了China给组件。 最后输出的结果是红色字体的Panda from China.
-
属性中带’-‘的处理方式
我们在写属性时经常会加入’-‘来进行分词,比如:,那这时我们在props里如果写成props:[‘form-here’]是错误的,我们必须用小驼峰式写法props:[‘formHere’]。
html文件:
<panda from-here="China"></panda>
javascript文件:
-
var app=new Vue({ el:'#app', components:{ "panda":{ template:`<div style="color:red;">Panda from {{ here }}.</div>`, props:['fromHere'] } } })
-
PS:因为这里有坑,所以还是少用-为好
-
在构造器里向组件中传值
把构造器中data的值传递给组件,我们只要进行绑定就可以了。就是我们第一季学的v-bind:xxx.
我们直接看代码:
Html文件:
<panda :from-here="message"></panda>
javascript文件:
-
var app = new Vue({ el: '#app', data:{ message:"China" }, components: { //局部组件可以定义多个,所以使用components,全局组件只能一个一个定义,所以使 "panda": { template: `<div style="color:green">Panda from {{fromHere}}</div>`, props:["fromHere"] } } })
- 示例代码:
-
<!DOCTYPE html> <html lang="en"> <head> <title>component props 属性设置</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>component props 属性设置</h1> <hr> <div id="app"> <panda :from-here="message"></panda> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data:{ message:"China" }, components: { //局部组件可以定义多个,所以使用components,全局组件只能一个一个定义,所以使用component "panda": { template: `<div style="color:green">Panda from {{fromHere}}</div>`, props:["fromHere"] } } }) </script> </body> </html>
- 效果演示:
3.8、Component 父子组件关系
在实际开发中我们经常会遇到在一个自定义组件中要使用其他自定义组件,这就需要一个父子组件关系。
-
构造器外部写局部注册组件
上面我们都把局部组件的编写放到了构造器内部,如果组件代码量很大,会影响构造器的可读性,造成拖拉和错误。
我们把组件编写的代码放到构造器外部或者说单独文件。
我们需要先声明一个对象,对象里就是组件的内容。
var pandaComponent = { template: `<div style="color:red">Panda from China</p></div>` };
声明好对象后在构造器里引用就可以了。
-
var app = new Vue({ el: '#app', components: { "panda": pandaComponent, } })
-
html中引用
<div id="app"> <panda></panda> </div>
- 父子组件的嵌套
我们先声明一个父组件,比如叫jspang,然后里边我们加入一个city组件,我们来看这样的代码如何写。
示例代码: -
<!DOCTYPE html> <html lang="en"> <head> <title>component-3 父子组件</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>component-3 父子组件</h1> <hr> <div id="app"> <panda></panda> <city></city> </div> <script type="text/javascript"> var cityComponent = {//根据加载顺序,要先写子组件,不然会报Unknown custom element: <city> - did you register the component correctly? For recursive components, make sure to provide the "name" option. template: `<div style="color:green">SiChuan of China</div>`, }; var pandaComponent = { template: ` <div style="color:red"> <p>Panda from China</p> <city></city> </div> `, components: { "city": cityComponent } }; var app = new Vue({ el: '#app', components: { "panda": pandaComponent, "city": cityComponent, } }) </script> </body> </html>
-
效果演示:
3.9、Component 标签
标签是Vue框架自定义的标签,它的用途就是可以动态绑定我们的组件,根据数据的不同更换不同的组件。
- 我们先在构造器外部定义三个不同的组件,分别是componentA,componentB和componentC.
-
var componentA = { template: `<div style="color:red">I'm componentA.</div>` } var componentB = { template: `<div style="color:green">I'm componentB.</div>` } var componentC = { template: `<div style="color:pink">I'm componentC.</div>` }
- 我们在构造器的components选项里加入这三个组件。
-
var app = new Vue({ el: '#app', data: { who: "componentA" }, components: { "componentA": componentA, "componentB": componentB, "componentC": componentC, }, methods: { changeComponent: function () { if (this.who == "componentA") this.who = "componentB"; else if (this.who == "componentB") this.who = "componentC"; else this.who = "componentA"; } }, })
- 我们在html里插入component标签,并绑定who数据,根据who的值不同,调用不同的组件。
<component :is="who"></component>
-
这就是我们的组件标签的基本用法。我们提高以下,给页面加个按钮,每点以下更换一个组件。
<div id="app"> <component :is="who"></component> <button @click="changeComponent">changeComponent</button> </div>
- 示例代码:
-
<!DOCTYPE html> <html lang="en"> <head> <title>component-4 标签</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>component-4 标签</h1> <hr> <div id="app"> <component :is="who"></component> <button @click="changeComponent">changeComponent</button> </div> <script type="text/javascript"> var componentA = { template: `<div style="color:red">I'm componentA.</div>` } var componentB = { template: `<div style="color:green">I'm componentB.</div>` } var componentC = { template: `<div style="color:pink">I'm componentC.</div>` } var app = new Vue({ el: '#app', data: { who: "componentA" }, components: { "componentA": componentA, "componentB": componentB, "componentC": componentC, }, methods: { changeComponent: function () { if (this.who == "componentA") this.who = "componentB"; else if (this.who == "componentB") this.who = "componentC"; else this.who = "componentA"; } }, }) </script> </body> </html>
- 效果展示:
4、选项
选项就是在Vue构造器里的配置功能的前缀(Vue已经给我们定义好了),Vue有很多选项,我们将在这一级教程中一一介绍。
4.1、propsData Option 全局扩展的数据传递
propsData 不是和属性有关,他用在全局扩展时进行传递数据。实际我们并不推荐用全局扩展的方式作自定义标签,我们学了组件,完全可以使用组件来做,这里只是为了演示propsData的用法。
- 扩展代码如下:
-
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="../assets/js/vue.js"></script> <title>PropsData Option Demo</title> </head> <body> <h1>PropsData Option Demo</h1> <hr> <header></header> <script type="text/javascript"> var header_a = Vue.extend({ template:`<p>{{message}}</p>`, data:function(){ return { message:'Hello,I am Header' } } }); new header_a().$mount('header'); </script> </body> </html>
- propsData传递数据
- 扩展标签已经做好了,这时我们要在挂载时传递一个数字过去,我们就用到了propsData。 我们用propsData三步解决传值:
- 在全局扩展里加入props进行接收。propsData:{a:1}
- 传递时用propsData进行传递。props:[‘a’]
- 用插值的形式写入模板。{{ a }}
- propsData代码:
var header_a = Vue.extend({ template:`<p>{{message}}-{{a}}</p>`, data:function(){ return { message:'Hello,I am Header' } }, props:['a'] }); new header_a({propsData:{a:1}}).$mount('header');
- 代码示例:
-
<!DOCTYPE html> <html lang="en"> <head> <title>propsData Option</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>propsData Option</h1> <hr> <header></header> <script type="text/javascript"> var header_a = Vue.extend({ template: `<p>{{message}}-{{a}}</p>`, data() { return { message: "Hello , I am header!" } }, props:['a'] }) new header_a({propsData:{a:1}}).$mount("header"); </script> </body> </html>
- 效果展示:
总结:propsData在实际开发中我们使用的并不多,我们在后边会学到Vuex的应用,他的作用就是在单页应用中保持状态和数据的。
- 效果展示:
4.2、computed Option 计算选项
computed 的作用主要是对原数据进行改造输出。改造输出:包括格式的编辑,大小写转换,顺序重排,添加符号……。
4.2.1、格式化输出结果
我们先来做个读出价格的例子:我们读书的原始数据是price:100 但是我们输出给用户的样子是(¥100元)。
主要的javascript代码:
computed: { newPrice:function(){ return "¥"+this.price+"元"; } },
全部代码:
<!DOCTYPE html> <html lang="en"> <head> <title>computed option</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>computed option</h1> <hr> <div id="app"> {{newPrice}} </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { price:100 }, computed: { newPrice:function(){ return "¥"+this.price+"元"; } }, }) </script> </body> </html>
效果展示:
现在输出的结果就是:¥100元。
4.2.2、用计算属性反转数组
例如:我们得到了一个新闻列表的数组,它的顺序是安装新闻时间的顺序正序排列的,也就是早反生的新闻排在前面。这是反人类的,我们需要给他反转。这时我们就可以用到我们的计算属性了。没有排序的新闻列表,是安装日期正序排列的。
var newsList=[ {title:'香港或就“装甲车被扣”事件追责 起诉涉事运输公司',date:'2017/3/10'}, {title:'日本第二大准航母服役 外媒:针对中国潜艇',date:'2017/3/12'}, {title:'中国北方将有明显雨雪降温天气 南方阴雨持续',date:'2017/3/13'}, {title:'起底“最短命副市长”:不到40天落马,全家被查',date:'2017/3/23'}, ];
我们希望输出的结果:
- 起底“最短命副市长”:不到40天落马,全家被查-2017/3/23
- 中国北方将有明显雨雪降温天气 南方阴雨持续-2017/3/13
- 日本第二大准航母服役 外媒:针对中国潜艇-2017/3/12
- 香港或就“装甲车被扣”事件追责 起诉涉事运输公司-2017/3/10 我们的在computed里的javascript代码:我们用js原生方法给数组作了反转。
computed:{ reverseNews:function(){ return this.newsList.reverse(); } }
全部代码:
<!DOCTYPE html> <html lang="en"> <head> <title>computed option</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>computed option</h1> <hr> <div id="app"> <p>{{newPrice}}</p> <ol> <li v-for="item in reverseNews">{{item.title}}-{{item.date}}</li> </ol> </div> <script type="text/javascript"> var newsList = [{ title: '香港或就“装甲车被扣”事件追责 起诉涉事运输公司', date: '2017/3/10' }, { title: '日本第二大准航母服役 外媒:针对中国潜艇', date: '2017/3/12' }, { title: '中国北方将有明显雨雪降温天气 南方阴雨持续', date: '2017/3/13' }, { title: '起底“最短命副市长”:不到40天落马,全家被查', date: '2017/3/23' }, ]; var app = new Vue({ el: '#app', data: { price: 100, newsList: newsList }, computed: { newPrice: function () { return "¥" + this.price + "元"; }, reverseNews: function () { return this.newsList.reverse(); } }, }) </script> </body> </html>
效果展示:
4.3、Methods Option 方法选项
我们还是复习一下最简单的使用方法,一个数字,每点击一下按钮加1.(做过很多次了,你们可以先不看代码和视频自己试着写一下)
<!DOCTYPE html> <html lang="en"> <head> <title>methods options</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>methods options</h1> <hr> <div id="app"> {{a}} <p><button @click="add">add</button></p> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { a: 1 }, methods: { add:function(){ this.a++; } }, }) </script> </body> </html>
4.3.1、methods中参数的传递
使用方法和正常的javascript传递参数的方法一样,分为两部:
- 在methods的方法中进行声明,比如我们给add方法加上一个num参数,就要写出 add:function(num){}.
- 调用方法时直接传递,比如我们要传递2这个参数,我们在button上就直接可以写。 <button @click=”add(2)”></button>.
现在知道了加参数的方法,看一段完整的代码,代码中给add添加了num参数,并在按钮上调用传递了。
示例代码:
<!DOCTYPE html> <html lang="en"> <head> <title>methods options</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>methods options</h1> <hr> <div id="app"> {{a}} <p><button @click="add(2)">add</button></p> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { a: 1 }, methods: { add:function(num){ if (num!=null) { this.a+=num } else { this.a++; } } }, }) </script> </body> </html>
效果展示:
这时,再点击按钮是每次加2个数字。
4.3.2、methods中的$event参数
传递的$event参数都是关于你点击鼠标的一些事件和属性。我们先看看传递的方法。
传递:
<p><button @click="add(2,$event)">add</button></p>
我们这时候可以打印一下,看看event到底是个怎样的对象。你会发现,它包含了大部分鼠标事件的属性。
4.3.3、native 给组件绑定构造器里的原生事件
在实际开发中经常需要把某个按钮封装成组件,然后反复使用,如何让组件调用构造器里的方法,而不是组件里的方法。就需要用到我们的.native修饰器了。
现在我们把我们的add按钮封装成组件:
- 声明btn对象
var btn={ template:`<button>组件Add</button>` }
- 在构造器里声明
components:{ "btn":btn }
- 用.native修饰器来调用构造器里的add方法
<p><btn @click.native="add(3)"></btn></p>
- 示例代码
-
<!DOCTYPE html> <html lang="en"> <head> <title>methods options</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>methods options</h1> <hr> <div id="app"> {{a}} <p><button @click="add(2,$event)">add</button></p> <p><btn @click.native="add(2,$event)"></btn></p> </div> <script type="text/javascript"> var btn={ template:`<button>组件ADD</button>` } var app = new Vue({ el: '#app', data: { a: 1 }, components:{ "btn":btn }, methods: { add:function(num,event){ if (num!=null) { this.a+=num } else { this.a++; } console.log(event); } }, }) </script> </body> </html>
- 效果展示
4.3.4、作用域外部调用构造器里的方法
这种不经常使用,如果你出现了这种情况,说明你的代码组织不够好。
<button onclick="app.add(4)" >外部调用构造器里的方法</button>
4.4、Watch 选项 监控数据
数据变化的监控经常使用,我们可以先来看一个简单的数据变化监控的例子。例如天气预报的穿衣指数,它主要是根据温度来进行提示的,当然还有其它的,咱们就不考虑了。
4.4.1、看一个监控变化的案例
温度大于26度时,我们建议穿T恤短袖,温度小于26度大于0度时,我们建议穿夹克长裙,温度小于0度时我们建议穿棉衣羽绒服。
先来模拟一个温度变化的情况:我们使用按钮来加减温度。
示例代码:
<!DOCTYPE html> <html lang="en"> <head> <title>watch Option 监控数据</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>watch Option 监控数据</h1> <hr> <div id="app"> <p>温度显示:{{wendu}}°</p> <p>穿衣建议:{{chuanyi}}</p> <p><button @click="shenggao">升高温度</button><button @click="jiangdi">降低温度</button></p> </div> <script type="text/javascript"> var chuanyiarray = ["T恤短袖", "夹克长裙", "棉衣羽绒服"]; var app = new Vue({ el: '#app', data: { wendu: 14, chuanyi: "夹克长裙" }, methods: { shenggao: function () { this.wendu += 5; }, jiangdi: function () { this.wendu -= 5; } }, watch: { wendu: function (newVal, oldVal) { //这里的温度是监控的对象的名称 if (newVal > 26) { this.chuanyi = chuanyiarray[0]; } else if (newVal >= 0 && newVal <= 26) { this.chuanyi = chuanyiarray[1]; } else { this.chuanyi = chuanyiarray[2] } } }, }) </script> </body> </html>
效果展示:
4.4.2、用实例属性写watch监控
有些时候我们会用实例属性的形式来写watch监控。也就是把我们watch卸载构造器的外部,这样的好处就是降低我们程序的耦合度,使程序变的灵活。
app.$watch('xxx',function(){})
还是上边的案例我们改成实例方法的模式。
//在外部进行watch监控 app.$watch("wendu",function(newVal, oldVal){ if (newVal > 26) { this.chuanyi = chuanyiarray[0]; } else if (newVal >= 0 && newVal <= 26) { this.chuanyi = chuanyiarray[1]; } else { this.chuanyi = chuanyiarray[2] } })
全部代码:
<!DOCTYPE html> <html lang="en"> <head> <title>watch Option 监控数据</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="../assets/js/vue.js"></script> </head> <body> <h1>watch Option 监控数据</h1> <hr> <div id="app"> <p>温度显示:{{wendu}}°</p> <p>穿衣建议:{{chuanyi}}</p> <p><button @click="shenggao">升高温度</button><button @click="jiangdi">降低温度</button></p> </div> <script type="text/javascript"> var chuanyiarray = ["T恤短袖", "夹克长裙", "棉衣羽绒服"]; var app = new Vue({ el: '#app', data: { wendu: 14, chuanyi: "夹克长裙" }, methods: { shenggao: function () { this.wendu += 5; }, jiangdi: function () { this.wendu -= 5; } } }) //在外部进行watch监控 app.$watch("wendu",function(newVal, oldVal){ if (newVal > 26) { this.chuanyi = chuanyiarray[0]; } else if (newVal >= 0 && newVal <= 26) { this.chuanyi = chuanyiarray[1]; } else { this.chuanyi = chuanyiarray[2] } }) </script> </body> </html>
效果展示:
4.5、Mixins 混入选项操作
Mixins一般有两种用途:
- 在你已经写好了构造器后,需要增加方法或者临时的活动时使用的方法,这时用混入会减少源代码的污染。
- 很多地方都会用到的公用方法,用混入的方法可以减少代码量,实现代码重用。
4.5.1、Mixins的基本用法
我们现在有个数字点击递增的程序,假设已经完成了,这时我们希望每次数据变化时都能够提示:“数据发生变化”.
示例代码:
<!DOCTYPE html> <html lang="en"> <head> <title>Mixins Option 混入</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
</head> <body> <h1>Mixins Option 混入</h1> <hr> <div id="app"> <p>num:{{ num }}</p> <P><button @click="add">增加数量</button></P> </div> <script type="text/javascript"> //额外临时加入时,用于显示日志 var addConsole = { updated: function () { alert("数据放生变化,变化成" + this.num + "."); } } var app = new Vue({ el: '#app', data: { num: 1 }, methods: { add: function () { this.num++; } }, mixins: [addConsole] //混入 }) </script> </body> </html>
4.5.2、mixins的调用顺序
从执行的先后顺序来说,都是混入的先执行,然后构造器里的再执行,需要注意的是,这并不是方法的覆盖,而是被执行了两边。
在上边的代码的构造器里我们也加入了updated的钩子函数:
updated: function () { alert("我是原生的Update"); },
这时控制台输出的顺序是:
数据放生变化,变化成2. 我是原生的Update
PS:当混入方法和构造器的方法重名时,混入的方法无法展现,也就是不起作用。
4.5.3、全局API混入方式
我们也可以定义全局的混入,这样在需要这段代码的地方直接引入js,就可以拥有这个功能了。我们来看一下全局混入的方法:
Vue.mixin({ updated() { alert("我是全局的混入的Update"); }, })
代码示例:
<!DOCTYPE html> <html lang="en"> <head> <title>Mixins Option 混入</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
</head> <body> <h1>Mixins Option 混入</h1> <hr> <div id="app"> <p>num:{{ num }}</p> <P><button @click="add">增加数量</button></P> </div> <script type="text/javascript"> //额外临时加入时,用于显示日志 var addConsole = { updated: function () { alert("数据放生变化,变化成" + this.num + "."); } } Vue.mixin({ updated() { alert("我是全局的混入的Update"); }, }) var app = new Vue({ el: '#app', data: { num: 1 }, methods: { add: function () { this.num++; } }, updated: function () { alert("我是原生的Update"); }, mixins: [addConsole] //混入 }) </script> </body> </html>
效果展示:
PS:全局混入的执行顺序要前于混入和构造器里的方法。
4.6、Extends Option 扩展选项
通过外部增加对象的形式,对构造器进行扩展。它和我们上节课讲的混入非常的类似。
4.6.1、extends我们来看一个扩展的实例
<!DOCTYPE html> <html lang="en"> <head> <title>extends Option 扩展选项</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
</head> <body> <h1>extends Option 扩展选项</h1> <hr> <div id="app"> <p>num:${ num }</p> <P><button @click="add">增加数量</button></P> </div> <script type="text/javascript"> var extendsObj = { updated: function () { alert("我是扩展的update"); }, methods:{ add: function () {//扩展的方法重名的话不执行 alert("我是扩展的方法"); this.num++; } } } var app = new Vue({ el: '#app', data: { num: 1 }, methods: { add: function () { alert("我是原生的方法"); this.num++; } }, updated: function () { alert("我是原生的Update"); }, extends:extendsObj, delimiters:["${","}"], }) </script> </body> </html>
4.6.2、delimiters 选项
delimiters的作用是改变我们插值的符号。Vue默认的插值是双大括号{{}}。但有时我们会有需求更改这个插值的形式。
delimiters:['${','}']
现在我们的插值形式就变成了${}。
效果展示:
5、实例和内置组件
5.1、Vue和Jquery.js一起使用
5.1.1、下载并引入jquery框架
下载可以去官网进行下载,我这里使用的版本是3.3.1,下载好后在需要的页面引入就可以了。当然你还有很多其它的方法引入jquery,只要可以顺利引入就可以了。
<script type="text/javascript" src="jquery-3.3.1.min.js"></script>
试着作一个案例,在DOM被挂载后修改里边的内容。
<!DOCTYPE html> <html lang="en"> <head> <title>example methods 实例</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
</head> <body> <h1>example methods 实例</h1> <hr> <div id="app"> {{message}} </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { message: "hello world!" }, mounted() { $("#app").html("我是Jquery~!") }, methods: { add: function () { alert("调用了构造器内部的Add方法"); } } }) </script> </body> </html>
现在页面显示是:我是jQuery,而不是hello Vue了。
5.1.2、实例调用自定义方法
在Vue的构造器里我们写一个add方法,然后我们用实例的方法调用它。
构造器里的add方法:
methods: { add: function () { alert("调用了构造器内部的Add方法"); } }
实例调用:
app.add();
PS:我们有可能把app.add()的括号忘记或省略,这时候我们得到的就是方法的字符串,但是并没有执行,所以必须要加上括号。
效果展示:
5.2、实例方法
-
$mount 方法
$mount方法是用来挂载我们的扩展的,我们可以用 $mount 的方法把扩展挂载到DOM上 -
$destroy() 卸载方法
-
$forceUpdate() 更新方法
-
$nextTick() 数据修改方法
当Vue构造器里的data值被修改完成后会调用这个方法,也相当于一个钩子函数吧,和构造器里的updated生命周期很像。 - 代码示例
-
<!DOCTYPE html> <html lang="en"> <head> <title>example methods 实例</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
</head> <body> <h1>example methods 实例</h1> <hr> <div id="app"> </div> <p><button onclick="destroy()">卸载</button></p> <p><button onclick="reload()">刷新</button></p> <p><button onclick="tick()">更改数据</button></p> <script type="text/javascript"> var jsextend = Vue.extend({ template: `<p>{{message}}</p>`, data: function () { return { message: "Hellow World!" } }, mounted() { console.log("mounted 被创建"); }, destroyed() { console.log("destroyed 销毁之后"); }, updated() { console.log("updated 更新之后"); }, }) var vm = new jsextend().$mount("#app"); function destroy() { vm.$destroy(); } function reload() { vm.$forceUpdate() } function tick() { vm.message = "update message info "; vm.$nextTick(function () { console.log('message更新完后我被调用了'); }) } </script> </body> </html>
- 效果展示
5.3、实例事件
实例事件就是在构造器外部写一个调用构造器内部的方法。这样写的好处是可以通过这种写法在构造器外部调用构造器内部的数据。
我们还是写一个点击按钮,持续加1的例子。
- $on 在构造器外部添加事件。
app.$on('reduce',function(){ console.log('执行了reduce()'); this.num--; });
$on 接收两个参数,第一个参数是调用时的事件名称,第二个参数是一个匿名方法。
-
如果按钮在作用域外部,可以利用 $emit 来执行。
//外部调用内部事件 function reduce(){ app.$emit('reduce'); }
- $once 执行一次的事件
app.$once('reduceOnce',function(){ console.log('只执行一次的方法'); this.num--; });
- $off 关闭事件
//关闭事件 function off(){ app.$off('reduce'); }
- 代码示例
-
<!DOCTYPE html> <html lang="en"> <head> <title>example methods 实例</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge">
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
</head> <body> <h1>example methods 实例</h1> <hr> <div id="app"> {{num}} <p><button @click="add">Add</button></p> </div> <p><button onclick="reduce()">reduce</button></p> <p><button onclick="reduceOnce()">reduceOnce</button></p> <p><button onclick="off()">off</button></p> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { num: 1 }, methods: { add: function () { this.num++; } } }) app.$on("reduce", function () { this.num--; }) app.$once("reduceOnce", function () { this.num--; }) function reduce() { app.$emit("reduce"); } function reduceOnce() { app.$emit("reduceOnce"); } //关闭事件 function off() { app.$off('reduce'); } </script> </body> </html>
- 效果展示
5.4、内置组件 -slot讲解
先来定义一个的组件,这个组件用来显示博主的一些信息。
我们在Vue 构造器里的data中给出了信息,信息如下:(博客地址,网名,使用技能)
data: { jsData: {
blogUrl: "https://www.cnblogs.com/h-z-y/", netName: "hzy", skill: "web前端"
} },
我们用 <template></template> 标签的方式定义了组件:
<template id="tep"> <div> <p>博客地址:<slot name="blogUrl"></slot></p> <p>网名:<slot name="netName"></slot></p> <p>技术类型:<slot name="skill"></slot></p> </div> </template>
我们现在就可以用slot功能让组件接收传递过来的值,并在模板中接收显示。
slot的使用需要两步:
- 在HTML的组件中用slot属性传递值。
<jscomponent> <span slot="blogUrl">{{jsData.blogUrl}}</span> <span slot="netName">{{jsData.netName}}</span> <span slot="skill">{{jsData.skill}}</span> </jscomponent>
- 在组件模板中用标签接收值。
-
<template id="tep"> <div> <p>博客地址:<slot name="blogUrl"></slot></p> <p>网名:<slot name="netName"></slot></p> <p>技术类型:<slot name="skill"></slot></p> </div> </template>
- 全部代码
-
<!DOCTYPE html> <html lang="en"> <head> <title>slot content extend 实例</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
</head> <body> <h1>lot content extend 实例</h1> <hr> <div id="app"> <jscomponent> <span slot="blogUrl">{{jsData.blogUrl}}</span> <span slot="netName">{{jsData.netName}}</span> <span slot="skill">{{jsData.skill}}</span> </jscomponent> </div> <template id="tep"> <div> <p>博客地址:<slot name="blogUrl"></slot></p> <p>网名:<slot name="netName"></slot></p> <p>技术类型:<slot name="skill"></slot></p> </div> </template> <script type="text/javascript"> var jscmp = { template: "#tep", } var app = new Vue({ el: '#app', data: { jsData: { blogUrl: "https://www.cnblogs.com/h-z-y/", netName: "hzy", skill: "web前端" } }, components: { "jscomponent": jscmp } }) </script> </body> </html>
- 效果展示