一、vue中template的三种写法
第一种(字符串模板写法):
直接写在vue构造器里,这种写法比较直观,适用于html代码不多的场景,但是如果模板里html代码太多,不便于维护,不建议这么写.
<body> <div id="app"></div> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: "#app", data: { message: '字符串拼接' }, template: '<div> <h1>{{message}}</h1> <div>', }) </script> </body>
第二种(使用script元素)HTML5标准之前的写法
<div id="app"></div> <script type="text/x-template" id="tem"> <div> <h1>{{message}}</h1> </div> </script> new Vue({ el: "#app", data: { message: 'HTML5标准之前的写法,存在一定弊端(可自行google) 之后HTML5发布的template元素弥补了此方式的缺点' }, template: '#tem', })
通过使用<script type="x-template" id="template2">
同时把script标签的id挂载到Vue实例化对象的template中 这种模板的好处是可以通过script的特性,通过src外部引入来使用.
第三种(使用template元素)HTML5标准之后的写法【第二种的升级版】
div id="app"></div> <template id="tem"> <div> <h1>{{message}}</h1> </div> </template> new Vue({ el: "#app", template: '#tem', data: { message: 'HTML5中的template标签' } })
在html中加入template标签,给于这个template标签一个id,然后通过实例化的Vue对象的template属性挂载template模板
二、v-bind
动态地绑定标签中的一个或多个属性,或一个组件 prop 到表达式。v-bind指令可以在其名称后面带一个参数,中间用一个冒号隔开。这个参数通常是HTML元素的特性(attribute)。
v-bind指令:实现对属性的绑定,以动态的切换属性的值。
示例
<body> <div id="app"> <!-- v-bind 是Vue中提供的用于绑定属性的指令 --> <!-- <input type="button" value="按钮" v-bind:title="mytitle" > --> <!-- 简写方式 --> <input type="button" value="按钮" :title="mytitle" > </div> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { msg: 'hello指令系统', mytitle:'v-bind绑定,自己定义的title' }, }) </script> </body>
v-bind:class='xxx':xxx为表达式结果的类型,除了字符串外,还可以是对象或数组;
语法:v-bind:属性名="常量 || 变量名 || 对象 || 数组"。
简写形式:属性名='变量名.....'
v-bind 进行属性绑定所有的属性都可以进行绑定,注意只要使用了v-bind后面的字符串一定是数据属性的值。
常见的使用方式
v-bind:src="imageSrc" 可以缩写: :src="imgaeSrc" :class="{ red: isRed }" 或 :class="[classA, classB]" :style="{ fontSize: size + 'px' }" 或 :style="[styleObjectA, styleObjectB]"
绑定一个有属性的对象,比如:v-bind="{ id: someProp, 'other-attr': otherProp }"
1、绑定字符串
<body> <div id="app"> <!-- v-bind 是Vue中提供的用于绑定属性的指令 --> <h3 v-bind:title="title">我是一个三级标题</h3> <img v-bind:src="imgSrc" v-bind:title="time"> </div> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { msg: 'hello指令系统', title: "哈哈哈2323", imgSrc: './timg.jpg', time: `页面加载于${new Date().toLocaleString()}` }, }) </script> </body>
显示效果
当鼠标悬停在h3标签几秒之后,会显示值“页面加载于”。悬浮在图片上会显示time的值。
v-bind的简便写法(只写冒号“:”不写v-bind):
`<img :src=``"imgSrc"` `:title=``"time"``>`
2、数组语法
我们可以把一个数组传给v-bind:class,以应用一个 class 列表:
<body> <div id="app"> <div v-bind:class="[activeClass, errorClass]">数组绑定class</div> </div> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { msg: 'hello指令系统', activeClass: 'active', errorClass: 'text-danger' }, }) </script> </body>
显示效果
如果你也想根据条件切换列表中的 class,可以用三元表达式:
`<div v-bind:``class``=``"[isActive ? activeClass : '', errorClass]"``></div>`
这样写将始终添加 errorClass
,但是只有在 isActive
是 true时才添加 activeClass
。
不过,当有多个条件 class 时这样写有些繁琐。所以在数组语法中也可以使用对象语法:
`<div v-bind:``class``=``"[{ active: isActive }, errorClass]"``></div>`
三、v-on
动态地绑定一个或多个特性,或一个组件 prop 到表达式;其作用和v-bind类似。注意:如果用在普通元素上时,只能监听 原生 DOM 事件;但是如果用在自定义元素组件上时,也可以监听子组件触发的自定义事件。
<body> <div id="app"> <!-- Vue 中提供了 v-on: 事件绑定机制 --> <input type="button" value="按钮" :title="mytitle + '123'" v-on:click="show"> </div> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { msg: 'hello指令系统', mytitle: '这是一个自己定义的title', }, methods: { // 这个 methods属性中定义了当前Vue实例所有可用的方法 show: function () { alert('Hello') } }//show属性对应函数 }) </script> </body>
显示效果
示例二
<body> <div id="app"> <!-- Vue 中提供了 v-on: 事件绑定机制 --> <input type="button" value="按钮" :title="mytitle + '123'" v-on:mouseover="show"> </div> <!-- 鼠标覆盖事件 --> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { msg: 'hello指令系统', mytitle: '这是一个自己定义的title', }, methods: { // 这个 methods属性中定义了当前Vue实例所有可用的方法 show: function () { alert('Hello') } }//show属性对应函数 }) </script> </body>
v-on
接收一个需要调用的方法名称,上面例子里的show就是自己定义的方法的名称。在vue中所有的事件都声明在methods中。
注意:v-on有简便写法,可以直接用@替代
`<button @click = ``"clickHandler"``>切换</button>`
v-on 与v-bind结合切换加载class
<style type="text/css"> .box { 100px; height: 100px; background: red; } .box2 { background: green; } </style> </head> <body> <div id="app"> <div class="box" v-bind:class="{box2:isGreen}"></div> <!-- 如果isGreen是true,那么v-bind绑定的属性会自动加入class属性,如果是false,则不会 --> <button @click="changeColor">切换颜色</button> </div> <script src="./lib/vue.js"></script> <script type="text/javascript"> // 指令系统 v-* var app = new Vue({ el: "#app", data: { isGreen: false, }, methods: { changeColor: function () { this.isGreen = !this.isGreen; } } }) </script> </body>
页面显示效果如下
四、更新元素的指令v-text与v-html
1、v-text
v-text等价于 {{}} ,实现原理:innerText。
更新元素的 textContent(**innerText**)
。如果要更新部分的 textContent
,需要使用 {{ Mustache }}
插值。v-text不能出来html标签
<body> <div id="app"> <!--<h3>{{msg}}</h3>--> </div> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { // 数据属性 msg: 'hello指令系统', msg2: '<a href="#">这是我的数据</a>' }, template:` <div> <h4>{{msg}}</h4> <h3 v-text='msg2'></h3> </div> ` }) </script> </body>
显示效果如下所示:
2、v-html
v-html实现原理是js中的innerHTML方法。v-html可以处理标签的替换
更新元素的 innerHTML
。注意:内容按普通 HTML 插入 - 不会作为 Vue 模板进行编译。如果试图使用 v-html
组合模板,可以重新考虑是否通过使用组件来替代。
<body> <div id="app"> <!--<h3>{{msg}}</h3>--> </div> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { // 数据属性 msg: 'hello指令系统', msg2: '<a href="#">这是我的数据</a>' }, template:` <div> <h4>{{msg}}</h4> <h3 v-text='msg2'></h3> <h2 v-html="msg2"></h2> </div> ` }) </script> </body>
显示效果如下所示:
使用v-html需要注意:
1)在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。只在可信内容上使用 v-html
,永不用在用户提交的内容上。
2)在单文件组件里,scoped
的样式不会应用在 v-html
内部,因为那部分 HTML 没有被 Vue 的模板编译器处理。如果你希望针对 v-html
的内容设置带作用域的 CSS,你可以替换为 CSS Modules 或用一个额外的全局 <style>
元素手动设置类似 BEM 的作用域策略。
五、条件渲染指令v-if 与v-show
1、v-if
条件渲染指令,根据表达式的真假来添加或删除元素。其语法结构是:v-if="expression",其中expression是一个返回bool值的表达式,其结果可以直接是true或false,也可以是返回true或false的表达式。
v-else-if
v-else
2、v-show
也是条件渲染指令,不同的是有 v-show 的元素会始终渲染并保持在 DOM 中。和v-if指令不同点在于:v-show是根据表达式之真假值,切换元素的 display CSS 属性,当条件变化时该指令触发过渡效果。
示例
<head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> .box{ color: red; } </style> </head> <body> <div id="app"> <div class="box" v-if="isShow">v-if 控制的元素</div> <div class="box" v-show="isShow">v-show 控制的元素</div> <input type="button" value="切换按钮" v-on:click='toggle'> </div> <script src="./lib/vue.js"></script> <script type="text/javascript"> new Vue({ el: '#app', data: { msg: 'hello指令系统', isShow:true, }, methods:{ toggle:function(){ this.isShow = !this.isShow; } } }) </script> </body>
效果
如上图所示,v-if和v-show的不同就是:带有v-show的元素始终会被渲染并保留在DOM中,v-show只是简单地切换元素的CSS属性display。
3、v-if 与 v-show 的区别
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show
较好;如果在运行时条件很少改变,则使用 v-if
较好。
4、v-else
你可以使用 v-else
指令来表示 v-if
的“else 块”:
<div v-if="Math.random() > 0.5"> Now you see me </div> <div v-else> Now you don't </div>
v-else
元素必须紧跟在带 v-if
或者 v-else-if
的元素的后面,否则它将不会被识别。
5、v-else-if
2.1.0 新增
v-else-if
,顾名思义,充当 v-if
的“else-if 块”,可以连续使用:
<div v-if="type === 'A'"> A </div> <div v-else-if="type === 'B'"> B </div> <div v-else-if="type === 'C'"> C </div> <div v-else> Not A/B/C </div>
类似于 v-else
,v-else-if
也必须紧跟在带 v-if
或者 v-else-if
的元素之后。
六、v-for
基于数据渲染一个列表,类似于JS中的遍历。其数据类型可以是 Array | Object | number | string。
该指令之值,必须使用特定的语法(item, index) in items, 为当前遍历元素提供别名。 v-for的优先级别高于v-if之类的其他指令。
一个对象的 v-for 你也可以用 v-for 通过一个对象的属性来迭代。
// 遍历obj中每个key对应的value <ul> <li v-for="value in obj">{{value}}</li> </ul> // 遍历obj的value和key <ul> <li v-for="(value, key) in obj">{{value}}</li> </ul> // 遍历obj的value、key和索引 <ul> <li v-for="(value, key, index) in obj">{{value}}</li> </ul>
1、v-for遍历普通数组
v-for
指令需要使用 item in items
形式的特殊语法,items
是源数据数组并且 item
是数组元素迭代的别名。
<body> <div id="app"> <!-- <p>{{list[0]}}</p> <p>{{list[1]}}</p> <p>{{list[2]}}</p> <p>{{list[3]}}</p> <p>{{list[4]}}</p> --> <p v-for="(item, i) in list">索引值:{{i}} --- 每一项:{{item}}</p> </div> <script src="./lib/vue.js"></script> <script> // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: { list: [1, 2, 3, 4, 5, 6] }, methods: {} }); </script> </body>
页面显示效果如下:
2、v-for遍历对象数组
<body> <div id="app"> <p v-for="(user, i) in list">Id:{{ user.id }} --- 名字:{{ user.name }} --- 索引:{{i}}</p> </div> <script src="./lib/vue.js"></script> <script> // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: { list: [ { id: 1, name: 'nicholas' }, { id: 2, name: 'jack' }, { id: 3, name: 'pony' }, { id: 4, name: 'lucy' } ] }, methods: {} }); </script> </body>
页面显示效果如下
3、v-for遍历对象
<body> <div id="app"> <!-- 注意:在遍历对象身上的键值对的时候, 除了 有 val key ,在第三个位置还有 一个 索引 --> <p v-for="(val, key, i) in user">值是: {{ val }} --- 键是: {{key}} -- 索引: {{i}}</p> </div> <script src="./lib/vue.js"></script> <script> // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: { user: { id: 1, name: 'nicholas', gender: '男' } }, methods: {} }); </script> </body>
页面显示效果如下
4、v-for迭代数字
<body> <div id="app"> <!-- in 后面我们放过 普通数组,对象数组,对象, 还可以放数字 --> <!-- 注意:如果使用 v-for 迭代数字的话,前面的 count 值从 1 开始 --> <p v-for="count in 10">这是第 {{ count }} 次循环</p> </div> <script src="./lib/vue.js"></script> <script> // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: {}, methods: {} }); </script> </body>
页面显示效果如下
5、v-for中key的作用:为什么使用v-for时必须添加唯一的key属性
key的作用:
key是为了给Vue一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,需要为每项提供一个唯一的key属性。
举个例子
没有加key的情况:
<body> <div id="app" > <div> <input type="text" v-model="name" > <button @click="add">添加</button> </div> <ul> <li v-for="item in list"> <input type="checkbox">ID:{{item.id}} -------name:{{item.name}} </li> </ul> </div> <script> var vm = new Vue({ el:'#app', data:{ name: '', list: [ { id:0,name:'nicholas1号' }, { id:1,name:'nicholas2号' }, { id:2,name:'nicholas3号' } ] }, methods:{ add() { // 1.拼接处一个完整的用户信息对象,包含ID 和name const newUser= {id: this.list.length,name: this.name}; // 2.把拼接出来的用户信息对象 调用this.list.unshift方法把对象追加到数组的第一个 this.list.unshift(newUser); } } }) </script> </body>
没有加key的时候,当我选中第二个“nicholas2号”后,再添加nicholas4号时:
则会出现问题:选中的变成了“nicholas1号”,位置依旧是第二个,很显然这不是我们想要的结果,解决这个问题的方法就是加key属性
加上key的情况:
<body> <div id="app" > <div> <input type="text" v-model="name" > <button @click="add">添加</button> </div> <ul> <li v-for="item in list" :key='item.id'> <!-- 增加key属性 --> <input type="checkbox">ID:{{item.id}} -------name:{{item.name}} </li> </ul> </div> <script> var vm = new Vue({ el:'#app', data:{ name: '', list: [ { id:0,name:'nicholas1号' }, { id:1,name:'nicholas2号' }, { id:2,name:'nicholas3号' } ] }, methods:{ add() { // 1.拼接处一个完整的用户信息对象,包含ID 和name const newUser= {id: this.list.length,name: this.name}; // 2.把拼接出来的用户信息对象 调用this.list.unshift方法把对象追加到数组的第一个 this.list.unshift(newUser); } } }) </script> </body>
加上key以后,当我选中第二个“nicholas2号”后,再添加nicholas4号时:
注意:key的取值必须是number 或 string,不能是对象,而且使用 v-for 循环的每一项的值,都要保证唯一性 。
参考资料