Vue.js是通过new Vue({...})来声明一个实例的,在这个实例中包含了当前页面的HTML结构、数据和事件。
Vue实例是MVVM模式中的ViewModel,实现了数据和视图的双向绑定。
在实例化时可以传入一个选项对象,它包含数据、模板、挂载元素、方法、生命周期钩子函数等选项。
el是element的简写,用来和DOM元素进行绑定,对应的是DOM元素的id属性值(类似id选择器)。
用法如下:
1 2 3 4 5 6 |
<div id="xxx"></div> <script> var vm = new Vue({ el: "#xxx" // xxx为id名 }) </script> |
在Vue实例中初始化的data中的所有数据会自动进行监听绑定,可以使用两个大括号 {{}} 来绑定data中的数据。
用法如下:
1 2 3 4 5 6 7 8 9 |
<div id="xxx"></div> <script> var vm = new Vue({ el: "#xxx", data: { 健: 值 } }) </script> |
健为属性的名称,值为初始值。
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 |
<div id="app"> <h2>{{message}}</h2> <input type="text" v-model="message"> </div> <script> var vm = new Vue({ el: "#app", data: { message: "橘猫吃不胖" } }) </script> |
如果在输入框中输入其他内容,h2标签也会显示该内容,vue与h2标签的绑定是单向的,与input标签的绑定是双向的。
注:data中的数据都是浅拷贝。这意味着,如果修改原来的对象也会改变data,从而触发更新事件。
computed是计算属性,当我们要用到的属性不存在,需要通过已有属性计算得来,这时使用计算属性。computed底层借助了Object.defineproperty方法提供的getter和setter来实现。
使用方法可以跟data中的属性一样使用,注意用的时候不要加“()”。
它是data属性的补充。在进行数据绑定的时候,对数据要进行一定的处理才能展示到HTML页面上。
虽然Vue提供了非常好的表达式绑定方法,但是只能应对低强度的需求。
用法如下:
1 2 3 4 5 6 7 8 9 |
<div id="xxx"></div> <script> var vm = new Vue({ el: "#xxx", computed: { 方法名: function () {} } }) </script> |
例如,把一个日期按照规定格式进行输出,可能就需要对日期对象做一些格式化。
Vue提供的计算属性(computed)允许开发者编写一些方法,协助进行绑定数据的操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<div id="app"> <table> <tr> <td>姓名:</td> <td>{{name}}</td> </tr> <tr> <td>生日:</td> <td>{{getBirthday}}</td> </tr> </table> </div> <script> var vm = new Vue({ el: "#app", data: { name: "橘猫吃不胖", birthday: 1014228510514 // 传了一个毫秒数 }, computed: { // 计算属性,对data中的数据进行处理 getBirthday: function () { // getBirthday就是表格中的{{getBirthday}},其本质是一个属性 let date = new Date(this.birthday); return date.getFullYear() + "年" + (date.getMonth() + 1) + "月" + date.getDate() + "日"; } } }) </script> |
每一个计算属性都包含一个getter和一个setter。
上面的示例是计算属性的默认用法, 只是利用了getter来读取。在需要时,也可以提供一个setter函数, 当手动修改计算属性的值就像修改一个普通数据那样时,就会触发setter函数,执行一些自定义的操作。
getter函数执行的时机:
(1)初次读取时会执行一次
(2)当依赖的数据发生改变时会被再次调用
计算属性computed优势:与methods实现相比,它的内部有缓存机制,计算属性只有在它相关依赖发生改变时才会重新求值,效率更高,调试方便。
注意:
(1)计算属性最终会出现在Vue实例vm上,直接读取使用即可
(2)如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
示例:在输入框中分别输入姓和名,最后将全名显示在页面上,感受getter方法;在控制台中修改全名,感受setter方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<div id="app"> 姓:<input type="text" v-model="xing"><br><br> 名:<input type="text" v-model="ming"><br><br> 你的姓名是:{{fullName}} </div> <script> var vm = new Vue({ el: "#app", data: { xing: "", // 初始值为空 ming: "" }, computed: { fullName: { get() { return this.xing + "-" + this.ming; // 返回值为全名 }, set(value) { let arr = value.split("-"); this.xing = arr[0]; this.ming = arr[1]; } } } }) </script> |
如下所示,在输入框中输入姓和名,会将全名显示在下方。
如果在控制台中修改全名,会修改掉输入框中的值。
methods需要搭配v-on指令来监听DOM事件,我们在methods对象中定义方法,最终会在Vue实例上,其中的this会指向Vue的实例vm,因此其中配置的函数不可以使用箭头函数,否则会改变this的指向。
用法如下:
1 2 3 4 5 6 7 8 9 |
<div id="xxx"></div> <script> var vm = new Vue({ el: '#xxx', methods: { 方法名: function () { } } }) </script> |
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<div id="app"> <p>原始字符串:"{{ message }}"</p> <p>反向字符串:"{{ reversedMessage()}}"</p> </div> <script> var vm = new Vue({ el: '#app', data: { message: '橘猫吃不胖' }, methods: { reversedMessage: function () { return this.message.split('').reverse().join('') } } }) </script> |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<div id="wrap"> <p>你的名字是{{list.name}}</p> </div> <script> var list = { name: "donna", age: 20 } var vm = new Vue({ el: "#wrap", data: { list } }); </script> |
先定义字符串模板,然后在vue 的选项对象里面利用template绑定。字符串模板的优先级会比html模板高,如果html和字符串模板中都有内容,会用字符串模板里的内容替换html模板。需要注意的是定义的字符串模板中根节点只能有一个。还有字符串用 ` 引起来是可以换行的。
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 |
<div id="app"></div> <script> let obj = { content: "橘猫吃不胖" } let str = `<div>Hello {{content}}</div>`; new Vue({ el: "#app", data: obj, template: str }) </script> |
除了用变量定义模板字符串,还可以用script标签,给script 标签定义id,根节点只能有一个,将html结构写在一对script标签中,设置type=“x-template”,模板将会替换挂载的元素。挂载元素的内容都将被忽略。Vue实例的template属性设置为给定的script标签
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<div id="app"></div> <script type="x-template" id="test"> <div> <p>姓名:{{obj.name}}</p> </div> </script> <script> let obj = { name: "张三" } new Vue({ el: "#app", data: { obj }, template: "#test" }) </script> |
1 2 3 |
render(createElement){ createElement(标签名,[数据对象],子元素)//子元素为数组或对象 } |
数据对象的属性:
1 2 3 4 5 |
class:{ }, //绑定class style:{ }, //绑定样式, attrs:{ }, //添加行间属性 domProps:{ }, //DOM元素属性 on:{ }, //绑定事件 |
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<div id="app"></div> <style> .bg { background-color: pink; } </style> <script> new Vue({ el: "#app", render(createElement) { return createElement( "ul", { class: { bg: true }, style: { listStyle: "none" }, attrs: { name: "tt" } }, [ createElement("li", "苹果"), createElement("li", "香蕉"), createElement("li", "橘子") ] ) } }) </script> |
watch属性用来观察和响应Vue实例上的数据变动,watch属性是一个配置对象,它有两个属性:一个是键,一个是值。
键是需要观察的表达式,值可以为以下形式:
选项 | 说明 |
---|---|
immediate | 在初始化时立即调用回调函数handler。第一次调用时,旧值将为undefined |
deep | 如果源是对象或数组,则强制深度遍历源,以便在深度变更时触发回调 |
flush | 调整回调的刷新时机 |
onTrack / onTrigger | 调试侦听器的依赖关系 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
new Vue({ ... watch: { // 值为回调函数形式,newVal表示新的值,oldVal表示旧的值 要监视的数据: function (newVal, oldVal) { } // 值为方法名形式: 要监视的数据: "methods中声明的方法名" // 值为包含额外选项的对象: 要监视的数据: { immediate: xxx, handler(newVal, oldVal) {}, deep: xxx, } } }) |
示例:点击按钮给属性a做减法,监听新值与旧值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<div id="app"> <button @click="a--">减1</button> <p>{{message}}</p> </div> <script> new Vue({ el: "#app", data: { a: 10, message: " ", }, watch: { a: function (val, oldVal) { this.message = "a的原值是:" + oldVal + ",a的新值是:" + val; } } }) </script> |
或者使用Vue实例中的$watch(),也可以达到监视效果,该方法的返回值是一个取消观察函数,用来停止触发回调,用法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// 完整形式 const vm = new Vue({ }) // unwatch:取消观察函数 let unwatch = vm.$watch("要监视的对象", { immediate: true, // 配置一些属性 ... handler(newVal, oldVal) { // 回调函数 unwatch(); // 停止监听对象 } }) // 简写形式 const vm = new Vue({ }) // unwatch:取消观察函数 let unwatch = vm.$watch("要监视的对象", function (newVal, oldVal) {} }) |
示例:点击按钮给属性a做减法,监听新值与旧值。当值为5时,停止监听。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<div id="app"> <button @click="a--">减1</button> <p>{{message}}</p> </div> <script> const vm = new Vue({ el: "#app", data: { a: 10, message: " ", } }) let unwatch = vm.$watch("a", { handler(val, oldVal) { if (val === 5) { unwatch(); } this.message = "a的原值是:" + oldVal + ",a的新值是:" + val; } }) </script> |
computed与watch的区别
条件渲染分为两种方式,一种是v-if,另一种是v-show。v-if又分为单路分支、双路分支和多路分支。只有if后面的值为true时才会有DOM元素,为false时不会有DOM元素
1、v-if方式渲染:在<template>中配合v-if渲染,在使用v-if控制元素的时候,需要将它添加到这个元素上。然而,如果需要切换很多元素时,一个一个添加比较麻烦。这时,可以使用<template></template>将一组元素进行包裹
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<div id="app"> <template v-if="yes"> <h2>vue</h2> </template> </div> <script> var vm = new Vue({ el: "#app", data: { yes: true } }) </script> |
2、v-show方式渲染:用法与v-if大致相同
列表渲染用v-for指令根据一组数据的选项列表进行渲染。v-for指令需要采用item in items 形式的特殊语法,其中items是源数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<div class="app"> <ul> <li v-for="item in items">{{item.text}}</li> </ul> </div> <script> new Vue({ el: '.app', data: { items: [ { text: 'Name'}, { text: 'Age'}, { text: 'Like'} ] } }) </script> |
可以使用v-for迭代对象的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<div class="app"> <ul> <li v-for="item in obj">{{item}}</li> </ul> </div> <script> new Vue({ el: '.app', data: { obj: { firstname: '欧阳', lastname: '静静', age:18 } } }) </script> |