今天是818,时间过的很快,2020上半年就过去了,您是否有对自己进行年中总结过呢?比如,VUE3.0也来了,您现在的VUE的技术是否有了新的进展了呢?今天给大家分享一些VUE数据模板引擎,即常用的指令。
vue.js官方给自己的定为是数据模板引擎,并给出了一套渲染数据的指令。
Vue.js 使用了基于 HTML 的模板语法,最简单的使用vue的方式是渲染数据,渲染数据最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>vue插值</title> </head> <body> <p id="app-01"> {{ message }} </p> <!--安装方式一:<script src="../../statics/vue.js"></script> --> <!--安装方式二--> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> <script> // 原生js let op = document.getElementById("app-01"); op.innerText = "欢迎来到Web前端之家,https://www.jiangweishan.com!"; // vue的核心之一是允许采用简洁的模板语法来将数据渲染进DOM系统 let app01 = new Vue({ el: "#app-01", data: { message: "欢迎来到Web前端之家,https://www.jiangweishan.com!" } }); </script> </body> </html>
首先创建一个vue实例,并在创建实例的过程中传入一个对象。
该对象的第一个属性名为el,它的值是我们需要渲染的目标标签,我们通过属性查找定位这个标签。
该对象的第二个属性名为data,里面就是我们要渲染给浏览器标签的数据,另外还有其他属性,我们在后面的章节中一一介绍。
看了上面的代码,可能大家觉得vue也不过如此,原生js代码两行就能完成的事情,vue需要6行代码来实现,还是原生js比较简洁,其实,上面的代码只是给大家演示了挂档的技术,究竟是汽车比较快,还是骑马比较好,我们通过后面的不断学习,来解释这个问题。
接下来,我们来介绍踩油门的技术。
上面的代码中,我们演示了如何将数据渲染进DOM标签,vue帮助我们找到标签并且渲染,对于程序员来说,我们不再需要重复的找标签,绑定事件,然后再找标签,再绑定事件这样的工作了,vue帮我们都做好了,我们只需要关注具体的数据,以及业务逻辑。这也是vue给自己的定位,数据模板引擎。
它是引擎,引擎帮助我们驱动数据渲染到模板。
所以,vue的大部分内容,都是为了渲染数据用的,接下来,我们介绍vue中用来渲染数据的常用指令。
一、vue.js模板语法之常用指令
常用指令: v-html
双大括号语法无法渲染HTML标签,我们需要使用v-html。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>v-html</title> </head> <body> <p id="app01"> <p v-html="vue"></p> </p> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> <script> let app01 = new Vue({ el: "#app01", data: { vue: '<h1>Hello Vue!</h1>' } }) </script> </body> </html>
常用指令:v-text
类似双大括号语法渲染数据的另一种方式是使用v-text。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>v-html</title> </head> <body> <p id="app01"> <p v-text="name"></p> </p> <script src="./vue.js"></script> <script> let app01 = new Vue({ el: "#app01", data: { name: "dogfa" } }) </script> </body> </html>
常用指令:v-for
接下来,我们看看数组和对象的渲染方式
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>v-for</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> </head> <body> <p id="app01"> <h2>dogfa的爱好</h2> <ul> <li v-for="item in qianqian">{{ item }}</li> </ul> <h2>学生的爱好</h2> <ul> <li v-for="stu in students">{{ stu.name }}的爱好是{{ stu.hobby}}</li> </ul> </p> <script> let app01 = new Vue({ el: "#app01", data: { qianqian: [ "学习", "逛街", "美甲" ], students: [ { name: "dogfa", hobby: "girls" }, { name: "djb", hobby: "girls" }, { name: "oldniu", hobby: "study" } ] } }) </script> </body> </html>
常用指令:v-if
渲染数据的时候,同样也可以使用条件判断,我们来看看。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>v-if</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> </head> <body> <p id="app01"> <p v-if="role == 'shanshan'"> <h2>欢迎小美女</h2> </p> <p v-else-if="role == 'longting'"> <h2>欢迎小龙女</h2> </p> <p v-else> <h2>滚~~~</h2> </p> </p> <script> // 请注意看HTML标签元素,v-if底层使用appendChild实现 let app01 = new Vue({ el: "#app01", data: { role: "shanshan" } }) </script> </body> </html>
通过上面的代码我们可以看出,v-if的作用是控制标签的显示,它通过判断添加标签,底层采用的是appendChild来实现的,下面我们来看一个同样也是控制标签显示的另一个指令v-show。
常用指令:v-show
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>v-show</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> </head> <body> <p id="app01"> <h1 v-show="isShow">Hello Vue!</h1> </p> <script> // v-show的实现原理是通过控制样式的display let app01 = new Vue({ el: "#app01", data: { isShow: true } }) </script> </body> </html>
与v-if不同的是,v-show通过样式的display控制标签的显示。
v-if和v-show的性能比较
我们简单比较一下二者的区别:
实现方式:v-if底层采用的是appendChild来实现的,v-show通过样式的display控制标签的显示,正因为实现方式上面有差异,导致了他们的加载速度方面产生了差异;
加载性能:v-if加载速度更快,v-show加载速度慢
切换开销:v-if切换开销大,v-show切换开销小
v-if是惰性的,它是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建,v-show 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if有更高的切换开销,而v-show有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show较好,如果在运行时条件很少改变,则使用v-if较好。
常用指令:v-bind
绑定属性,不多说了,注意冒号后面跟标签的属性,属性后面的等号指向数据,它可以简写为 :class, :href。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>v-bind</title> <style> .active { background-color: #2b84da; } </style> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> </head> <body> <p id="app01"> <a v-bind:href='link' v-bind:class="{active: isActive}">去百度</a> </p> <script> // 绑定属性,简写冒号: let app01 = new Vue({ el: "#app01", data: { link: "https://www.luffycity.com", isActive: true } }) </script> </body> </html>
常用指令:v-on
另一个非常重要的指令是v-on,使用v-on我们可以在标签上面绑定事件,注意我们新建的vue实例app01中多了一个属性,methods,在methods中,是我们具体事件的实现方式。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>v-on</title> <style> </style> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> </head> <body> <p id="app01"> <!--方式一: 绑定一个事件--> <a v-bind:href='link' v-bind:class="{active: isActive}" v-on:click="myClick" >去百度</a> <!--方式二: 绑定多个事件--> <button v-on="{click: myClick, mouseenter: mouseEnter, mouseleave: mouseLeave}"> 点我今晚吃鸡~~~ </button> </p> <script> // 绑定属性,简写冒号: let app01 = new Vue({ el: "#app01", data: { link: "https://www.baidu.com", isActive: false }, methods: { myClick: function () { console.log("大吉大利,今晚吃鸡~~~") }, mouseEnter: function () { console.log("鼠标来了~~~"); }, mouseLeave: function () { console.log("鼠标走了~~~"); } } }) </script> </body> </html>
常用指令:v-model
上面演示的是通过vue实例将数据渲染进模板,并且在控制台,我们修改数据之后,修改后的数据能够及时(官方称之为响应式)的渲染到模板层,那么,如果有这样的需求,比如有一个input标签,当用户修改渲染的原始数据后,打印修改后的数据,简单说,我们需要vue实例可以帮我们渲染数据并响应式的监听数据修改,同时我们还需要监听用户行为,如果用户在标签上面修改了数据(之前的修改,指的是通过vue实例app01进行的数据修改),我们需要获取到数据,针对这个需求,我们可以使用v-mode指令。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>v-model</title> </head> <body> <p id="app01"> <p>请选择你的性别</p> <br> <input v-model="name"/> <p><input type="text" v-model="name"/></p> <p> <input type="checkbox" value="男" v-model="gender"/> <input type="checkbox" value="女" v-model="gender"/> </p> <br> {{ name }} {{ gender }} <p>请选择你的女朋友</p> <select name="" id="" v-model="girlFriends"> <option>dogfa</option> <option>djb</option> <option>oldniu</option> </select> <br> {{ girlFriends }} <p> <textarea v-model="article"></textarea> </p> <br> {{ article }} </p> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> <script> let app01 = new Vue({ el: "#app01", data: { name: "dogfa", gender: [], girlFriends: [], article: "这是一篇文章", } }) </script> </body> </html>
常用指令:指令修饰符
用户可以输入任何数据类型,但有时候,我们需要限定用户输入的数据类型,可以在指令后面加上number修饰符。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> </head> <body> <p id="app01"> <table border="1"> <thead> <tr> <th>学科</th> <th>成绩</th> </tr> </thead> <tbody> <tr> <td>Python基础</td> <td><input type="text" v-model.number="python"/></td> </tr> <tr> <td>前端</td> <td><input type="text" v-model.lazy="web"/></td> </tr> <tr> <td>Django</td> <td><input type="text" v-model.trim="django"/></td> </tr> </tbody> </table> </p> <script> let app01 = new Vue({ el: "#app01", data: { python: 75, web: 98, django: 88 } }) </script> </body> </html>
常用指令:计算属性
计算属性用来监听多个数据,每次页面加载,计算属性中的函数立即执行,但是只要原数据不被修改,那么,就不会触发重新计算,计算属性会使用计算后的缓存结果,只当原数据修改时,才会重新计算并将结果缓存起来。计算属性的计算结果可以当做data中的数据一样使用。
<html> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> </head> <body> <p id="app01"> <table border="1"> <thead> <tr> <th>学科</th> <th>成绩</th> </tr> </thead> <tbody> <tr> <td>Python基础</td> <td><input type="text" v-model.number="python"/></td> </tr> <tr> <td>前端</td> <td><input type="text" v-model.trim="web"/></td> </tr> <tr> <td>Django</td> <td><input type="text" v-model.lazy="django"/></td> </tr> <tr> <td>总分</td> <td>{{ python + web + django }}</td> </tr> <tr> <td>平均分</td> <td>{{ avgScore }}</td> </tr> </tbody> </table> </p> <script> // 计算属性放在缓存当中,只有数据修改时才重新计算 let app01 = new Vue({ el: "#app01", data: { python: 75, web: 98, django: 88 }, computed: { sumScore: function () { return this.python + this.web + this.django; }, avgScore: function () { return this.sumScore/3; } } }) </script> </body> </html>
计算属性是通过过滤多个数据之后的结果,不一定是data中已存在的数据。
常用指令:侦听属性
计算属性用来监听多个属性,我们也可以使用它来监听一个属性,但是页面加载即执行计算并不符合我们的需求,如何只在数据被修改后出发相应事件,vue提供给我们的是watch,即侦听属性。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> </head> <body> <p id="app"> <p>Original message: {{ message }}</p> <p>Computed message: {{ reversedMessage }}</p> <p>Full name: {{ fullName }}</p> <p><input type="text" v-model="firstName"/></p> <p><input type="text" v-model="lastName"/></p> </p> <script> new Vue({ el: "#app", data: { message: "Hello Vue!", firstName: "Foo", lastName: "Bar", fullName: "Foo Bar", }, computed: { reversedMessage: { get: function () { console.log(1); // 多次刷新reversedMessage不会改变, 除非message发生改变 return this.message.split('').reverse().join(''); } } }, watch: { firstName: function (value) { console.log(value); this.fullName = value + ' ' + this.lastName }, lastName: function (value) { console.log(value); this.fullName = this.firstName + ' ' + value } } }) </script> </body> </html>
侦听属性必须是data中的已存在的数据。
常用指令:自定义指令
遇到一些复杂的需求,vue提供的指令不能完美的处理,有时候我们需要自定义指令,针对这一需求,vue提供了自定义指令,如下所示:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>自定义属性</title> <style> .box { width: 100px; height: 100px; border: 1px; background-color: #ff0000; } </style> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> </head> <body> <p id="app01" v-pos.left.bottom="post"> </p> <script> Vue.directive("pos", function (el, bindding) { let decorators = bindding.modifiers; if (bindding.value) { el.style['position'] = 'fixed'; for (let key in decorators) { el.style[key] = 0; } } else { el.style.position = "static"; } }); // 自定义属性 let app01 = new Vue({ el: "#app01", data: { post: true } }) </script> </body> </html>
el是我们自定义指令所在的DOM元素;
bindding是自定义指令的一些具体数据,请记住,最重要的一点是,不管是现在还是将来,任何情况下,我们都需要根据数据进行业务处理,所以,此处最关键的也是数据,即bindding.value。
常用指令:获取DOM元素
某些情况下,我们需要直接获取DOM元素,并对元素进行一些加工处理。vue提供给我们$refs来获取DOM元素
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>获取DOM</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> </head> <body> <p id="app01"> <p ref="myBox">dogfa</p> <button v-on:click="dogfa">点击dogfa变红</button> </p> <script> // 错误实例button放在p外面 let app01 = new Vue({ el: "#app01", methods: { dogfa: function () { this.$refs.myBox.style.color = "red"; } } }) </script> </body> </html>
在DOM元素上面绑定了ref之后,vue根实例上面就会出现$refs
变量,它是一个object类型,key为ref后面的自定义名称,而value为DOM元素。我们通过this.$refs
拿到object,之后就可以通过自定义的key名,来找到DOM元素
二、案例:todoList
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>使用Vue实现todoList</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> <style> * { margin: 0; padding: 0; } .container { width: 500px; height: auto; margin: 0 auto; } .container .header { text-align: center } li { list-style-type: none } p.left { float: left; margin-left: 50px; } p.right { float: right; margin-right: 50px; } li { margin-top: 5px; } </style> </head> <body> <p id="app"> <p> <!--头部添加待办--> <p> <input id="addthings" @keyup.enter="todoEnter" v-model="todo"> <span @click="todoEnter">添加待办</span> </p> <!--已办和待办最外层的盒子--> <p> <!--已办事项--> <p> <span>待办事项</span> <p> <ul> <li v-for="(todo, index) in todoThings" :key="index"> <input type="radio" name="todo" v-on:click="addThing(index)"><span>{{ todo }}</span> </li> </ul> </p> </p> <!--待办事项--> <p> <span>已办事项</span> <p> <ul> <li v-for="(done, index) in doneThings" :key="index"> <input type="radio" name="done" v-on:click="delThing(index)"><span>{{ done }}</span> </li> </ul> </p> </p> </p> </p> </p> <script> new Vue({ el: "#app", data: { todo: '', addDone: '', todoThings: ['写代码', '五道口吃火锅', '超市买鸡蛋', '图书馆看书', '看电影', '看演唱会', '游泳', '跑步'], doneThings: ['看书', '写博客', '散步', '跟朋友聊天', '打电话给父母', '学炒菜', '洗衣服', '打扫房间'] }, methods: { todoEnter: function () { if (this.todo) { this.todoThings.push(this.todo); this.todo = ''; } }, addThing: function (index) { event.currentTarget.checked = false; things = this.todoThings.splice(index, 1)[0]; this.doneThings.push(things); }, delThing: function (index) { event.currentTarget.checked = false; things = this.doneThings.splice(index, 1)[0]; this.todoThings.push(things); } } }) </script> </body> </html>
三、案例:轮播图
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> <style> * { margin: 0; padding: 0; } .container { margin: 0 auto; width: 800px; height: 500px; position: relative; top: 80px; } .img { width: 800px; height: 500px; position: absolute; } img { width: 800px; height: 500px; } .circle { width: 130px; height: 2px; position: absolute; left: 50%; margin-left: -65px; bottom: 30px; } .circle span { padding: 1px 10px; background-color: #c2ccd1; border-radius: 50%; margin-left: 5px; cursor: pointer; } .circle span.current { background-color: #F90; } </style> </head> <body> <p id="app"> <p> <p><img :src="imageArray[currentIndex].imgSrc" v-on="{ mouseenter: mouseEnter, mouseleave: mouseLeave}"></p> <p> <span v-for="(circle, index) in circleCount" :class="{current: currentIndex===index}" v-on:click="changePic(index)"></span> </p> </p> </p> <script> new Vue({ el: "#app", data: { imageArray: [ { id: 1, imgSrc: "../images/timg1.jpg" }, { id: 2, imgSrc: "../images/timg2.jpg" }, { id: 3, imgSrc: "../images/timg3.jpg" }, { id: 4, imgSrc: "../images/timg4.jpg" }, { id: 5, imgSrc: "../images/timg5.jpg" }, ], currentIndex: 0, circleCount: 5 }, methods: { prevImg: function () { this.currentIndex = this.currentIndex - 1; if (this.currentIndex < 0) { this.currentIndex = this.imageArray.length - 1; } }, nextImg: function () { this.currentIndex = this.currentIndex + 1; if (this.currentIndex === this.imageArray.length) { this.currentIndex = 0; } }, mouseEnter: function () { clearInterval(this.interval); }, mouseLeave: function () { this.setInterVal(); }, setInterVal: function () { this.interval = setInterval(() => { this.currentIndex = this.currentIndex + 1; if (this.currentIndex === this.imageArray.length) { this.currentIndex = 0; } }, 3000) }, changePic: function (index) { this.currentIndex = index; } }, created(){ this.setInterVal(); } }) </script> </body> </html>
四、案例:音乐播放器
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>使用Vue实现音乐播放器</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script> <style> * { margin: 0; padding: 0; } .active { background-color: red; } </style> </head> <body> <p id="app"> <audio :src="songs[currentIndex].songSrc" controls="controls" loop="loop" autoplay="autoplay"></audio> <ul> <li v-for="song in songs" :key="song.id" @click="playSong(song.id)" :class="{ active: song.id===currentIndex+1 }"> <h2>歌手:{{ song.artist }}</h2> <p>歌名:{{ song.name }}</p> </li> </ul> </p> <script> new Vue({ el: "#app", data: { songs: [ { id: 1, songSrc: '../medias/不再让你孤单.mp3', artist: "李必胜", name: '不再让你孤单' }, { id: 2, songSrc: '../medias/漂洋过海来看你.mp3', artist: "Pizza Li", name: '漂洋过海来看你' }, { id: 3, songSrc: '../medias/成都.mp3', artist: '必胜', name: '成都' }, { id: 4, songSrc: '../medias/晚风.mp3', artist: 'Pizza', name: '晚风' }, ], currentIndex: 0 }, methods: { playSong(index) { this.currentIndex = index - 1; } } }) </script> </body> </html>
网友评论文明上网理性发言 已有0人参与
发表评论: