基础指令-2
5、数组更新检测
5.1、变异方法
所谓变异方法,是指在调用了该方法后会改变原本的数组。Vue 包含一组观察数组的变异方法,它们将会触发视图更新。具体包含以下方法:
push():接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度。
pop():从数组末尾移除最后一项,减少数组的 length 值,然后返回移除的项。
shift():移除数组中的第一个项并返回该项,同时数组的长度减 1。
unshift():在数组前端添加任意个项并返回新数组长度。
splice():删除原数组的一部分成员,并可以在被删除的位置添加入新的数组成员。
reverse():用于反转数组的顺序,返回经过排序之后的数组。
sort():调用每个数组项的 toString() 方法,然后比较得到的字符串排序,返回经过排序之后的数组。可以自己定义方法参数
下面我们来看一个具体的示例,如下:
<body>
<div id='app'>
<button @click="addLast">数组最后增加push</button>
<button @click="delLast">数组最后删除pop</button>
<button @click="addFirst">数组最前增加unshift</button>
<button @click="delFirst">数组最前删除shift</button>
<button @click="splice">删除并替换首元素splice</button>
<button @click="reverse">反序数组内容reverse</button>
<button @click="sort">根据id排序sort</button>
<ul>
<li v-for="obj in arr">
{{obj}}
</li>
</ul>
</div>
</body>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
arr: [{
id: 12,
name: "张三",
age: 20
}, {
id: 2,
name: "李四",
age: 28
}, {
id: 34,
name: "王五",
age: 22
}, {
id: 4,
name: "赵六",
age: 34
}]
},
methods: {
addLast: function () {
this.arr.push({
id: 5,
name: "周七",
age: 25
})
},
delLast: function () {
this.arr.pop()
},
addFirst: function () {
this.arr.unshift({
id: 5,
name: "周七",
age: 25
})
},
delFirst: function () {
this.arr.shift()
},
reverse: function () {
this.arr.reverse();
},
splice:function(){
this.arr.splice(0,1,{id:11,name:"jack",age:29})
},
sort:function(){
function idSort(){
return function(a,b){
return a.id - b.id;
}
}
this.arr.sort(idSort());
}
},
})
</script>
5.2、替换数组
除了上面所列举的变异方法以外,JavaScript 中也存在不会改变原来数组的非变异方法。这个时候,我们可以使用新数组来替换旧数组。常见的非变异方法如下:
concat():先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。
slice():基于当前数组中一个或多个项创建一个新数组,接受一个或两个参数,即要返回项的起始和结束位置,最后返回新数组。
map():对数组的每一项运行给定函数,返回每次函数调用的结果组成的数组。
filter():对数组中的每一项运行给定函数,该函数会返回true的项组成的数组。
具体示例如下:
<body>
<div id="app">
<div>
<button @click='concat'>concat</button>
<button @click='slice'>slice</button>
<button @click='map'>map</button>
<button @click='filter'>filter</button>
</div>
<ul>
<li v-for="item in items">
{{ item }}
</li>
</ul>
</div>
</body>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
items: ['刘备', '关羽', '张飞'],
addValue: '赵云'
},
methods: {
concat() {
this.items = this.items.concat(this.addValue); // 拼接新的值
},
slice() {
this.items = this.items.slice(1); // 移除第一个数据
},
map() {
// 每一项数据前面拼接索引
this.items = this.items.map(function (item, index, arr) {
return "<h1>" + index + "--" + item + "</h1>";
})
},
filter() {
// 返回索引大于 0 的数据
this.items = this.items.filter(function (item, index, arr) {
return (index > 0);
});
}
}
})
</script>
5.3、无法检测的数组变化
在 Vue 中无法检测到以下 2 种变异的形式:
- 利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
- 修改数组的长度时,例如:vm.items.length = newLength 不过,针对上面的 2 种情况,我们也有相应的对策。如果要设置数组某一个具体的项目,可以使用 Vue 实例的 set 方法或者splice带有三个参数的替换模式。而如果要改变数组的长度,可以使用 splice 来进行替代。
下面是一个具体的示例,如下:
<body>
<div id="app">
<!-- 特别需要注意的是以下的数组变动方法是不支持的:
通过索引直接设置项:app.books[2] = {...}
修改数组长度:app.books.length = 1 -->
<input type="text" name="" id="" placeholder="请输入书名" v-model='newBookName'>
<input type="text" name="" id="" placeholder="请输入作者" v-model='newBookAuthor'>
<button @click='editOne'>设置第一本书的信息</button>
<p>购买的书如下:</p>
<ul>
<template v-for='(book,index) in books'>
<li>序号:{{index}}</li>
<li>书名:{{book.name}}</li>
<li>作者:{{book.author}}</li>
<li>-------------------------</li>
</template>
</ul>
<button @click='remainOne'>只留下第一本书</button>
</div>
</body>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
newBookName: '', // 和第一个文本框的数据相关联
newBookAuthor: '', // 和第二个文本框的数据相关联
books: [{
'name': '斗破苍穹',
'author': '天蚕土豆'
},
{
'name': '逆天邪神',
'author': '火星引力'
},
{
'name': '斗罗大陆',
'author': '唐家三少'
},
{
'name': '星辰变',
'author': '我吃西红柿'
},
]
},
methods: {
// 如果要设置数组某一个具体的项目,可以使用 Vue 实例的 set 方法
// 或者splice的带三个参数的方法
editOne: function () {
Vue.set(this.books, 0, {
'name': this.newBookName,
'author': this.newBookAuthor
});
//第一个参数表示要替换的起始位置,第二个参数表示要替换几个,第三个参数表示要替换的值
this.books.splice(0,1,{"name":this.newBookName,"author":this.newBookAuthor})
},
// 如果要改变数组的长度,可以使用splice来进行替代
remainOne: function () {
//如果splice只有一个参数表示删除,从参数位置开始,往后全部删除
this.books.splice(1);
}
}
});
</script>
6、v-on
v-on
用来添加事件,前面我们已经用过很多次了,这个指令可以简写,我们绑定事件可以写成下面这样
<!-- 绑定点击事件 -->
<button @click=‘fn1’>点击1</button>
<!-- 绑定鼠标移入事件 -->
<div @mouseover='fn2'>点击2</div>
7、v-bind
v-bind
用来绑定属性,它也有简写的形式
<!-- 绑定一个href属性
注意单引号,因为vue绑定认为里面是一个变量的值
-->
<a v-bind:href="'http://www.baidu.com'">百度一下</a>
<!-- 可以简写成下面的形式 -->
<a :href="'http://www.baidu.com'">百度一下</a>
<!-- 绑定src属性 -->
<img :src="'images/xxx.jpg'">
8、v-model
v-model
可以在表单控件或者组件上创建双向绑定
<body>
<div id='app'>
<input type="text" v-model="message">
<p>{{message}}</p>
</div>
</body>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
message:"Hello Vue!",
}
})
</script>
再比如下面的示例:
<body>
<div id='app'>
<input type="text" v-model="url" style="width: 200px">
<a :href="url">跳转</a>
<p>{{url}}</p>
</div>
</body>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
url:"http://www.baidu.com"
}
})
</script>
9、v-pre
跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签(也就是{{}})。跳过大量没有指令的节点会加快编译。通俗的说,加了这个指令,元素和它的子元素将不会被编译
<span v-pre>{{ message }}</span>
10、v-cloak
如果网页显示较慢,{{}}在页面还未加载完成的时候,总会显示在页面上。如果想屏蔽掉这种情况,可以使用v-cloak
<body>
<div id='app'>
<input type="text" v-model="url" style="width: 200px" v-cloak>
<a :href="url" v-cloak>跳转</a>
<p v-cloak>{{url}}</p>
</div>
</body>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
setTimeout(() => {
let vm = new Vue({
el: '#app',
data: {
url:"http://www.baidu.com"
}
})
}, 3000);
</script>
11、v-once
只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
<body>
<div id='app'>
<p v-once>{{message}}</p>
<button @click="change()">点击</button>
</div>
</body>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
message:"Hello",
arr: ["Hello Vue!","Hello Jack!","Hello World!","Hello Mr.Yan","Hello,Hello!"]
},
methods: {
change:function(){
let r = Math.floor(Math.random() * this.arr.length);
this.message = this.arr[r];
}
},
})
</script>
Comments