1.计算属性
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>22-Vue-计算属性</title> <script src="js/vue.js"></script> </head> <body> <!-- 1.插值语法特点 可以在{{}}中编写合法的JavaScript表达式 2.在插值语法中编写JavaScript表达式缺点 2.1没有代码提示 2.2语句过于复杂不利于我们维护 3.如何解决? 对于任何复杂逻辑,你都应当使用计算属性 --> <!--这里就是MVVM中的View--> <div id="app"> <p>{{name}}</p> <p>{{age + 1}}</p> <p>{{msg.split("").reverse().join("")}}</p> <!-- 注意点: 虽然在定义计算属性的时候是通过一个函数返回的数据 但是在使用计算属性的时候不能在计算属性名称后面加上() 因为它是一个属性不是一个函数(方法) --> <p>{{msg2}}</p> </div> <script> // 这里就是MVVM中的View Model let vue = new Vue({ el: '#app', // 这里就是MVVM中的Model data: { name: "lnj", age: 18, msg: "abcdef" }, // 专门用于存储监听事件回调函数 methods: {}, // 专门用于定义计算属性的 computed: { msg2: function () { let res = "abcdef".split("").reverse().join(""); return res; } } }); </script> </body> </html>
2.计算属性与函数的异同
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>23-Vue-计算属性和函数</title> <script src="js/vue.js"></script> </head> <body> <!-- 1.计算属性和函数 通过计算属性我们能拿到处理后的数据, 但是通过函数我们也能拿到处理后的数据 那么计算属性和函数有什么区别呢? 2.1函数"不会"将计算的结果缓存起来, 每一次访问都会重新求值 2.2计算属性"会"将计算的结果缓存起来, 只要数据没有发生变化, 就不会重新求值 2.计算属性应用场景 计算属性:比较适合用于计算不会频繁发生变化的的数据 --> <!--这里就是MVVM中的View--> <div id="app"> <!--会输出三次--> <p>{{msg1()}}</p> <p>{{msg1()}}</p> <p>{{msg1()}}</p> <!--下面调用三次只输出一次--> <p>{{msg2}}</p> <p>{{msg2}}</p> <p>{{msg2}}</p> </div> <script> // 这里就是MVVM中的View Model let vue = new Vue({ el: '#app', // 这里就是MVVM中的Model data: { }, // 专门用于存储监听事件回调函数 methods: { /* 函数的特点: 每次调用都会执行 * */ msg1(){ console.log("msg1函数被执行了"); let res = "abcdef".split("").reverse().join(""); return res; } }, // 专门用于定义计算属性的 computed: { /* 计算属性的特点: 只要返回的结果没有发生变化, 那么计算属性就只会被执行一次 计算属性的应用场景: 由于计算属性会将返回的结果缓存起来 所以如果返回的数据不经常发生变化, 那么使用计算属性的性能会比使用函数的性能高 * */ msg2() { console.log("msg2计算属性被执行了"); let res = "abcdef".split("").reverse().join(""); return res; } } }); </script> </body> </html>
3.过滤器
3.1 全局过滤器
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>24-Vue-自定义全局过滤器</title> <script src="js/vue.js"></script> </head> <body> <!-- 1.什么是过滤器? 过滤器和函数和计算属性一样都是用来处理数据的 但是过滤器一般用于格式化插入的文本数据 2.如何自定义全局过滤器 Vue.filter("过滤器名称", 过滤器处理函数): 3.如何使用全局过滤器 {{msg | 过滤器名称}} :value="msg | 过滤器名称" 4.过滤器注意点 4.1只能在插值语法和v-bind中使用 4.2过滤器可以连续使用 --> <!--这里就是MVVM中的View--> <div id="app"> <!--Vue会把name交给指定的过滤器处理之后, 再把处理之后的结果插入到指定的元素中--> <p>{{name | formartStr1 | formartStr2}}</p> </div> <script> /* 如何自定义一个全局过滤器 通过Vue.filter(); filter方法接收两个参数 第一个参数: 过滤器名称 第二个参数: 处理数据的函数 注意点: 默认情况下处理数据的函数接收一个参数, 就是当前要被处理的数据 * */ Vue.filter("formartStr1", function (value) { // console.log(value); value = value.replace(/学院/g, "大学"); console.log(value); return value; }); Vue.filter("formartStr2", function (value) { // console.log(value); value = value.replace(/大学/g, "幼儿园"); console.log(value); return value; }); // 这里就是MVVM中的View Model let vue = new Vue({ el: '#app', // 这里就是MVVM中的Model data: { name: "知播渔学院, 指趣学院, 前端学院, 区块链学院" }, // 专门用于存储监听事件回调函数 methods: { }, // 专门用于定义计算属性的 computed: { } }); </script> </body> </html>
3.2 局部过滤器
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>24-Vue-自定义全局过滤器</title> <script src="js/vue.js"></script> </head> <body> <!-- 1.自定义全局过滤器的特点 在任何一个Vue实例控制的区域中都可以使用 2.自定义局部过滤器的特点 只能在自定义的那个Vue实例中使用 3.如何自定义一个局部指令 给创建Vue实例时传递的对象添加 filters: { // key: 过滤器名称 // value: 过滤器处理函数 'formartStr': function (value) {} } --> <!--这里就是MVVM中的View--> <div id="app2"> <p>{{name | formartStr}}</p> </div> <script> // 这里就是MVVM中的View Model let vue2 = new Vue({ el: '#app2', // 这里就是MVVM中的Model data: { name: " 前端学院" }, // 专门用于存储监听事件回调函数 methods: { }, // 专门用于定义计算属性的 computed: { }, // 专门用于定义局部过滤器的 filters: { "formartStr": function (value) { // console.log(value); value = value.replace(/学院/g, "大学"); // console.log(value); return value; } } }); </script> </body> </html>
3.3 一个小小的练习
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>24-Vue-自定义全局过滤器</title> <script src="js/vue.js"></script> </head> <body> <!-- 需求: 利用过滤器对时间进行格式化 --> <!--这里就是MVVM中的View--> <div id="app"> <p>{{time | dateFormart("yyyy-MM-dd")}}</p> </div> <script> /* 注意点: 在使用过滤器的时候, 可以在过滤器名称后面加上() 如果给过滤器的名称后面加上了(), 那么就可以给过滤器的函数传递参数 * */ Vue.filter("dateFormart", function (value, fmStr) { // console.log(fmStr); let date = new Date(value); let year = date.getFullYear(); let month = date.getMonth() + 1 + ""; let day = date.getDate() + ""; let hour = date.getHours() + ""; let minute = date.getMinutes() + ""; let second = date.getSeconds() + ""; if(fmStr && fmStr === "yyyy-MM-dd"){ //padStart用于补足头部 return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`; } return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")} ${hour.padStart(2, "0")}:${minute.padStart(2, "0")}:${second.padStart(2, "0")}`; }); // 这里就是MVVM中的View Model let vue = new Vue({ el: '#app', // 这里就是MVVM中的Model data: { time: Date.now() }, // 专门用于存储监听事件回调函数 methods: { }, // 专门用于定义计算属性的 computed: { } }); </script> </body> </html>
4.过渡动画
4.1 通过类名的方式添加
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>28-Vue-过渡动画</title> <script src="js/vue.js"></script> <style> *{ margin: 0; padding: 0; } .box{ width: 200px; height: 200px; background: red; } .v-enter{ opacity: 0; } .v-enter-to{ opacity: 1; } .v-enter-active{ transition: all 3s; } .v-leave{ opacity: 1; } .v-leave-to{ opacity: 0; } .v-leave-active{ transition: all 3s; } </style> </head> <body> <!-- 1.如何给Vue控制的元素添加过渡动画 1.1将需要执行动画的元素放到transition组件中 1.2当transition组件中的元素显示时会自动查找.v-enter/.v-enter-active/.v-enter-to类名 当transition组件中的元素隐藏时会自动查找.v-leave/ .v-leave-active/.v-leave-to类名 v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。 v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效, 在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。 v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移 除),在过渡/动画完成之后移除。 v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。 v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在 过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。 v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。 1.3我们只需要在.v-enter和.v-leave-to中指定动画动画开始的状态 在.v-enter-active和.v-leave-active中指定动画执行的状态 即可完成过渡动画 --> <!--这里就是MVVM中的View--> <div id="app"> <button @click="toggle">我是按钮</button> <transition> <div class="box" v-show="isShow"></div> </transition> </div> <script> // 这里就是MVVM中的View Model let vue = new Vue({ el: '#app', // 这里就是MVVM中的Model data: { isShow: false }, // 专门用于存储监听事件回调函数 methods: { toggle(){ this.isShow = !this.isShow; } }, // 专门用于定义计算属性的 computed: { } }); </script> </body> </html>
4.2 transition的注意点
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>29-Vue-过渡动画</title> <script src="js/vue.js"></script> <style> *{ margin: 0; padding: 0; } .box{ width: 200px; height: 200px; background: red; } .one-enter{ opacity: 0; } .one-enter-to{ opacity: 1; margin-left: 500px; } .one-enter-active{ transition: all 3s; } .two-enter{ opacity: 0; } .two-enter-to{ opacity: 1; margin-top: 500px; } .two-enter-active{ transition: all 3s; } </style> </head> <body> <!-- 1.transition注意点: transition中只能放一个元素, 多个元素无效 如果想给多个元素添加过渡动画, 那么就必须创建多个transition组件 2.初始动画设置 默认情况下第一次进入的时候没没有动画的 如果想一进来就有动画, 我们可以通过给transition添加appear属性的方式 告诉Vue第一次进入就需要显示动画 3.如何给多个不同的元素指定不同的动画 如果有多个不同的元素需要执行不同的过渡动画,那么我们可以通过给transition指定name的方式 来指定"进入之前/进入之后/进入过程中, 离开之前/离开之后/离开过程中"对应的类名 来实现不同的元素执行不同的过渡动画 --> <!--这里就是MVVM中的View--> <div id="app"> <button @click="toggle">我是按钮</button> <transition appear name="one"> <div class="box" v-show="isShow"></div> <!-- <div class="box" v-show="isShow"></div>--> </transition> <transition appear name="two"> <div class="box" v-show="isShow"></div> </transition> </div> <script> // 这里就是MVVM中的View Model let vue = new Vue({ el: '#app', // 这里就是MVVM中的Model data: { isShow: true }, // 专门用于存储监听事件回调函数 methods: { toggle(){ this.isShow = !this.isShow; } }, // 专门用于定义计算属性的 computed: { } }); </script> </body> </html>
4.3 钩子函数来添加动画
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>30-Vue-过渡动画</title> <script src="js/vue.js"></script> <style> *{ margin: 0; padding: 0; } .box{ width: 200px; height: 200px; background: red; } /*.v-enter{ opacity: 0; } .v-enter-to{ opacity: 1; margin-left: 500px; } .v-enter-active{ transition: all 3s; }*/ </style> </head> <body> <!-- 1.当前过渡存在的问题 通过transition+类名的方式确实能够实现过渡效果 但是实现的过渡效果并不能保存动画之后的状态 因为Vue内部的实现是在过程中动态绑定类名, 过程完成之后删除类名 正式因为删除了类名, 所以不能保存最终的效果 2.在Vue中如何保存过渡最终的效果 通过Vue提供的JS钩子来实现过渡动画 v-on:before-enter="beforeEnter" 进入动画之前 v-on:enter="enter" 进入动画执行过程中 v-on:after-enter="afterEnter" 进入动画完成之后 v-on:enter-cancelled="enterCancelled" 进入动画被取消 v-on:before-leave="beforeLeave" 离开动画之前 v-on:leave="leave" 离开动画执行过程中 v-on:after-leave="afterLeave" 离开动画完成之后 v-on:leave-cancelled="leaveCancelled" 离开动画被取消 3.JS钩子实现过渡注意点 3.1在动画过程中必须写上el.offsetWidth或者el.offsetHeight 3.2在enter和leave方法中必须调用done方法, 否则after-enter和after-leave不会执行 3.3需要需要添加初始动画, 那么需要把done方法包裹到setTimeout方法中调用 --> <!--这里就是MVVM中的View--> <div id="app"> <button @click="toggle">我是按钮</button> <!-- 注意点: 虽然我们是通过JS钩子函数来实现过渡动画 但是默认Vue还是回去查找类名, 所以为了不让Vue去查找类名 可以给transition添加v-bind:css="false" --> <transition appear v-bind:css="false" v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:after-enter="afterEnter"> <div class="box" v-show="isShow"></div> </transition> </div> <script> // 这里就是MVVM中的View Model let vue = new Vue({ el: '#app', // 这里就是MVVM中的Model data: { isShow: true }, // 专门用于存储监听事件回调函数 methods: { toggle(){ this.isShow = !this.isShow; }, beforeEnter(el){ // 进入动画开始之前 console.log("beforeEnter"); el.style.opacity = "0"; }, enter(el, done){ // 进入动画执行过程中 console.log("enter"); /* 注意点: 如果是通过JS钩子来实现过渡动画 那么必须在动画执行过程中的回调函数中写上 el.offsetWidth / el.offsetHeight * */ el.offsetWidth; el.style.transition = "all 3s"; /* 注意点: 动画执行完毕之后一定要调用done回调函数 否则后续的afterEnter钩子函数不会被执行 */ //done(); /* 注意点: 如果想让元素一进来就有动画, 那么最好延迟一下再调用done方法 */ setTimeout(function () { done(); }, 0); }, afterEnter(el){ // 进入动画执行完毕之后 console.log("afterEnter"); el.style.opacity = "1"; el.style.marginLeft = "500px"; } }, // 专门用于定义计算属性的 computed: { } }); </script> </body> </html>
4.4 配合第三方库来实现动画
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>31-Vue-过渡动画</title> <script src="js/vue.js"></script> <style> *{ margin: 0; padding: 0; } .box{ width: 200px; height: 200px; background: red; } </style> </head> <body> <!-- 1.配合Velocity实现过渡动画 在Vue中我们除了可以自己实现过渡动画以外, 还可以结合第三方框架实现过渡动画 1.1导入Velocity库 1.2在动画执行过程钩子函数中编写Velocity动画 --> <!--这里就是MVVM中的View--> <div id="app"> <button @click="toggle">我是按钮</button> <transition appear v-bind:css="false" v-on:before-enter="beforeEnter" v-on:enter="enter" v-on:after-enter="afterEnter"> <div class="box" v-show="isShow"></div> </transition> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script> <script> // 这里就是MVVM中的View Model let vue = new Vue({ el: '#app', // 这里就是MVVM中的Model data: { isShow: true }, // 专门用于存储监听事件回调函数 methods: { toggle(){ this.isShow = !this.isShow; }, beforeEnter(el){ }, enter(el, done){ Velocity(el, {opacity: 1, marginLeft: "500px"}, 3000); done(); }, afterEnter(el){ } }, // 专门用于定义计算属性的 computed: { } }); </script> </body> </html>
4.5 自定义动画的类名
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>32-Vue-过渡动画</title> <script src="js/vue.js"></script> <style> *{ margin: 0; padding: 0; } .box{ width: 200px; height: 200px; background: red; } .a{ opacity: 0; } .b{ opacity: 1; margin-left: 500px; } .c{ transition: all 3s; } </style> </head> <body> <!-- 1.自定义类名动画 在Vue中除了可以使用 默认类名(v-xxx)来指定过渡动画 除了可以使用 自定义类名前缀(yyy-xx)来指定过渡动画(transition name="yyy") 除了可以使用 JS钩子函数来指定过渡动画以外 还可以使用自定义类名的方式来指定过渡动画 enter-class // 进入动画开始之前 enter-active-class // 进入动画执行过程中 enter-to-class // 进入动画执行完毕之后 leave-class // 离开动画开始之前 leave-active-class // 离开动画执行过程中 leave-to-class // 离开动画执行完毕之后 --> <!--这里就是MVVM中的View--> <div id="app"> <button @click="toggle">我是按钮</button> <transition appear enter-class="a" enter-active-class="c" enter-to-class="b"> <div class="box" v-show="isShow"></div> </transition> </div> <script> // 这里就是MVVM中的View Model let vue = new Vue({ el: '#app', // 这里就是MVVM中的Model data: { isShow: true }, // 专门用于存储监听事件回调函数 methods: { toggle(){ this.isShow = !this.isShow; } }, // 专门用于定义计算属性的 computed: { } }); </script> </body> </html>
4.6 自定义动画类名结合Animate.css
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>33-Vue-过渡动画</title> <script src="js/vue.js"></script> <style> *{ margin: 0; padding: 0; } .box{ width: 200px; height: 200px; background: red; } </style> <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css"> </head> <body> <!-- 1.配合Animate.css实现过渡动画 1.1导入Animate.css库 1.2在执行过程中的属性上绑定需要的类名 --> <!--这里就是MVVM中的View--> <div id="app"> <button @click="toggle">我是按钮</button> <transition appear enter-class="" enter-active-class="animated bounceInRight" enter-to-class=""> <div class="box" v-show="isShow"></div> </transition> </div> <script> // 这里就是MVVM中的View Model let vue = new Vue({ el: '#app', // 这里就是MVVM中的Model data: { isShow: true }, // 专门用于存储监听事件回调函数 methods: { toggle(){ this.isShow = !this.isShow; } }, // 专门用于定义计算属性的 computed: { } }); </script> </body> </html>
4.7 v-for中的key
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>34-Vue-v-for-key</title> <script src="js/vue.js"></script> </head> <body> <!-- 1.v-for注意点 1.1v-for为了提升性能, 在更新已渲染过的元素列表时,会采用“就地复用”策略。 也正是因为这个策略, 在某些时刻会导致我们的数据混乱 例如: 在列表前面新增了内容 1.2为了解决这个问题, 我们可以在渲染列表的时候给每一个元素加上一个独一无二的key v-for在更新已经渲染过的元素列表时, 会先判断key是否相同, 如果相同则复用, 如果不同则重新创建 2.key属性注意点 不能使用index的作为key,因为当列表的内容新增或者删除时index都会发生变化 --> <!--这里就是MVVM中的View--> <div id="app"> <form> <input type="text" v-model="name"> <input type="submit" value="添加" @click.prevent="add"> </form> <ul> <li v-for="(person,index) in persons" :key="person.id"> <input type="checkbox"> <span>{{index}} --- {{person.name}}</span> </li> </ul> </div> <script> // 这里就是MVVM中的View Model let vue = new Vue({ el: '#app', // 这里就是MVVM中的Model data: { persons: [ {name: "zs", id: 1}, {name: "ls", id: 2}, {name: "ww", id: 3} ], name: "" }, // 专门用于存储监听事件回调函数 methods: { add(){ let lastPerson = this.persons[this.persons.length - 1]; let newPerson = {name: this.name, id: lastPerson.id + 1}; // this.persons.push(newPerson); this.persons.unshift(newPerson); this.name = ""; } }, // 专门用于定义计算属性的 computed: { } }); </script> </body> </html>
4.8 同时给多个元素添加动画 transition-group
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>35-Vue-过渡动画</title> <script src="js/vue.js"></script> <style> *{ margin: 0; padding: 0; } .v-enter{ opacity: 0; } .v-enter-to{ opacity: 1; } .v-enter-active{ transition: all 3s; } .v-leave{ opacity: 1; } .v-leave-to{ opacity: 0; } .v-leave-active{ transition: all 3s; } </style> </head> <body> <!-- 1.如何同时给多个元素添加过渡动画 通过transition可以给单个元素添加过渡动画 如果想给多个元素添加过渡动画, 那么就必须通过transition-group来添加 transition-group和transition的用法一致, 只是一个是给单个元素添加动画, 一个是给多个元素添加动画而已 --> <!-- 1.transition-group注意点: 默认情况下transition-group会将动画的元素放到span标签中 我们可以通过tag属性来指定将动画元素放到什么标签中 2.transition-group动画混乱问题 一般情况下组动画出现动画混乱都是因为v-for就地复用导致的 我们只需要保证所有数据key永远是唯一的即可 --> <!--这里就是MVVM中的View--> <div id="app"> <form> <input type="text" v-model="name"> <input type="submit" value="添加" @click.prevent="add"> </form> <ul> <transition-group appear> <li v-for="(person,index) in persons" :key="person.id" @click="del(index)"> <input type="checkbox"> <span>{{index}} --- {{person.name}}</span> </li> </transition-group> </ul> </div> <script> // 这里就是MVVM中的View Model let vue = new Vue({ el: '#app', // 这里就是MVVM中的Model data: { persons: [ {name: "zs", id: 1}, {name: "ls", id: 2}, {name: "ww", id: 3} ], name: "" }, // 专门用于存储监听事件回调函数 methods: { add(){ let lastPerson = this.persons[this.persons.length - 1]; let newPerson = {name: this.name, id: lastPerson.id + 1}; // this.persons.push(newPerson); this.persons.unshift(newPerson); this.name = ""; }, del(index){ this.persons.splice(index, 1); } }, // 专门用于定义计算属性的 computed: { } }); </script> </body> </html>