Vue核心

Vue

vue 的使用有两种方式:安装、使用CDN

CDN 方式: 通过script 标签引入

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

 

Vue 基础语法

1.创建一个Vue对象

通过new 关键字,Vue对象中有 几个比较重要的属性

  • el :模板 ,用来绑定视图,用 #视图id 占位

  • data:向视图中绑定数据

  • methods:该vue对象的方法

2.在视图中用 {{}} 可以使用 data 中的数据

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--导入vue-->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
</head>
<body>
<div id="divvue">
    {{message}}
</div>
​
<script>
<!--    创建vue对象-->
    var vm = new Vue({
        el: "#divvue",
        data: {
            message: "this is first vue"
        }
    });
</script>
</body>
</html>
  • Vue和容器 是一一对应的

  • 真实开发中只有一个Vue实例

  • {{}} 中要写js表达式,并且可以读取到实例的data的任何值

  • 另外一种方式指定vue实例的容器是 调用 vm.$mount('#divvue')

  • 此处的data是对象式写法,此外data还可以写成函数式,必须返回值

    data:function(){
        return{
            name:"xxx"
        }
    }

    这个data函数是Vue所管理的函数,一定不要写成箭头函数,因为写成箭头函数this就不再是vue实例了

 

3.v-band 绑定数据

<body>
<div id="divvue">
    <span v-bind:title="message">
        将鼠标悬停在此,查看详细信息!
    </span>
</div>
​
<script>
<!--    创建vue对象-->
    var vm = new Vue({
        el: "#divvue",
        data: {
            message: "this is first vue"
        }
    });
</script>
</body>
  • 在span标签上用v-band绑定到它的 title属性,内容还是message

  • v-bind 可以给标签里的任意属性动态绑定值

  • v-bind: 可以简写成 : (v-bind:span ----> :span)

 

 

4.条件渲染 v-if v-else

v-if、v-else、v-else-if是一组判断必须挨在一起,不能被打断

<body>
<div id="divvue">
    <h3 v-if="flag">{{message}}</h3>
    <h3 v-else> Have not Message</h3>
</div>
​
<script>
<!--    创建vue对象-->
    var vm = new Vue({
        el: "#divvue",
        data: {
            message: "this is first vue",
            flag: true
        }
    });
</script>
</body>

使用v-show 做条件渲染,v-show中可以放boolean值,也可放表达式或 对象

v-if 和 v-show的区别

v-if 对于不展示的DOM元素直接删除。v-show不展示的DOM元素不移除,而是隐藏

 

5.列表渲染 v-for

<body>
<div id="divvue">
    <li v-for="(item,index) in student" :key="index">
        {{item.name}}-----{{index}}
    </li>
</div>
​
<script>
<!--    创建vue对象-->
    var vm = new Vue({
        el: "#divvue",
        data: {
            message: "this is first vue",
            student:[
                {name: '小明'},
                {name: '小红'}
            ]
        }
    });
</script>
</body>
  • 想生成多个谁就在谁身上用 v-for

  • 最好在遍历的后面,写上:key,并且必须是唯一的

  • v-for 还可以遍历对象,遍历对象时,item是 对象的value,index是对象的key

v-for中的 key

vue根据模板先生成虚拟DOM,然后根据虚拟DOM 生成真实DOM,key就用于虚拟DOM

  1. 虚拟DOM 中 key的作用

    • key是虚拟DOM的标识,当状态中的数据发生变化时,Vue会根据新数据生成新的虚拟FOM

      随后Vue 进行新虚拟DOM 和 旧虚拟DOM 的差异比较

  2. 差异比较的 规则

    • 旧的虚拟DOM中找到了与新虚拟DOM相同的 key

      • 如果虚拟DOM中的内容没变,直接使用之前的真实DOM

      • 如果虚拟DOM 中的内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM

    • 旧的虚拟DOM 中未找到与 新虚拟DOM相同的Key,则创建新的真实DOM,渲染到页面

  3. 用 index作为key可能会引发的问题

    • 若对数据进行逆序添加或删除等破坏顺序的操作,最产生没有必要的真实DOM 更新,如果结构中还包括输入类的DOM,就会产生错误的DOM更新,界面会出问题

  4. 开发中如何选择key

    • 最好使用每条数据的唯一标识作为key

    • 如果不存在对数据的逆序添加或删除等破坏顺序操作,用index作为key是没有问题的

    • 如果不写 key,在生成虚拟DOM时,会自动将 index 作为 key

 

 

Vue绑定事件

在vue对象中的属性 methods,方法需要定义在里面

在视图中 用 v-on 来绑定事件,比如点击事件等等

<body>
<div id="divvue">
    <button v-on:click="alertMessage">点击弹出</button>
</div>
​
<script>
<!--    创建vue对象-->
    var vm = new Vue({
        el: "#divvue",
        data: {},
        methods: {
            alertMessage:function () {
                alert(this.message)
            }
        }
    });
</script>
</body>
  • 使用v-on:xxx 绑定事件,简写是 @xxx

  • 事件回调需要配置在methods对象中

  • methods中配置的函数,不要使用箭头函数,否则this就不是vm了

  • @click=“alertMessage” 和 @click="alertMessage($event)" 效果一致,后者可以传参

事件修饰符

  • prevent 阻止默认事件

  • stop 阻止事件冒泡

  • once 事件只触发一次

  • capture 使用事件的捕获模式

  • self 只有event.target 是当前操作的元素时才触发事件

  • passive 事件的默认行为立即执行,无需等待时间回调执行完毕

键盘事件

  1. 键盘事件常用的有两种 keydown和 keyup 分别是 按键 按下和弹起时去执行的事件

  2. 键盘事件对应的也有修饰符,在按下这些键位之后才去执行绑定的事件,常用修饰符有九个enter、delete、esc、sapce、tab、up、down、left、right,注意这些只是vue起的别名,用它原来的名字 如Enter 也是可以的

  3. 其中 tab 比较特殊 必须搭配 keydown 去使用,因为当你按下tab还未抬起时,焦点就切换到下一个了,当抬起时,焦点已不在原来的位置

  4. 使用系统修饰符 ctrl、alt、shift、meta 时,搭配 keyup使用时在按下修饰键的同时,在按下其他键,然后松开其他键,事件才触发,搭配keydown使用正常触发,在系统提示符后面可以继续追加按键,代表的就是 哪两个键一起按触发事件

<body>
<div id="root">
    <input type="text" placeholder="请输入" @keyup.enter="showInput">
</div>
​
<script>
    const vm = new Vue({
        el:"#root",
        methods:{
            showInput(e){
                console.log(e.target.value);
            }
        }
    })
</script>
</body>

这段代码的含义就是 在输入框中输入内容按下 回车键,会在控制台输出内容

 

Vue 双向绑定

使用 v-model vue中的数据可以跟着视图的改变而改变

<body>
<div id="divvue">
    <input type="text" v-model="message">{{message}}

    <input type="radio" name="sex" value="男" v-model="sex">男
    <input type="radio" name="sex" value="女" v-model="sex">女
    {{sex}}
    <input type="checkbox" name="hobby" value="写代码" v-model="hobby">写代码
    <input type="checkbox" name="hobby" value="唱歌" v-model="hobby">唱歌
    <input type="checkbox" name="hobby" value="跳舞" v-model="hobby">跳舞
    {{hobby}}
</div>

<script>
    <!--    创建vue对象-->
    var vm = new Vue({
        el: "#divvue",
        data: {
            message: "",
            sex:"",
            hobby:[]
        }
    });
</script>
</body>
  • v-model 叫做双向绑定,一般都应用在表单元素上

  • v-model:value 可以简写为v-model ,因为v-model默认收集的就是value值

  • v-model.number 该修饰符保证收集到用户的表单后,数字类型的数据,收集到依旧是数字类型,不加该修饰符,就会变成字符类型

  • v-model.lazy 该修饰符是让表单项失去焦点后收集到信息,而不是立刻收集

  • v-model.trim 去掉前后的空格

 

Axios

作用:实现AJAX 异步通信

由于vue不包含ajax通信功能,所以我们可以使用 axios 来进行通信

<body>
<div id="divvue">
    <div>{{info.name}}</div>
    <div>{{info.address.country}}</div>
    <a v-bind:href="info.url">点击跳转</a>
</div>

<script>
    <!--    创建vue对象-->
    var vm = new Vue({
        el: "#divvue",
        //钩子函数 mounted,在这里面进行ajax请求获取数据
        mounted(){
            axios.get("../data.json").then(response=>(this.info=response.data))
        },
        //在data 方法中接收数据
        data(){
            return{
                info:{
                    name:null,
                    url:null,
                    usePerson:0,
                    address:{
                        country:null
                    }
                }
            }
        }
    });
</script>
</body>

这个案例是从 json文件中获取数据,使用axios的get方法,返回的data数据赋值给 data方法的info,注意data的info 要和 json文件的格式一致

 

Vue计算属性

它是一个能将计算结果缓存起来的属性。

<body>
<div id="divvue">
    <p>currentTime1:{{currentTime1()}}</p>
    <p>currentTime2:{{currentTime2}}</p>
</div>

<script>
    <!--    创建vue对象-->
    var vm = new Vue({
        el: "#divvue",
        data:{
            message:"Compote"
        },
        methods:{
          currentTime1: function () {
              return Date.now();
          }  
        },
        computed:{
            currentTime2: function () {
                return Date.now();
            }
        }
    });
</script>
</body>

在computed中定义的方法 currentTime2 就是计算属性,一旦计算就被缓存,只有当其中的数据被刷新后才会重新计算。

计算属性就是通过计算得出的属性,他也有 get和 set方法

get什么时候调用:1.初次读取该计算属性时 2.该属性所依赖的属性发生变化时

set什么时候调用:当该计算属性被修改时

计算属性可以简写,在只读取不修改的前提下,可以简写为

<script> ... computed:{ currentTime2() { ... } } ... </script>

列表过滤排序的案例

<body>
<div id="root">
  <div>人员列表</div>
  <label>
    <input type="text" v-model="keyword"></input>
    <button @click="sortType= 2">升序</button>
    <button @click="sortType= 1">降序</button>
    <button @click="sortType= 0">原顺序</button>
  </label>
  <ul>
    <li v-for="(item,index) in filPerson" :key="item.id">
      {{item.name}}-{{item.age}}-{{item.sex}}
    </li>
  </ul>
</div>
<script>
  new Vue({
    el:"#root",
    data:{
      keyword:"",
      sortType:0,
      persons:[
        {id:"001",name:"马冬梅",age:25,sex:"女"},
        {id:"002",name:"周冬雨",age:19,sex:"女"},
        {id:"003",name:"周杰伦",age:30,sex:"男"},
        {id:"004",name:"温兆伦",age:21,sex:"男"}
      ]
    },
    computed:{
      filPerson(){
          const arr =  this.persons.filter((p)=>{
            return p.name.indexOf(this.keyword) !== -1
          })
          if(this.sortType){
            arr.sort((p1,p2)=>{
              return this.sortType === 2 ? p1.age-p2.age : p2.age-p1.age
            })
          }
          return arr
      }
    }
  })
</script>
</body>

 

Vue 插槽 slot

插槽可以动态地替换视图

比如在一个列表中 表的标题名和 列表的内容都是从别的地方获取的

<div>
    <ul>
        <li>
        </li>
    </ul>
</div>

其中列表名div标签和 列表内容 li标签都是从数据中获取,而ul 标签不用

可以使用插槽将 div 和 li 插入

  • 通过 component 创建组件 ,包括列表名和列表内容 ,div和 li 标签都用 slot标签来代替,slot的属性name,ul 不变

  • 再通过component 创建两个组件,分别是 标题 div 和 列表的项 li,这里就和之前学习组件一样

<body>
<div id="divvue">
    <todo>
        <todo-title slot="list-title" v-bind:title="title"></todo-title>
        <todo-items slot="list-items" v-for= "item in citys" v-bind:cityitem="item"></todo-items>
    </todo>
</div>

<script>
    Vue.component("todo",{
        template: '<div>' +
            '<slot name="list-title"></slot>' +
            '<ul>' +
            '<slot name="list-items"></slot>' +
            '</ul>'
    });

    Vue.component("todo-title",{
        props:['title'],
        template: '<div>{{title}}</div>>'
    });
    Vue.component("todo-items",{
        props:['cityitem'],
        template: '<li>{{cityitem}}</li>>'
    });
    <!--    创建vue对象-->
    var vm = new Vue({
        el: "#divvue",
        data:{
            title:'城市',
            citys:["A济南","B青岛","C淄博"]
        },
    });
</script>
</body>

视图中的两个 todo-title 和 todo-items 去替换掉 第一个component组件中的 slot 标签,而这两个组件本身就是 div 和 li

 

数据代理

1.Object.defineProperty

这个方法是给一个对象定义属性使用的

下面是给 person 添加 age 属性

<script>
    let person = {
        name:"张三",
        sex:"男"
    }
    Object.defineProperties(person,'age',{
        value:3
    })
</script>

defineProperty的三个参数分别是,要添加属性的对象、要添加的属性、属性模板(value是属性的值)

通过这种方式添加的属性不可被枚举,也就是不能被遍历,若想能够被遍历可以在属性模板中添加配置项

<script>
    let person = {
        name:"张三",
        sex:"男"
    }
    Object.defineProperties(person,'age',{
        value:3
        enumerable:true  //控制属性可以被枚举,默认值是false
        writable:true   //控制属性可以被修改
        configurable: true  //控制属性可以被删除
    })
</script>

需求:给person的age 赋值为一个变量number,当变量改变时,age跟着变

<script>
    let number = 10
    let person = {
        name:"张三",
        sex:"男"
    }
    Object.defineProperty(person,'age',{
        //value:3

        get:function (){
            return number
        },
        set(value){

        }
    })
</script>

当person的age属性被读取时,get函数就会被调用,返回值就是age的值,与之对应的是 当有人修改

person的age属性时,set函数就会被调用,参数就是修改的值

2.何为数据代理

通过一个对象代理对另一个对象中属性的操作,代码如下:obj2去代理obj

<script>
    let obj={x:100}
    let obj2={y:100}
    Object.defineProperty(obj2,'x',{
        get(){
            return obj.x
        },
        set(value){
            obj.x = value
        }
    })
</script>

 

3.Vue 中的数据代理

通过vm对象来代理data对象中属性的操作,vm里面有一个_data,真正的数据代理出现在 _data的属性和vm的属性中,基本原理就是通过 Object.defineProperty 的 getter/setter 方法添加到vm上

 

 

监视属性

<body>
<div id="root">
    <h2>今天天气很{{info}}</h2>
    <button @click="changeWeather">点击切换天气</button>
</div>
<script>
    new Vue({
        el:"#root",
        data:{
          isHot:true
        },
        methods:{
            changeWeather(){
                this.isHot = !this.isHot
            }
        },
        computed:{
            info(){
                return this.isHot ? "炎热":"凉爽";
            }
        }

    })
</script>
</body>

案例:点击按钮,改变天气,通过计算属性info来展示天气状况

我们想要知道 每次属性的改变,可以用vue实例的watch属性

里面就写要监视的属性 isHot 或 info,也是写成对象的形式,其中有个方法叫做handler

handler 有两个参数第一个是 属性改变后的值,第二个是属性改变前的值

watch:{
    isHot:{
        handler(newValue,oldValue){
            console.log("isHot 发生了改变",newValue,oldValue)
        }
    }
}

在watch 中还有一个属性是 immediate 设置为true 表示初始化时调用handler

总结:

  • 当被监视的属性发生变化时,回调函数自动调用

  • 监视的属性必须存在

  • 两种写法

    • 在new Vue中传入watch配置

    • 通过vm.$watch()

    两种写法的内容一致

深度监视

Vue中默认不监视对象内部值的改变,也就是data中的对象里的对象

data:{
  isHot:true, 
  numbers:{
      a:1,
      b:1
  }
},

如果你去监视numbers,当 numbers中的a或b改变时,并不会被监视到,如果想要numbers被监视到可以使用 watch中的配置 deep: true,这样 就可以监视numbers内部值的变化了

 

当你不需要 immediate 和 deep这两个配置时,就可以将watch简写

watch:{
    isHot(newValue,oldValue){
            console.log("isHot 发生了改变",newValue,oldValue)
    }
}

 

除了在new Vue 中配置watch,还可以通过 vm对象调用

vm.$watch(isHot,{
	handler(newValue,oldValue){
		xxx
	}
})

这种方式的简写形式为:

vm.$watch(isHot, function(){
	xxx
})

同样不能使用 immediate 和 deep这两个配置

 

Vue监视数据的原理

  • vue会监视data 中所有层级的数据

  • 如何监视对象中的数据?

    • 通过setter实现监视,且要在new Vue时就传入要监视的数据

    • 对象中后追加的属性,Vue不做响应式处理

    • 如果需要给后追加的属性做响应式,可用如下API

      • Vue.set(target, propertyName/index, value)

      • vm.$set(target, propertyName/index, value)

  • 如何监视数组中的数据?

    • 通过包裹数组更新元素的方法,本质做了两件事

      • 调用原生对应的方法对数组进行更新

      • 重新解析模板,进而更新界面

  • 在Vue修改数组中某个元素一定要用如下方法

    • push()、pop、shift、unshift、spilce、sort、reverse

    • 使用 Vue.set 或 vm.$set

    • Vue.set 或 vm.$set 不能给vm或vm的根数据对象添加属性

 

过滤器

过滤器也是定义在 Vue 对象中的配置,和computed、methods类似

通过格式化 时间戳的案例展示 过滤器的使用

<html>
	<head>
		<meta charset="utf-8">
		<title>过滤器</title>
		<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
		<script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.11/dayjs.min.js"></script>
	</head>
	<body>
		<div id="root">
			<h2>显示格式化后的时间</h2>
			<h3>现在是:{{time | timeFilter}}</h3>
		</div>
		<script>
			new Vue({
				el:"#root",
				data:{
					time:1621561377603
				},
				filters:{
					timeFilter(){
						return dayjs().format('YYYY-MM-DD HH:mm:ss')
					}
				}
			})
		</script>
	</body>
</html>
  • 在 模板中 的插值语句中写上要过滤的属性,后面接一个管道符(|) 后面就是 过滤器的函数

  • 过滤器函数在filters 中配置

  • 在上面的案例中 time 作为参数 传给了 timeFilter,timeFilter返回值 替换掉插值语法的内容

  • 过滤器 除了前面的内容还可以接收其他的参数

  • 过滤器还可以串联,在已有过滤器后面再加管道符 和 新的过滤器,新过滤器的接收的参数就是老过滤器的返回值

    <body>
        <div id="root">
            <h2>显示格式化后的时间</h2>
            <h3>现在是:{{time | timeFilter | mySlice}}</h3>
        </div>
        <script>
            new Vue({
                el:"#root",
                data:{
                    time:1621561377603
                },
                filters:{
                    timeFilter(){
                        return dayjs().format('YYYY-MM-DD HH:mm:ss')
                    },
                    mySlice(val){
                        return val.slice(0,4)
                    }
                }
            })
        </script>
    </body>

     

上面的过滤器是局部过滤器,只能由创建它的vue对象去调用,除此之外还有全局的过滤器

<script>
    Vue.filter('mySlice',function(value){
        return value.slice(0,4)
    })
    new Vue({...})
</script>

这样所有的vue都能使用它,需要注意的是:必须在new Vue之前创建它

过滤器并没有改变原本的数据,是产生新的对应的数据

 

内置指令

1.v-text

作用:向其所在的节点中渲染文本内容

和 插值语法效果相同,但是不如插值语法灵活,在标签内原来的内容会完全被替换掉。并且v-text不能解析标签

2.v-html

作用:向指定节点中渲染包含html结构的内容

v-html 和 v-text 的区别就是 前者能够解析html 标签

v-html 存在安全性问题,容易导致XSS攻击(Cookie泄露 ),不要在用户提交的内容上使用 v-html

 

3.v-clock

  • 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-clock属性

  • 使用 css 配合 v-clock可以解决网速慢时页面展示出 {{xxx}} 的效果

 

4.v-once

  • v-once所在节点在初次动态渲染后,就视为静态内容了

  • 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能

<h2 v-once >name的值是:{{name}}</h2>

 

5.v-pre

  • 跳过其所在节点编译过程

  • 可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译

 

自定义指令

函数式指令

<body>
<div id="root">
<h2>num的值是:<span v-text="number"></span></h2>
<h2>放大10倍的num的值是:<span v-big="number"></span></h2>
    <button @click="number++">点击number+1</button>
</div>

<script>
    new Vue({
        el:"#root",
        data:{
            number:1
        },
        directives:{
            big(element,binding){
                element.innerText = binding.value * 10
            }
        }
    })
</script>
</body>

此处 自定义的指令是 v-big

在模板中就是使用 v-big来展示数据,和 v-text相似

在定义该指令的时候,使用的配置对象是 directives,这里介绍用函数的方式定义

这个函数接收两个参数,第一个参数是 v-big指令所在的真实DOM 元素,第二个参数是一个对象,里面的内容是这个指令的数据,包括定义的名字、使用的名字,最重要的是 value(要填充的数据的值),也就是 number

在函数中 通过操作DOM元素,给它填充值

big函数执行的时机?

  • 指令与元素成功绑定时(一上来)

  • 指令所在的模板被重新解析时

 

对象式指令

上面的那种方式有时不能处理一些细节,比如有一个 input 输入框,给他绑定一个数值,之前可以用v-bind去实现,现在还有另外一个需求是让这个input自动获取焦点,我们可以用 自定义的指令来实现,这里我们叫他 v-fbind,如果按照 函数式去定义指令,实现不了这种效果

<body>
<div id="root">
<h2><span>num的值是:{{number}}</span></h2>
<h2>放大10倍的num的值是:<span v-big="number"></span></h2>
    <button @click="number++">点击number+1</button> <br/>
    <input type="text" v-fbind:value="number">
</div>

<script>
    new Vue({
        el:"#root",
        data:{
            number:1
        },
        directives:{
            big(element,binding){
                element.innerText = binding.value * 10
            },
            fbind(element,binding){
                element.value = binding.value
                element.focus()
            }
        }
    })
</script>
</body>

原因是 在解析模板的时候,input还没被放到 页面中,就直接获取焦点,所以没效果

这个时候就需要用 对象式的自定义指令去实现

directives:{
    big(element,binding){
        element.innerText = binding.value * 10
    },
    fbind:{
        bind(element,binding){
            element.value = binding.value
        },
        inserted(element,binding){
            element.focus()
        },
        update(element,binding){
            element.value = binding.value
        }
    }
}

使用对象式自定义,该对象要写三个方法

  • bind 是指令与元素成功绑定时调用

  • inserted 指令所在元素被插入页面时调用

  • update 指令所在模板被重新解析时调用

注意点

  • 指令命名时如果有多个单词,就用”-“来连接,不要使用驼峰命名法,定义的时候名字就要用引号引起来

    <body>
    <div id="root">
        <input type="text" v-big-number:value="number">
    </div>
    <script>
    	new Vue({
            el:"#root",
            data:{
                number:1
            },
            directives:{
            	"big-number"(){
                    ...
                }
        	}
        })    
    </script>
    </body>
  • 在 directives 配置项中的this 指的并不是 vue对象,而是 window

  • 全局 自定义指令 和 过滤器十分类似

    <body>
    <div id="root">
        <input type="text" v-big-number:value="number">
    </div>
    <script>
        Vue.directive('big-number'{
        	...              
        })
    	new Vue({
            el:"#root",
            data:{
                number:1
            },
        })    
    </script>
    </body>

    使用 Vue.directive 定义

     

生命周期

  • 生命周期又名生命周期回调函数、生命周期函数、生命周期钩子

  • Vue在关键时刻帮我们调用的一些特殊名称的函数

  • 生命周期函数名字不可更改,内容根据需求更改

  • 生命周期函数中的this指的是vm或组件实例对象

 

生命周期图

生命周期

常用的生命周期钩子:

  • mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等初始化操作

  • beforeDestroy:清除定时器、解绑自定义事件、取消订阅等收尾工作

关于销毁Vue实例

  • 销毁后自定义事件会失效,但原生DOM事件仍然有效

  • 一般不会在beforeDestroy操作数据,因为即便操作有效,也不会触发更新流程了

posted @ 2024-07-01 19:18  GrowthRoad  阅读(13)  评论(0编辑  收藏  举报