一、计算属性
1、案例引入
实现如下效果 当姓和名变化时 全名跟着变化
2、使用插值语法实现和methods实现
<body> <div id="root"> 姓<input v-model="firstName" type="text"> 名<input v-model="lastName" type="text"> <!--使用插值语法实现--> 全名<span>{{firstName}}{{lastName}}</span> <!--使用methods实现 vue当数据发生变化 模板重新渲染加载 数据也会重新更新--> 全名<span>{{fullName()}}</span> </div> <script> const vm = new Vue({ el:"#root", data:{ firstName:"", lastName:"" }, methods:{ fullName(){ return this.firstName+this.lastName } } }) </script> </body>
上面案例插入语法缺点
vue官网风格指南强烈建议插值语法保持简介
3、计算属性定义
要用的属性不存在 要通过已有属性计算得出
4、原理
通过object.defineproperty方法提供的getter和setter
5、优点
和methods对象实现相比 有缓存机制 效率更高 调试方便
备注:计算属性最终出现在vm上 直接读取即可
<body> <div id="root"> 姓<input v-model="firstName" type="text"> 名<input v-model="lastName" type="text"> 全名<span>{{fullName}}</span> </div> <script> const vm = new Vue({ el:"#root", data:{ firstName:"", lastName:"" }, methods:{ }, /*1、fullName属性通过函数计算出的新属性 fullName也在vm对象上 * 2、功能:当有人读取fullName时 get且返回值作为fullName值 * 3、会做缓存处理,初次读取和所依赖的数据发生变化时get调用*/ computed:{ fullName:{ get(){ return this.firstName+this.lastName }, /*当新属性被修改时候调用*/ set(){ } } } }) </script> </body>
6、计算属性简写方式
确定计算属性只读不写时候才能简写
<body> <div id="root"> 姓<input v-model="firstName" type="text"> 名<input v-model="lastName" type="text"> 全名<span>{{fullName}}</span> </div> <script> const vm = new Vue({ el:"#root", data:{ firstName:"", lastName:"" }, methods:{ }, computed:{ //简写方式 看着是个函数 实际是个属性 fullName(){ return this.firstName+this.lastName; } } }) </script> </body>
二、监视属性
1、定义
监视某一个属性的变化,只有当监视的属性存在才能监视
2、两种写法
<body> <div id="root"> <span>天气{{info}}</span> <button @click="changeWeather">切换</button> </div> <script> const vm = new Vue({ el:"#root", data:{ isHot:true }, methods:{ changeWeather(){ this.isHot = !this.isHot } }, computed:{ info(){ return this.isHot ? '炎热':'凉爽' } }, /*第一种写法:创建实列就已经知道要监视哪个属性就用这种方法*/ watch:{ //不仅可以监听data中属性 也可以监视计算属性info isHot:{ immediate:true,//初始化就调用一下handler //当ishot发生变化时调用handler handler(newValue,oldValue){ console.log(newValue,oldValue); } } }, }); /*第二种写法:当用户行为发生变化时候才监视用这种*/ vm.$watch('isHot',{ immediate:true, handler(newValue,oldValue){ console.log(newValue,oldValue); } }) </script> </body>
3、深度监视
vue中的watch默认不监测对象内部值得变化(一层)
配置deep:true可以监测对象内部值得变化(多层)
<body> <div id="root"> <span>{{num.a}}</span> <button @click="num.a++">切换</button> </div> <script> const vm = new Vue({ el:"#root", data:{ num:{ a:1, b:2 } }, methods:{ }, watch:{ /*监视多级结构中某个属性变化*/ 'num.a':{ handler(newValue,oldValue){ console.log(newValue,oldValue); } }, /*监视多级中所有属性变化*/ num: { deep:true, handler(newValue,oldValue){ console.log(newValue,oldValue); } } }, }); </script> </body>
备注:
vue自身是可以监测对象内部值得改变 但vue提供得watch默认不可以
使用watch需要根据数据结构得变化决定是否采用监视
4、简写
<body> <div id="root"> <span>{{num.a}}</span> <button @click="num.a++">切换</button> </div> <script> const vm = new Vue({ el:"#root", data:{ isHot:true }, methods:{ }, watch:{ /*当不用配置deep和immediate时监视可以简写如下*/ isHot(newValue,oldValue){ console.log(newValue,oldValue) } } }); /*当不用配置deep和immediate时监视可以简写如下*/ vm.$watch('isHot',function (newValue,oldValue) { console.log(newValue,oldValue) }) </script> </body>
5、计算属性和监视属性对比
1、computed能完成的功能 watch都可以完成
2、watch能完成的功能 computed不一定能完成 例如watch可以进行异步操作
3、所有被vue管理的函数最好写成普通函数,别用箭头函数,这样this的指向才是vm
4、所有不被vue管理的函数(定时器函数、ajax回调函数、promise回调函数)最好携程箭头函数 这样this指向才是vm或者组件实列对象
三、样式绑定
1、通过class绑定样式(三种方式)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> <style> .basic{ width: 200px; height: 200px; } .active1{ background-color: rosybrown; } .active2{ border-radius: 20px; } .active3{ border-color: green; background-color: red; } </style> </head> <body> <div id="root"> <!--字符串写法:适用于样式的类名不确定需要动态指定--> <div class="basic" :class="one"></div> <!--数组写法:适用于要绑定的样式个数不确定 名字也不确定--> <div class="basic" :class="two"></div> <!--对象写法:适用于要绑定的样式个数确定 名字也确定 但要动态决定用不用--> <div class="basic" :class="three"></div> </div> <script> const vm = new Vue({ el:"#root", data:{ one:'active1', two:['active1','active2'], three:{ active2:true, active3:true } }, }); </script> </body> </html>
2、通过style绑定样式(2种)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> <style> .basic{ width: 200px; height: 200px; } .active1{ background-color: rosybrown; } .active2{ border-radius: 20px; } .active3{ border-color: green; background-color: red; } </style> </head> <body> <div id="root"> <!--对象写法--> <div class="basic" :style="styleObj">222</div> <!--数组写法--> <div class="basic" :style="styleArr">333</div> </div> <script> const vm = new Vue({ el:"#root", data:{ one:'active1', two:['active1','active2'], styleObj:{ borderRadius:"20px", backgroundColor:"red" }, styleArr:[ { borderRadius:"20px", backgroundColor:"red" }, { fontSize:"20px", padding:"20px" } ] }, }); </script> </body> </html>
四、条件渲染和列表渲染
1、条件渲染
1.1、v-show语法
1、底层使用的是display实现,仅仅时样式的移除
<body> <div id="root"> <!--直接写表达式--> <div v-show="true">{{name}}</div> <!--通过属性控制--> <div v-show="flag">{{name}}</div> </div> <script> const vm = new Vue({ el:"#root", data:{ name:'hello', flag:true }, }); </script> </body>
1.2、v-if语法
1、v-if条件渲染时不展示dom的元素直接移除,而不是使用display隐藏
2、v-if可以和v-else-if、v-else一起使用 但要求结构不能被打断
3、template只能配置v-if使用(使用template不会破坏原来的元素结构)
html结构直接删掉
<body> <div id="root"> <!--直接写表达式--> <div v-show="true">{{name}}</div> <!--通过属性控制--> <div v-show="flag">{{name}}</div> </div> <script> const vm = new Vue({ el:"#root", data:{ name:'hello', flag:true }, }); </script> </body>
1.3、比较
1. 如果需要频繁切换 v-show 较好 因为节点在只是隐藏了
2. 当条件不成立时, v-if 的所有子节点不会解析
2、列表渲染
2.1、v-for
v-for指令用于展示列表数据,语法:v-for="(item,index) in xxx" :key="yyy"
可以遍历数组、对象、字符串、指定次数
<body> <div id="root"> <div> <!--遍历数组--> <h2 v-for="(item,index) in arr">{{item}}--{{item.id}}--{{item.name}}--{{index}}</h2> <!--遍历对象--> <h2 v-for="(value,key) in obj" >{{key}}--{{value}}</h2> <!--遍历字符串--> <h2 v-for="(item,index) in str" >{{item}}--{{index}}</h2> <!--遍历指定次数--> <h2 v-for="(number,index) of 5" >{{number}}--{{index}}</h2> </div> </div> <script> const vm = new Vue({ el:"#root", data:{ arr:[ { id:1, name:'一' }, { id:2, name:'二' }, { id:3, name:'三' } ], obj:{ id:1, age:12, name:'张三', sex:'男' }, str:'hello', }, }); </script> </body>
2.2、key的作用和原理
3、列表过滤
案例截图,输入关键字模糊展示
3.1、使用监视属性实现
<body> <div id="root"> <input v-model="keyWord"> <ul> <li v-for="(item,index) in filPersons" :key="item.id">{{item.id}}-年龄{{item.age}}-{{item.name}}</li> </ul> </div> <script> const vm = new Vue({ el:"#root", data:{ keyWord:'', persons:[ {id:1, name:'张三',age:10}, {id:2, name:'李四',age:20}, {id:3, name:'王五',age:30} ], filPersons:[] }, watch:{ keyWord:{ immediate:true, handler(val){ this.filPersons = this.persons.filter((p)=>{ /*indexOf(str)没有找到返回-1 找到返回下表位置,如果var是''即空字符串, 则返回0即每个字符串都包含空字符串在开头*/ return p.name.indexOf(val)!== -1; }) } } } }); </script> </body>
3.2、使用计算属性实现
<body> <div id="root"> <input v-model="keyWord"> <ul> <li v-for="(item,index) in filPersons" :key="item.id">{{item.id}}-年龄{{item.age}}-{{item.name}}</li> </ul> </div> <script> const vm = new Vue({ el:"#root", data:{ keyWord:'', persons:[ {id:1, name:'张三',age:10}, {id:2, name:'李四',age:20}, {id:3, name:'王五',age:30} ], }, computed:{ filPersons(){ return this.persons.filter((p)=>{ return p.name.indexOf(this.keyWord) !== -1 }) } } }); </script> </body>
当计算属性和监视都能实现的时候优先选择计算属性
4、列表排序
<body> <div id="root"> <input v-model="keyWord" type="text" placeholder="输入关键字查询"> <button @click="sortType = 2">年龄升序</button> <button @click="sortType = 1">年龄降序</button> <button @click="sortType = 0">原顺序</button> <ul> <li v-for="(item,index) in filPersons" :key="item.id">{{item.id}}-年龄{{item.age}}-{{item.name}}</li> </ul> </div> <script> const vm = new Vue({ el:"#root", data:{ keyWord:'', sortType:0, persons:[ {id:1, name:'张三',age:10}, {id:2, name:'李四',age:20}, {id:3, name:'张二三',age:90}, {id:4, name:'王五',age:30} ], }, computed:{ filPersons(){ const arr = this.persons.filter((p)=>{ return p.name.indexOf(this.keyWord) !== -1 }); //只要sort不是0 都是true if(this.sortType){ //sort会改变原数组 filter不会改变原数组 arr.sort((pre,next)=>{ //sort降序用后一个元素减去前一个元素即可 升序用前一个元素减去后一个元素 return this.sortType === 1 ? next.age-pre.age : pre.age-next.age }); } return arr; } } }); </script> </body>
五、内置指令
1、v-text
向其所在的节点中渲染文档内容;会替换掉其他节点中的内容,但是插值语法表达式不会
2、v-html
向指定节点渲染包含html结构的内容
v-html有安全问题容易导致xss攻击,一定要在可信的内容使用v-html 不要在用户提交的内容
3、v-if
如果为 true, 当前标签才会输出到页面
4、v-else
如果为 false, 当前标签才会输出到页面
5、v-show
通过控制 display 样式来控制显示/隐藏
6、v-for
遍历数组/对象
7、v-on
绑定事件监听, 一般简写为@
8、v-bind
绑定解析表达式, 可以省略 v-bind
9、v-model
双向数据绑定
10、v-cloak
配合css解决由于网速慢是在页面展示{{xx}}问题
正常的html+js+css页面如下 是从头往下渲染的
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!--如果加载这个资源花了5s(浏览器设置网速模拟) 那么前5s是空白界面 然后从上而下加载页面 这个称为页面的阻塞 --> <script src="http://xxx/js/vue.js"></script> </head> <body> <div id="root"> <span>你好</span> </div> <script> const vm = new Vue({ el:"#root", data:{ name:'<h3>你好</h3>' }, }); </script> </body> </html>
上面也是可以正常运行的
但是js位置也可以放在body中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> /*设置有v-clock属性的元素样式 v-clock在vue接管元素后自动消失*/ [v-clock]{ display: none; } </style> </head> <body> <div id="root"> <span v-clock>{{name}}</span> </div> <script src="http://xxx/js/vue.js"></script> </body> <script> const vm = new Vue({ el:"#root", data:{ name:'<h3>你好</h3>' }, }); </script> </html> 11、v-once
初次动态渲染后就视为静态内容,以后的数据改变不会引起v-once所在结构的更新可以用于优化性能
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="root"> <span v-once>初始值{{num}}</span> <span>当前值{{num}}</span> <button @click="num++">num+1</button> </div> <script src="js/vue.js"></script> </body> <script> const vm = new Vue({ el:"#root", data:{ num:1 }, }); </script> </html> 12、v-pre
v-pre不会编译当前元素
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="root"> <span>固定的没有指令的可以加v-pre优化性能</span> <span v-pre>{{num}}有指令的不能加v-pre</span> </div> <script src="js/vue.js"></script> </body> <script> const vm = new Vue({ el:"#root", data:{ num:1 }, }); </script> </html>
六、vue生命周期
- 初始化显示
- beforeCreate()
- created()
- beforeMount()
- mounted()
- 更新状态: this.xxx = value
- beforeUpdate()
- updated()
- 销毁 vue 实例: vm.$destory()
- beforeDestory()
- destoryed()
七、插件
作用
对vue增加作用,本质是一个{}对象,但是要求这个对象必须包含install(安装)方法,所以可以自定义插件
定义
export default { /*vue会自动调用 可以带参数 这个Vue参数就是vm的缔造者即vue构造函数*/ install(Vue,x,y,z){ console.log(x,y,z) //全局过滤器 Vue.filter('mySlice',function(value){ return value.slice(0,4) }) //定义全局指令 Vue.directive('fbind',{ //指令与元素成功绑定时(一上来) bind(element,binding){ element.value = binding.value }, //指令所在元素被插入页面时 inserted(element,binding){ element.focus() }, //指令所在的模板被重新解析时 update(element,binding){ element.value = binding.value } }) //定义混入 Vue.mixin({ data() { return { x:100, y:200 } }, }) //给Vue原型上添加一个方法(vm和vc就都能用了) Vue.prototype.hello = ()=>{alert('你好啊')} } }
引入并使用
main.js中引入并使用
import MyPlugins from "./MyPlugins"; Vue.use(MyPlugins,1,2,3)