Vue全套视频教程vite版,Vue2+Vue3快速上手,一套通透

老杜Vue学习笔记
第二章 Vue 核心技术
2.1 事件处理
2.1.1 事件处理的核心语法
(1) 指令的语法格式:<标签 v-指令名:参数=”表达式”></标签>
(2) 事件绑定的语法格式:v-on:事件名。例如鼠标单击事件的绑定使用 v-on:click。
(3) 绑定的回调函数需要在 Vue 实例中使用 methods 进行注册。methods 可以配置多个回调函数,采用逗号隔开。
(4) 绑定回调函数时,如果回调函数没有参数,( )可以省略。
(5) 每一个回调函数都可以接收一个事件对象 event。
(6) 如果回调函数有参数,并且还需要获取事件对象,可以使用$event 进行占位。
(7) v-on:click 可以简写为@click。简写的语法格式:@事件名
(8) 回调函数中的 this 是 vm。如果回调函数是箭头函数的话,this 是 window 对象,因为箭头函数没有自己的 this,它的 this 是继承过来的,默认这个 this 是箭头函数所在的宿主对象。这个宿主对象其实就是它的父级作用域。
而对象又不能构成单独的作用域,所以这个父级作用域是全局作用域,也就是 window。
(9) 回调函数并没有在 vm 对象上,为什么通过 vm 可以直接调用函数呢?尝试手写 Vue 框架。
(10) 可以在函数中改变 data 中的数据,例如:this.counter++,这样会联动页面上产生动态效果。
2.1.2 事件修饰符
(1) .stop - 调用 event.stopPropagation()。
1. <div @click="san">
2.<div @click.stop="er">
3.<button @click="yi">{{name}}</button>
4.</div>
5. </div>
(2) .prevent - 调用 event.preventDefault()。
1. <a href="http://www.bjpowernode.com" @click.prevent="yi">
2. {{name}}
3. </a>
(3) .capture - 添加事件侦听器时使用 capture 模式。
1. <div @click.capture="san">
2.<div @click.capture="er">
3.<button @click="yi">{{name}}</button>
4.</div>
5. </div>
注意:只有添加了 capture 修饰符的元素才会采用捕获模式。(或者说带有 capture 修饰符的优先触发)
(4) .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
1. <div @click="san">
2.<div @click.self="er">
3.<button @click="yi">{{name}}</button>
4.</div>
5. </div>
(5) .once - 只触发一次回调。
1. <button @click.once="yi">
2.{{name}}
3. </button>
(6) .passive - (2.3.0) 以 { passive: true } 模式添加侦听器
①无需等待,直接继续(立即)执行事件默认行为。(对 wheel 事件有效果)
②.passive 和 .prevent 修饰符不能共存。
2.1.3 按键修饰符
1. 常用的按键修饰符包括:
(1) .enter
(2) .tab (只能配合 keydown 使用)
(3) .delete (捕获“删除”和“退格”键)
(4) .esc
(5) .space
(6) .up
(7) .down
(8) .left
(9) .right
2. 可以直接将 KeyboardEvent.key 暴露的任意有效按键名转换为 kebab-case 来作为修饰符。
<input type=”text” @keyup.page-down=”getInfo”>
3. 可以通过全局 config.keyCodes 对象自定义按键修饰符别名
Vue.config.keyCodes.huiche = 13
2.1.4 系统修饰键
1. 系统修饰键包括 4 个
(1) .ctrl
(2) .alt
(3) .shift
(4) .meta
2. 系统修饰键在使用时应注意:
(1) 只有当系统修饰键和其他键组合使用,并且组合键释放时,才会触发 keyup 事件。
(2) 只要按下系统修饰键,就会触发 keydown 事件。
3. 小技巧
(1) <input type=”text” @keyup.ctrl.c=”getInfo”/>
2.2 计算属性
1. 案例:用户输入信息,然后翻转用户输入的字符串。
(1) 插值语法可以实现,但是有三个问题
1、代码可读性差
2、代码不可复用
3、代码难以维护
(2) 可以使用 methods 方式实现,存在 1 个问题
1、效率低,即使数据没有发生变化,但每一次仍然会调用 method。
(3) 使用计算属性可以解决以上问题。
2. 什么是计算属性?
data 中的是属性。用 data 的属性经过计算得出的全新的属性就是计算属性。
3. 计算属性的使用
1. <div id="app">
2.<h1>{{msg}}</h1>
3.输入的信息:<input type="text" v-model="info"><br>
4.反转的信息:{{reversedInfo}} <br>
5.反转的信息:{{reversedInfo}} <br>
6.反转的信息:{{reversedInfo}} <br>
7.反转的信息:{{reversedInfo}} <br>
8. </div>
9. <script>
10.const vm = new Vue({
11.el : '#app',
12.data : {
13.msg : '计算属性-反转字符串案例',
14.info : ''
15.},
16.computed : {
17.reversedInfo:{
18.get(){
19.console.log('getter 被调用了');
20.return this.info.split('').reverse().join('')
21.},
22.set(val){
23.//this.reversedInfo = val // 不能这样做,这样会导致无限递归
24.this.info = val.split('').reverse().join('')
25.}
26.}
27.}
28.})
29. </script>
(1) 计算属性需要使用:computed
(2) 计算属性通过 vm.$data 是无法访问的。计算属性不能通过 vm.$data 访问。
(3) 计算属性的 getter/setter 方法中的 this 是 vm。
(4) 计算属性的 getter 方法的调用时机:
①第一个时机:初次访问该属性。
②第二个时机:计算属性所依赖的数据发生变化时。
(5) 计算属性的 setter 方法的调用时机:
①当计算属性被修改时。(在 setter 方法中通常是修改属性,因为只有当属性值变化时,计算属性的值就会联动更新。注意:计算属性的值被修改并不会联动更新属性的值。)
(6) 计算属性没有真正的值,每一次都是依赖 data 属性计算出来的。
(7) 计算属性的 getter 和 setter 方法不能使用箭头函数,因为箭头函数的 this 不是 vm。而是 window。
4. 计算属性的简写形式
只考虑读取,不考虑修改时,可以启用计算属性的简写形式。
1. computed : {
2.reversedInfo(){
3.console.log('getter 被调用了');
4.return this.info.split('').reverse().join('')
5.}
6. }
2.3 侦听属性的变化
1. 侦听属性的变化其实就是监视某个属性的变化。当被监视的属性一旦发生改变时,执行某段代码。
2. 监视属性变化时需要使用 watch 配置项。
使用 watch 实现:比较数字大小的案例
1. <div id="app">
2.<h1>{{msg}}</h1>
3.数值 1:<input type="text" v-model="number1"><br>
4.数值 2:<input type="text" v-model="number2"><br>
5.比较大小:{{compareResult}}
6. </div>
7. <script>
8.const vm = new Vue({
9.el : '#app',
10.data : {
11.msg : '侦听属性的变化',
12.number1 : 1,
13.number2 : 1,
14.compareResult : ''
15.},
16.watch : {
17.number1 : {
18.immediate : true,
19.handler(newVal, oldVal){
20.let result = newVal - this.number2
21.if(result > 0){
22.this.compareResult = newVal + '>' + this.number2
23.}else if(result < 0){
24.this.compareResult = newVal + '<' + this.number2
25.}else{
26.this.compareResult = newVal + '=' + this.number2
27.}
28.}
29.},
30.number2 : {
31.immediate : true,
32.handler(newVal, oldVal){
33.let result = this.number1 - newVal
34.if(result > 0){
35.this.compareResult = this.number1 + '>' + newVal
36.}else if(result < 0){
37.this.compareResult = this.number1 + '<' + newVal
38.}else{
39.this.compareResult = this.number1 + '=' + newVal
40.}
41.}
42.}
43.}
44.})
45. </script>
运行效果:



3. 如何深度监视:
(1) 监视多级结构中某个属性的变化,写法是:’a.b.c’ : {}。注意单引号哦。
(2) 监视多级结构中所有属性的变化,可以通过添加深度监视来完成:deep : true
4. 如何后期添加监视:
(1) 调用 API:vm.$watch(‘number1’, {})
5. watch 的简写:
(1) 简写的前提:当不需要配置 immediate 和 deep 时,可以简写。
(2) 如何简写?
①watch:{ number1(newVal,oldVal){}, number2(newVal, oldVal){} }
(3) 后期添加的监视如何简写?
①vm.$watch(‘number1’, function(newVal, oldVal){})
6. computed 和 watch 如何选择?
(1) 以上比较大小的案例可以用 computed 完成,并且比 watch 还要简单。所以要遵守一个原则:computed
和 watch 都能够完成的,优先选择 computed。
(2) 如果要开启异步任务,只能选择 watch。因为 computed 依靠 return。watch 不需要依赖 return。
7. 关于函数的写法,写普通函数还是箭头函数?
(1) 不管写普通函数还是箭头函数,目标是一致的,都是为了让 this 和 vm 相等。
(2) 所有 Vue 管理的函数,建议写成普通函数。
(3) 所有不属于 Vue 管理的函数,例如 setTimeout 的回调函数、Promise 的回调函数、AJAX 的回调函数,
建议使用箭头函数。
2.4 class 与 style 绑定
数据绑定的一个常见需求场景是操纵元素的 CSS class 列表和内联样式。因为 class 和 style 都是 attribute,我们
可以和其他 attribute 一样使用 v-bind 将它们和动态的字符串绑定。但是,在处理比较复杂的绑定时,通过拼接
生成字符串是麻烦且易出错的。因此,Vue 专门为 class 和 style 的 v-bind 用法提供了特殊的功能增强。除了字
符串外,表达式的值也可以是对象或数组。
2.4.1 class 绑定
2.4.1.1 绑定字符串
适用于样式的名字不确定,需要动态指定。
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4.<meta charset="UTF-8">
5.<title>class 绑定字符串形式</title>
6.<script src="../js/vue.js"></script>
7.<style>
8..static{
9.border: 1px solid black;
10.background-color: beige;
11.}
12..big{
13.width: 200px;
14.height: 200px;
15.}
16..small{
17.width: 100px;
18.height: 100px;
19.}
20.</style>
21.</head>
22.<body>
23.<div id="app">
24.<h1>{{msg}}</h1>
25.<div class="static" :class="c1"></div>
26.</div>
27.<script>
28.const vm = new Vue({
29.el : '#app',
30.data : {
31.msg : 'class 绑定字符串形式',
32.c1 : 'small'
33.}
34.})
35.</script>
36.</body>
37.</html>
运行效果:

使用 vue 开发者工具修改 c1 的 small 为 big:

通过测试可以看到样式完成了动态的切换。
2.4.1.2 绑定数组
适用于绑定的样式名字不确定,并且个数也不确定。
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4.<meta charset="UTF-8">
5.<title>class 绑定数组形式</title>
6.<script src="../js/vue.js"></script>
7.<style>
8..static{
9.border: 1px solid black;
10.}
11..active{
12.background-color: green;
13.}
14..text-danger{
15.color: red;
16.}
17.</style>
18.</head>
19.<body>
20.<div id="app">
21.<h1>{{msg}}</h1>
22.<div class="static" :class="['active','text-danger']">
数组形式</div>
23.<br><br>
24.<div class="static" :class="[activeClass,errorClass]">
数组形式</div>
25.<br><br>
26.<div class="static" :class="classArray">数组形式</div>
27.</div>
28.<script>
29.const vm = new Vue({
30.el : '#app',
31.data : {
32.msg : 'class 绑定数组形式',
33.activeClass : 'active',
34.errorClass : 'text-danger',
35.classArray : ['active', 'text-danger']
36.}
37.})
38.</script>
39.</body>
40.</html>
运行效果:

使用 vue 开发者工具删除数组中的一个样式:

2.4.1.3 绑定对象
适用于样式名字和个数都确定,但是要动态决定用或者不用。
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4.<meta charset="UTF-8">
5.<title>class 绑定对象形式</title>
6.<script src="../js/vue.js"></script>
7.<style>
8..static{
9.border: 1px solid black;
10.}
11..active{
12.background-color: green;
13.}
14..text-danger{
15.color: red;
16.}
17.</style>
18.</head>
19.<body>
20.<div id="app">
21.<h1>{{msg}}</h1>
22.<div class="static" :class="{active : true, 'text-dang
er' : true}">对象形式</div>
23.<br><br>
24.<div class="static" :class="classObject">对象形式
</div>
25.</div>
26.<script>
27.const vm = new Vue({
28.el : '#app',
29.data : {
30.msg : 'class 绑定对象形式',
31.classObject : {
32.active : true,
33.text-danger' : false
34.}
35.}
36.})
37.</script>
38.</body>
39.</html>
运行效果:

使用 vue 开发者工具修改 text-danger 为 true:

2.4.2 style 绑定
2.4.2.1 绑定对象
1. <div id="app">
2.<h1>{{msg}}</h1>
3.<!-- 静态写法 -->
4.<div class="static" style="font-size: 20px;">对象形式
</div><br><br>
5.<!-- 动态写法 1 -->
6.<div class="static" :style="{fontSize: 40 + 'px'}">对象形式
</div><br><br>
7.<!-- 动态写法 2 -->
8.<div class="static" :style="styleObject">对象形式
</div><br><br>
9. </div>
10.<script>
11.const vm = new Vue({
12.el : '#app',
13.data : {
14.msg : 'style 绑定对象形式',
15.styleObject : {
16.fontSize : '40px'
17.}
18.}
19.})
20.</script>
2.4.2.2 绑定数组
1. <div id="app">
2.<h1>{{msg}}</h1>
3.<!-- 静态写法 -->
4.<div class="static" style="font-size: 40px; color: red;">数
组形式</div><br><br>
5.<!-- 动态写法 1 -->
6.<div class="static" :style="[{fontSize:'40px'},{color:'red
'}]">数组形式</div><br><br>
7.<!-- 动态写法 2 -->
8.<div class="static" :style="styleArray">对象形式
</div><br><br>
9. </div>
10.<script>
11.const vm = new Vue({
12.el : '#app',
13.data : {
14.msg : 'style 绑定对象形式',
15.styleArray : [
16.{fontSize:'40px'},
17.{color:'red'}
18.]
19.}
20.})
21.</script>
2.5 条件渲染
2.5.1 v-if
指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 true 时才被渲染
1. <div id="app">
2.<h1>{{msg}}</h1>
3.温度:<input type="number" v-model="temprature"><br>
4.天气:
5.<span v-if="temprature <= 10">寒冷</span>
6.<span v-if="temprature > 10 && temprature <= 25">凉爽
</span>
7.<span v-if="temprature > 25">炎热</span>
8. </div>
9. <script>
10.const vm = new Vue({
11.el : '#app',
12.data : {
13.msg : '条件渲染',
14.temprature : 10
15.}
16.})
17.</script>
运行效果:


2.5.2 v-else-if、v-else
顾名思义,v-else-if 提供的是相应于 v-if 的“else if 区块”。它可以连续多次重复使用。
一个使用 v-else-if 的元素必须紧跟在一个 v-if 或一个 v-else-if 元素后面。
你也可以使用 v-else 为 v-if 添加一个“else 区块”,当然,v-else 元素也是必须紧跟在一个 v-if 或一个 v-else-if 元素
后面。
1. <div id="app">
2.<h1>{{msg}}</h1>
3.温度:<input type="number" v-model="temprature"><br>
4.天气:
5.<span v-if="temprature <= 10">寒冷</span>
6.<span v-else-if="temprature <= 25">凉爽</span>
7.<span v-else>炎热</span>
8. </div>
9. <script>
10.const vm = new Vue({
11.el : '#app',
12.data : {
13.msg : '条件渲染',
14.temprature : 10
15.}
16.})
17.</script>
2.5.3 <template>与 v-if
因为 v-if 是一个指令,他必须依附于某个元素。但如果我们想要切换不止一个元素呢?在这种情况下我们可以在一个 <template> 元素上使用 v-if,这只是一个不可见的包装器元素,最后渲染的结果并不会包含个 <template> 元素。v-else 和 v-else-if 也可以在 <template> 上使用。
1. <div id="app">
2.<h1>{{msg}}</h1>
3.温度:<input type="number" v-model="temprature"><br>
4.天气:
5.<template v-if="temprature <= 10">
6.<span>寒冷</span>
7.</template>
8.<template v-else-if="temprature <= 25">
9.<span>凉爽</span>
10.</template>
11.<template v-else>
12.<span>炎热</span>
13.</template>
14.</div>
15.<script>
16.const vm = new Vue({
17.el : '#app',
18.data : {
19.msg : '条件渲染',
20.temprature : 10
21.}
22.})
23.</script>
2.5.4 v-show
另一个可以用来按条件显示一个元素的指令是 v-show。其用法基本一样:
1. <div id="app">
2.<h1>{{msg}}</h1>
3.温度:<input type="number" v-model="temprature"><br>
4.天气:
5.<span v-show="temprature <= 10">寒冷</span>
6.<span v-show="temprature > 10 && temprature <= 25">凉爽
</span>
7.<span v-show="temprature > 25">炎热</span>
8. </div>
9. <script>
10.const vm = new Vue({
11.el : '#app',
12.data : {
13.msg : '条件渲染',
14.temprature : 10
15.}
16.})
17.</script>
不同之处在于 v-show 会在 DOM 渲染中保留该元素;v-show 仅切换了该元素上名为 display 的 CSS 属性。
v-show 不支持在 <template> 元素上使用,也不能和 v-else 搭配使用。
2.5.5 v-if VS v-show
v-if 是“真实的”按条件渲染,因为它确保了在切换时,条件区块内的事件监听器和子组件都会被销毁与重建
v-if 也是惰性的:如果在初次渲染时条件值为 false,则不会做任何事。条件区块只有当条件首次变为 true 时才被渲染。
相比之下,v-show 简单许多,元素无论初始条件如何,始终会被渲染,只有 CSS display 属性会被切换。
总的来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要频繁切换,则使用 v-show 较好;如果在运行时绑定条件很少改变,则 v-if 会更合适。
2.6 列表渲染
语法格式:v-for 指令。该指令用在被遍历的标签上。
1. v-for="(element, index) in elements" :key="element.id"
或者
1.v-for="(element, index) of elements" :key="element.id"
2.6.1 遍历数组、对象、字符串、指定次数
1. 遍历数组
1. <div id="app">
2.<h1>{{msg}}</h1>
3.<h2>遍历数组</h2>
4.<ul>
5.<li v-for="(product, index) in products" :key="product.
id">
6.商品名称:{{product.name}},单价:{{product.price}}元/
千克,下标:{{index}}
7.</li>
8.</ul>
9. </div>
10.<script>
11.const vm = new Vue({
12.el : '#app',
13.data : {
14.msg : '列表渲染',
15.products : [
16.{id:'111',name:'西瓜',price:20},
17.{id:'222',name:'苹果',price:10},
18.{id:'333',name:'香蕉',price:30}
19.]
20.}
21.})
22.</script>
运行效果:

2. 遍历对象
1. <div id="app">
2.<h1>{{msg}}</h1>
3.<h2>遍历对象</h2>
4.<ul>
5.<li v-for="(propertyValue, propertyName) of dog" :key=
"propertyName">
6.{{propertyName}}:{{propertyValue}}
7.</li>
8.</ul>
9. </div>
10.<script>
11.const vm = new Vue({
12.el : '#app',
13.data : {
14.msg : '列表渲染',
15.dog : {
16.name : '拉布拉多',
17.age : 3,
18.gender : '雄性'
19.}
20.}
21.})
22.</script>
运行结果:

3. 遍历字符串
1. <div id="app">
2.<h1>{{msg}}</h1>
3.<h2>遍历字符串</h2>
4.<ul>
5.<li v-for="char,index of str" :key="index">
6.{{index}}:{{char}}
7.</li>
8.</ul>
9. </div>
10.<script>
11.const vm = new Vue({
12.el : '#app',
13.data : {
14.msg : '列表渲染',
15.str : '动力节点'
16.}
17.})
18.</script>
运行结果:

4. 遍历指定次数
1. <div id="app">
2<h1>{{msg}}</h1>
3.<h2>遍历指定次数</h2>
4.<ul>
5.<li v-for="number,index of 10" :key="index">
6.下标:{{index}},数字:{{number}}
7.</li>
8.</ul>
9. </div>
10.<script>
11.const vm = new Vue({
12.el : '#app',
13.data : {
14.msg : '列表渲染'
15.}
16.})
17.</script>
运行结果:

2.6.2 虚拟 dom 和 diff 算法
所谓的虚拟 dom 就是内存当中的 dom 对象。vue 为了提高渲染的效率,只有真正改变的 dom 元素才会重新渲染。

2.6.3 v-for 的 key 的作用以及实现原理
1. 用 index 作为 key
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4.<meta charset="UTF-8">
5.<title>key 的原理</title>
6.<script src="../js/vue.js"></script>
7. </head>
8. <body>
9.<div id="app">
10.<h1>{{msg}}</h1>
11.<button @click="addFirst">在数组第一个位置添加 tom</button>
12.<button @click="addLast">在数组最后位置添加 vue</button>
13.<table>
14.<tr>
15.<th>序号</th>
16.<th>姓名</th>
17.<th>邮箱</th>
18.<th>选择</th>
19.</tr>
20.<tr v-for="(vip,index) of vips" :key="index">
21.<td>{{index + 1}}</td>
22.<td>{{vip.name}}</td>
23.<td>{{vip.email}}</td>
24.<td><input type="checkbox"></td>
25.</tr>
26.</table>
27.</div>
28.<script>
29.const vm = new Vue({
30.el : '#app',
31.data : {
32.msg : 'key 原理(虚拟 dom 与 diff 算法)',
33.vips : [
34.{id:'100',name:'jack',email:'jack@123.com'},
35.{id:'200',name:'lucy',email:'lucy@123.com'},
36.{id:'300',name:'james',email:'james@123.com'}
37.]
38.},
39.methods : {
40.addFirst(){
41.this.vips.unshift({id:'400',name:'tom',email:'tom@123.com'})
42.},
43.addLast(){
44.this.vips.push({id:'500',name:'vue',email:'vue@123.com'})
45.}
46.}
47.})
48.</script>
49. </body>
50. </html>
运行效果:

全部选中:

添加 tom:

可以看到错乱了。思考这是为什么?
2. 用 vip.id 作为 key
运行和测试结果正常,没有出现错乱。为什么?

3. key 的作用
key 存在于虚拟 dom 元素中,代表该虚拟 dom 元素的唯一标识(身份证号)。
4. diff 算法是如何比较的?
新的虚拟 dom 和旧的虚拟 dom 比较时,先拿 key 进行比较:
(1) 如果 key 相同:则继续比较子元素:
①子元素不同:直接将新的虚拟 dom 元素渲染到页面生成新的真实 dom 元素。
②子元素相同:直接复用之前的真实 dom。
(2) 如果 key 不同:直接将新的虚拟 dom 元素渲染到页面生成新的真实 dom 元素。
5. index 作为 key 存在两个问题
(1) 效率较低。
(2) 对数组的非末尾元素进行增删时,容易错乱。
6. index 作为 key 和 vip.id 作为 key 对比
当 index 作为 key 时:

当 vip.id 作为 key 时:

2.7 列表过滤
使用 watch 和 computed 分别进行实现:
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4.<meta charset="UTF-8">
5.<title>列表过滤</title>
6.<script src="../js/vue.js"></script>
7.<style>
8.table,tr,th,td{
9.border: 1px solid blue;
10.}
11.</style>
12.</head>
13.<body>
14.<div id="app">
15.<h1>{{msg}}</h1>
16.<input type="text" placeholder="请输入搜索关键词
" v-model="keyword">
17.<table>
18.<tr>
19.<th>序号</th>
20.<th>姓名</th>
21.<th>邮箱</th>
22.</tr>
23.<tr v-for="(vip,index) of filterVips" :key="vip.id
">
24.<td>{{index+1}}</td>
25.<td>{{vip.name}}</td>
26.<td>{{vip.email}}</td>
27.</tr>
28.</table>
29.</div>
30.<script>
31.const vm = new Vue({
32.el : '#app',
33.data : {
34.keyword : '',
35.msg : '列表过滤',
36.vips : [
37.{id:'100',name:'jack',email:'jack@123.com'}
,
38.{id:'200',name:'lucy',email:'lucy@123.com'}
,
39.{id:'300',name:'james',email:'james@123.co
m'}
40.],
41.//filterVips : []
42.},
43./* watch : {
44.keyword : {
45.immediate : true,
46.handler(newValue, oldValue){
47.this.filterVips = this.vips.filter((v)
=> {
48.return v.name.indexOf(newValue) >=
0
49.})
50.}
51.}
52.}, */
53.computed : {
54.filterVips(){
55.return this.vips.filter((v) => {
56.return v.name.indexOf(this.keyword) >=
0
57.})
58.}
59.}
60.})
61.</script>
62.</body>
63.</html>
2.8 列表排序
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4.<meta charset="UTF-8">
5.<meta http-equiv="X-UA-Compatible" content="IE=edge">
6.<meta name="viewport" content="width=device-width, initial-scale=1.0">
7.<title>列表排序</title>
8.<script src="../js/vue.js"></script>
9.<style>
10.table,tr,td,th{
11.border:1px solid black;
12.}
13.</style>
14. </head>
15. <body>
16.<div id="app">
17.<h1>{{msg}}</h1>
18.<input type="text" placeholder="输入关键字搜索" v-model="keyword"><br>
19.<button @click="type = 1">按照名字升序</button><br>
20.<button @click="type = 2">按照名字降序</button><br>
21.<button @click="type = 0">按照名字原始顺序</button><br>
22.<table>
23.<tr>
24.<th>序号</th>
25.<th>姓名</th>
26.<th>邮箱</th>
27.<th>操作</th>
28.</tr>
29.<tr v-for="(vip, index) in filterVips" :key="vip.id">
30.<td>{{index+1}}</td>
31.<td>{{vip.name}}</td>
32.<td>{{vip.email}}</td>
33.<td><input type="checkbox"></td>
34.</tr>
35.</table>
36.</div>
37.<script>
38.const vm = new Vue({
39.el : '#app',
40.data : {
41.msg : '列表排序',
42.vips : [
43.{id:'100',name:'jack',email:'jack@123.com'},
44.{id:'200',name:'lucy',email:'lucy@123.com'},
45.{id:'300',name:'james',email:'james@123.com'},
46.{id:'400',name:'lilei',email:'lilei@123.com'},
47.],
48.keyword : '',
49.type : 0
50.},
51.computed : {
52.filterVips(){
53.// 筛选
54.let arr = this.vips.filter((vip) => {
55.return vip.name.indexOf(this.keyword) >= 0
56.})
57.// 根据排序类型进行排序
58.if(this.type){
59.arr.sort((v1, v2) => {
60.console.log('@')
61.return this.type == 1 ? v1.name.localeCompare(v2.name) : v2.nam
e.localeCompare(v1.name)
62.})
63.}
64.// 返回
65.return arr
66.}
67.}
68.})
69.</script>
70. </body>
71.</html>