Vue.js 第2章 钩子函数&自定义指令&过滤器&计算属性&侦听器
目标
钩子函数
自定义指令
自定义过滤器
计算属性
-
-
为了复用,为了代码的灵活
-
-
指令的分类:全局指令,局部指令
-
在vm外面创建的指令
-
通过Vue.directive来创建
-
-
如何定义自定义指令(不用赋值)
-
Vue.directive(名称,{inserted(el,binding){}})
-
-
如何使用自定义指令(不用赋值)
-
v-名称
-
-
如何定义带值的指令
-
Vue.directive(名称,{inserted(el,binding){binding.value}})
-
-
如何使用需要赋值的指令
-
v-名称='值'
-
需求:我们希望能够在页面加载完成的时候让id文本框获取焦点
-
页面加载完毕就触发:window.onload
-
获取焦点:dom.focus()
-
在vue中有一套完整的生命周期的钩子函数
-
mounted钩子函数,它是一个独立的结构,不要写在methods属性中
-
钩子函数:在某个场景会自动触发的函数
-
-
不建议使用原生dom的方式去获取元素,因为vue就是希望能够将我们从繁琐的dom操作中解脱
-
vue中标记元素可以通过ref (reference)
-
ref='标记值'
-
功能类似于之前的id设置
-
获取值通过this.$refs
-
-
指令:可以实现某种功能,用户可以选择使用
-
什么是全局自定义指令 :在vue实例外创建的指令
-
如何创建全局自定义指令
-
Vue.directive(名称,{inserted钩子函数})
-
inserted钩子函数:在添加指令的元素插入到父节点时触发--说白了就是生成dom树
-
<!DOCTYPE html> <html lang="en"> <head> <title></title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> #app { width: 600px; margin: 10px auto; } .tb { border-collapse: collapse; width: 100%; } .tb th { background-color: #0094ff; color: white; } .tb td, .tb th { padding: 5px; border: 1px solid black; text-align: center; } .add { padding: 5px; border: 1px solid black; margin-bottom: 10px; } </style> <!-- 1.引入js文件 --> <script src="./js/vue2.js"></script> </head> <body> <!-- 4.添加模板结构 --> <div id="app"> <div class="add"> 编号: <input type="text" v-model='id' ref='bid'> 品牌名称: <input type="text" v-model='brandname' ref='bname' v-focus> <input type="button" value="添加" @click='add'> </div> <div class="add"> 品牌名称: <input type="text" placeholder="请输入搜索条件" > </div> <div> <table class="tb"> <thead> <tr> <th>编号</th> <th>品牌名称</th> <th>创立时间</th> <th>操作</th> </tr> </thead> <tbody> <!-- 5.实现循环遍历生成动态结构 --> <tr v-for="(value,index) in brandList"> <td>{{value.id}}</td> <td>{{value.name}}</td> <td>{{value.time}}</td> <td> <a href="#" @click='del(index)'>删除</a> </td> </tr> <!-- 添加提示 --> <!--通过v-show来实现提示信息的合理出现 --> <tr v-show="brandList.length==0"> <td colspan="4">没有任何数据了,请先添加</td> </tr> </tbody> </table> </div> </div> <script> // window.onload = function(){ // } // 1.定义全局自定义指令:全局自定义是指在vm实例定义的指令 // 2.通过Vue.directive来创建自定义指令 // Vue.directive(指令名称,{配置}) Vue.directive('focus',{ inserted(el,binding,vNode){ // 我们需要获取元素并设置聚焦 console.log(el) el.focus() } }) // 2.创建vm实例 var vm = new Vue({ // 3.添加配置 el: '#app', data: { // id号 id:'', // 品牌名称 brandname:'', brandList: [ { "id": 1, name: 'AA', time: new Date() }, { "id": 2, name: 'BB', time: new Date() } ] }, methods:{ // 删除 del(index){ this.brandList.splice(index,1) }, // 添加 add(){ // 生成对象 var newobj = {id:this.id,name:this.brandname,time:new Date()} // 添加到数组 this.brandList.push(newobj) } }, // 添加一个生命周期钩子函数 mounted(){ // 实现元素的自动获取焦点 // document.querySelector('#bid').focus() // console.log(this) // this.$refs可以获取模板中所有拥有ref属性的元素,它是一个对象 // this.$refs.bid.focus() } }) </script> </body> </html>
使用 “v-名称” 来调用全局自定义指令
新的需求:我们需要根据用户的喜好来修改文本颜色
-
-
通过Vue.directive(名称,{inserted(el,binding){}})
-
使用指令的时候:v-名称='值'
<!DOCTYPE html> <html lang="en"> <head> <title></title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> #app { width: 600px; margin: 10px auto; } .tb { border-collapse: collapse; width: 100%; } .tb th { background-color: #0094ff; color: white; } .tb td, .tb th { padding: 5px; border: 1px solid black; text-align: center; } .add { padding: 5px; border: 1px solid black; margin-bottom: 10px; } </style> <!-- 1.引入js文件 --> <script src="./js/vue2.js"></script> </head> <body> <!-- 4.添加模板结构 --> <div id="app"> <div class="add"> 编号: <input type="text" v-model='id' ref='bid' v-setcolor="color"> 品牌名称: <input type="text" v-model='brandname' ref='bname' v-focus > <input type="button" value="添加" @click='add'> </div> <div class="add"> 品牌名称: <input type="text" placeholder="请输入搜索条件" > </div> <div> <table class="tb"> <thead> <tr> <th>编号</th> <th>品牌名称</th> <th>创立时间</th> <th>操作</th> </tr> </thead> <tbody> <!-- 5.实现循环遍历生成动态结构 --> <tr v-for="(value,index) in brandList"> <td>{{value.id}}</td> <td>{{value.name}}</td> <td>{{value.time}}</td> <td> <a href="#" @click='del(index)'>删除</a> </td> </tr> <!-- 添加提示 --> <!--通过v-show来实现提示信息的合理出现 --> <tr v-show="brandList.length==0"> <td colspan="4">没有任何数据了,请先添加</td> </tr> </tbody> </table> <button @click='color="red"'>红色</button> <button @click='color="green"'>绿色</button> <button @click='color="yellow"'>黄色</button> </div> </div> <script> // window.onload = function(){ // } // 1.定义全局自定义指令:全局自定义是指在vm实例定义的指令 // 2.通过Vue.directive来创建自定义指令 // Vue.directive(指令名称,{配置}) Vue.directive('focus',{ inserted(el,binding,vNode){ // 我们需要获取元素并设置聚焦 console.log(el) el.focus() } }) // 设置颜色的自定义指令 Vue.directive('setcolor',{ // el:当前使用这个指令的元素 // binding:它是一个对象,里面有一个属性value,就是当前指令所绑定的值 inserted(el,binding){ console.log(binding) el.style.color = binding.value }, // 添加update,监听指令的值的变化,以便页面进行刷新 update(el,binding){ console.log(el) console.log(binding) el.style.color = binding.value } }) // 2.创建vm实例 var vm = new Vue({ // 3.添加配置 el: '#app', data: { color:'yellow', // id号 id:'', // 品牌名称 brandname:'', brandList: [ { "id": 1, name: 'AA', time: new Date() }, { "id": 2, name: 'BB', time: new Date() } ] }, methods:{ // 删除 del(index){ this.brandList.splice(index,1) }, // 添加 add(){ // 生成对象 var newobj = {id:this.id,name:this.brandname,time:new Date()} // 添加到数组 this.brandList.push(newobj) } }, // 添加一个生命周期钩子函数 mounted(){ // 实现元素的自动获取焦点 // document.querySelector('#bid').focus() // console.log(this) // this.$refs可以获取模板中所有拥有ref属性的元素,它是一个对象 // this.$refs.bid.focus() } }) </script> </body> </html>
命名细节:如果你使用cemal命名法,那么在使用指令的时候就需要将多个单词拆分开,使用-连接。所以建议定义指令的时候命名都是小写
update钩子函数可处理当数据或者模板内容发生变化的时候就自动的触发
// 添加update,监听指令的值的变化,以便页面进行刷新
update(el,binding){
console.log(el)
console.log(binding)
el.style.color = binding.value
}
-
-
种类:
-
全局过滤器:在vm实例之前(外面)创建的过滤器
-
局部过滤器:在组件内部创建的过滤器
-
-
如何定义
-
Vue.filter(名称,函数)
-
细节
-
过滤器会默认接收一个参数,这个参数就是当前调用过滤器的数据对象
-
如果你手动传递了参数,也不会影响默认参数的传递,意味着过滤器中直接在默认参数后添加新的接收形参就可以了
-
过滤器的函数“一定”要写return,因为过滤器一定要返回结果
-
-
-
如何调用
-
通过管道符|
-
格式:需要调用过滤器的数据 | 过滤器名称
-
<!DOCTYPE html> <html lang="en"> <head> <title></title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> #app { width: 600px; margin: 10px auto; } .tb { border-collapse: collapse; width: 100%; } .tb th { background-color: #0094ff; color: white; } .tb td, .tb th { padding: 5px; border: 1px solid black; text-align: center; } .add { padding: 5px; border: 1px solid black; margin-bottom: 10px; } </style> <!-- 1.引入js文件 --> <script src="./js/vue2.js"></script> </head> <body> <!-- 4.添加模板结构 --> <div id="app"> <div class="add"> 编号: <input type="text" v-model='id' ref='bid' v-setcolor="color"> 品牌名称: <input type="text" v-model='brandname' ref='bname' v-focus> <input type="button" value="添加" @click='add'> </div> <div class="add"> 品牌名称: <input type="text" placeholder="请输入搜索条件" @keyup='search'> </div> <div> <table class="tb"> <thead> <tr> <th>编号</th> <th>品牌名称</th> <th>创立时间</th> <th>操作</th> </tr> </thead> <tbody> <!-- 5.实现循环遍历生成动态结构 --> <tr v-for="(value,index) in brandList"> <td>{{value.id}}</td> <td>{{value.name}}</td> <!-- <td>{{timeFormat(value.time)}}</td> --> <td>{{value.time | timeForamt('~')}}</td> <td> <a href="#" @click='del(index)'>删除</a> </td> </tr> <!-- 添加提示 --> <!--通过v-show来实现提示信息的合理出现 --> <tr v-show="brandList.length==0"> <td colspan="4">没有任何数据了,请先添加</td> </tr> </tbody> </table> <button @click='color="red"'>红色</button> <button @click='color="green"'>绿色</button> <button @click='color="yellow"'>黄色</button> </div> </div> <script> // window.onload = function(){ // } // 1.定义全局自定义指令:全局自定义是指在vm实例定义的指令 // 2.通过Vue.directive来创建自定义指令 // Vue.directive(指令名称,{配置}) Vue.directive('focus', { inserted(el, binding, vNode) { // 我们需要获取元素并设置聚焦 console.log(el) el.focus() } }) // 设置颜色的自定义指令 Vue.directive('setcolor', { // el:当前使用这个指令的元素 // binding:它是一个对象,里面有一个属性value,就是当前指令所绑定的值 inserted(el, binding) { console.log(binding) el.style.color = binding.value }, // 添加update,监听指令的值的变化,以便页面进行刷新 update(el, binding) { console.log(el) console.log(binding) el.style.color = binding.value } }) // 添加全局的自定义过滤器 Vue.filter('timeForamt', (date,seperator1) => { // var date = new Date(); // var seperator1 = "/"; var year = date.getFullYear(); var month = date.getMonth() + 1; var strDate = date.getDate(); if (month >= 1 && month <= 9) { month = "0" + month; } if (strDate >= 0 && strDate <= 9) { strDate = "0" + strDate; } var currentdate = year + seperator1 + month + seperator1 + strDate; return currentdate; }) // 2.创建vm实例 var vm = new Vue({ // 3.添加配置 el: '#app', data: { color: 'yellow', // id号 id: '', // 品牌名称 brandname: '', brandList: [ { "id": 1, name: 'AA', time: new Date() }, { "id": 2, name: 'BB', time: new Date() } ] }, methods: { // 格式化日期 // timeFormat(time){ // return "2019-9-9 :9:9:9" // }, // 删除 del(index) { this.brandList.splice(index, 1) }, // 添加 add() { // 生成对象 var newobj = { id: this.id, name: this.brandname, time: new Date() } // 添加到数组 this.brandList.push(newobj) } }, // 添加一个生命周期钩子函数 mounted() { // 实现元素的自动获取焦点 // document.querySelector('#bid').focus() // console.log(this) // this.$refs可以获取模板中所有拥有ref属性的元素,它是一个对象 // this.$refs.bid.focus() } }) </script> </body> </html>
什么场景使用计算属性:当你的模板中的业务比较复杂的时候就可以使用计算属性进行封装
当计算属性中依赖的数据发生变化的时候,这个计算属性就会被触发
所谓依赖的数据就是指里面所依赖的this的成员
它与普通方法的区别:
普通方法没有缓存机制,只要你使用到了方法,就必须进行方法的调用执行
而计算属性是基本依赖进行缓存的,意味着只要依赖项的值没有变化,那么计算属性不会再重新的调用,而是使用上一次的计算结果--提高效率
使用计算属性实现搜索功能
<!DOCTYPE html> <html lang="en"> <head> <title></title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> #app { width: 600px; margin: 10px auto; } .tb { border-collapse: collapse; width: 100%; } .tb th { background-color: #0094ff; color: white; } .tb td, .tb th { padding: 5px; border: 1px solid black; text-align: center; } .add { padding: 5px; border: 1px solid black; margin-bottom: 10px; } </style> <!-- 1.引入js文件 --> <script src="./js/vue2.js"></script> </head> <body> <!-- 4.添加模板结构 --> <div id="app"> <div class="add"> 编号: <input type="text" v-model='id' ref='bid' v-setcolor="color"> 品牌名称: <input type="text" v-model='brandname' ref='bname' v-focus> <input type="button" value="添加" @click='add'> </div> <div class="add"> 品牌名称: <!-- oninput --> <input type="text" placeholder="请输入搜索条件" v-model='userKey'> </div> <div> <table class="tb"> <thead> <tr> <th>编号</th> <th>品牌名称</th> <th>创立时间</th> <th>操作</th> </tr> </thead> <tbody> <!-- 5.实现循环遍历生成动态结构 --> <tr v-for="(value,index) in search"> <td>{{value.id}}</td> <td>{{value.name}}</td> <!-- <td>{{timeFormat(value.time)}}</td> --> <td>{{value.time | timeForamt('~')}}</td> <td> <a href="#" @click='del(index)'>删除</a> </td> </tr> <!-- 添加提示 --> <!--通过v-show来实现提示信息的合理出现 --> <tr v-show="search.length==0"> <td colspan="4">没有任何数据了,请先添加</td> </tr> </tbody> </table> <button @click='color="red"'>红色</button> <button @click='color="green"'>绿色</button> <button @click='color="yellow"'>黄色</button> </div> </div> <script> // window.onload = function(){ // } // 1.定义全局自定义指令:全局自定义是指在vm实例定义的指令 // 2.通过Vue.directive来创建自定义指令 // Vue.directive(指令名称,{配置}) Vue.directive('focus', { inserted(el, binding, vNode) { // 我们需要获取元素并设置聚焦 // console.log(el) el.focus() } }) // 设置颜色的自定义指令 Vue.directive('setcolor', { // el:当前使用这个指令的元素 // binding:它是一个对象,里面有一个属性value,就是当前指令所绑定的值 inserted(el, binding) { // console.log(binding) el.style.color = binding.value }, // 添加update,监听指令的值的变化,以便页面进行刷新 update(el, binding) { // console.log(el) // console.log(binding) el.style.color = binding.value } }) // 添加全局的自定义过滤器 Vue.filter('timeForamt', (date,seperator1) => { // var date = new Date(); // var seperator1 = "/"; var year = date.getFullYear(); var month = date.getMonth() + 1; var strDate = date.getDate(); if (month >= 1 && month <= 9) { month = "0" + month; } if (strDate >= 0 && strDate <= 9) { strDate = "0" + strDate; } var currentdate = year + seperator1 + month + seperator1 + strDate; return currentdate; }) // 2.创建vm实例 var vm = new Vue({ // 3.添加配置 el: '#app', data: { // 搜索关键字 userKey:'', color: 'yellow', // id号 id: '', // 品牌名称 brandname: '', brandList: [ { "id": 1, name: 'AA', time: new Date() }, { "id": 2, name: 'BB', time: new Date() } ] }, methods: { // 删除 del(index) { this.brandList.splice(index, 1) }, // 添加 add() { // 生成对象 var newobj = { id: this.id, name: this.brandname, time: new Date() } // 添加到数组 this.brandList.push(newobj) } }, computed: { search(){ // 监听用户关键字的变化,只是用户输入有变化,就需要重新进行搜索 // 计算属性中的函数一般都会返回一个计算结果 // var result = [] // for(var i=0;i<this.brandList.length;i++){ // // 说明这个对象的name值中包含关键字,这就是我要找的记录之一 // // 如果没有输入任何的关键字,那么this.userKey默认就是"" // if(this.brandList[i].name.indexOf(this.userKey) != -1){ // result.push(this.brandList[i]) // } // } // return result // 每次都会从数组中取出一个值,传递给回调函数中的参数value // 在回调函数中对Value进行检测判断如果满足条件,那么就会将value值存储到filter方法内部创建的临时数组arr中,最终将这个数组arr返回 // forEach map filter return this.brandList.filter((value) => { return value.name.indexOf(this.userKey) != -1 }) } } }) </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <title></title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="./js/vue2.js"></script> </head> <body> <div id="app"> <input type="text" v-model='first'> <input type="text" v-model='second'> <p>{{fullname}}</p> </div> <script> var vm = new Vue({ el: '#app', data: { first:'', second:'', fullname:'' }, // 添加侦听器 watch:{ // 方法的名称必须和你想要侦听的data中的成员名称一致 first(newvalue,oldvalue){ setTimeout(() => { console.log(newvalue,oldvalue) this.fullname = newvalue.trim().toUpperCase() +":"+this.second }, 100); }, second(newvalue,oldvalue){ console.log(newvalue,oldvalue) } } }) </script> </body> </html>
watch监听如何实现深度监听
什么是深度:不再是this的直接成员,面是this的成员的成员
两种实现方式:
1.handler +deep
2.'对象.属性'(){}
深度监听Demo
<!DOCTYPE html> <html lang="en"> <head> <title></title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <script src="./js/vue2.js"></script> </head> <body> <div id="app"> <input type="text" v-model='obj.name'> <input type="text" v-model='obj.age'> <p>{{obj.name+":"+obj.age}}</p> </div> <script> var vm = new Vue({ el: '#app', data: { msg:'', obj:{ name:'', age:'' } }, // 添加侦听属性 watch:{ msg(){}, // 深度侦听: // 为什么直接侦听obj,在修改数据的时候没有响应,是因为obj一个对象,你修改对象的属性值,并没有修改对象的的地址 // obj(){ // } // obj:{ // // 通过handler函数进行侦听 // handler(nv,ov){ // console.log(nv.name,nv.age) // }, // // 设置为深度侦听 // deep:true // } // 侦听指定的成员值的变化 'obj.name' (nv){ console.log(nv) } } }) </script> </body> </html>
什么时候使用侦听器?
当数据操作涉及到异步方式的时候,就需要使用侦听器
Vue学习文档:https://cn.vuejs.org/v2/guide/