> 文档中心 > 计算属性与监听器、Vue 实例的生命周期

计算属性与监听器、Vue 实例的生命周期


本文是我在学习过程中记录学习的点点滴滴,仅仅为了学完之后巩固一下,日后忘记了也可以方便快速的复习。

计算属性与监听器、Vue 实例的生命周期

  • 前言
  • 一、计算属性
    • 1.1、计算属性初步理解
    • 1.2、计算属性的组成
  • 二、监听属性 watch
    • 2.1、回调值为函数方法
    • 2.2、回调函数是在 methods 中已定义的方法
    • 2.3、回调值为对象
    • 2.4、vue 实例方法 vm.$watch 及 watch 使用总结
  • 三、Vue实例生命周期
    • 3.1、Vue 实例生命周期初步认识
    • 3.2、浅析8个钩子函数
    • 3.3、钩子函数 beforeCreate & created
      • 3.3.1、 beforeCreate
      • 3.3.1、Created
    • 3.4、钩子函数 beforeMount & mounted
      • 3.4.1、 beforeMount
      • 3.4.2、 Mounted
    • 3.5、钩子函数 beforeUpdate & updated
      • 3.5.1、 beforeUpdate
      • 3.5.2、Updated
    • 3.6、钩子函数 beforeDestroy & destroyed
      • 3.6.1、 beforeDestroy
      • 3.6.2、Destroyed
  • 四、 本地存储、钩子函数、watch 等本章综合应用实例

前言

今天主要学习的是关于计算属性与监听器、Vue 实例的生命周期的学习。


一、计算属性

总结:
在{{}}里面只放比较简单的东西,对于多运算多逻辑的要放到computed里面计算,并且computed里面的计算不会实时更新,只有当computed计算属性里面依赖的属性值(在data里面)发生变化,computed计算属性里面才会再一次计算。
计算属性实际上有 get 和 set 函数组成,分别用来获取和设置计算属性值…只有一个 get 函数时的写法(可以省去set和get直接return):
ReverseMsg:function(){
return this.msg.split(“”).reverse().join(“”)

1.1、计算属性初步理解

在{{}}里面写表达式非常便利,但是设计它们的初衷是用于简单运算的。在{{}}(模板)中放入太多的逻辑会让模板过重且难以维护。
例如:

{{ message.split(‘’).reverse().join(‘’) }}

在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能看懂,这里是想要显示变量 message 的翻转字符串。当你想要在模板中多次引用此处的翻转字符串时,就会更加难以处理。所以,对于任何复杂逻辑,你都应当使用计算属性,那么计算属性如何定义呢?

<div id="app">{{msg.split("").reverse().join("")}}{{ReverseMsg}}</div><script>var vm=new Vue({el:"#app", data:{msg:"hello vue"},computed:{ReverseMsg:function(){return this.msg.split("").reverse().join("")}}})</script>

以上结果都显示出"hello vue"的反转后的字符。但是计算属性虽称为属性,也是用来存储数据的(像 data 选项一样),但是它本质是方法。也就是说上面computed里面的代码改为如下代码像属性一样直接赋值不行的,必须是通过方法去返回。
ReverseMsg:this.msg.split(“”).reverse().join(“”)

计算属性,一般是用来描述一个属性值依赖于另一个的属性值, 当我们使用模板表达式{{ }}将计算属性绑定到页面元素上时,计算属性会在依赖的属性值的变化时自动的更新 DOM 元素。

<div id="app">{{msg.split("").reverse().join("")}}{{ReverseMsg}}<input v-model="msg"></div><script>var vm=new Vue({el:"#app", data:{msg:"hello vue"},computed:{ReverseMsg:function(){return this.msg.split("").reverse().join("")}//ReverseMsg:this.msg.split("").reverse().join("")}})</script>

运行后发现通过文本框改变 msg 的值,计算属性 ReverseMsg值会跟着改变。即是改变计算属性的依赖值就可以改变计算属性值

1.2、计算属性的组成

计算属性实际上有 get 和 set 函数组成,分别用来获取和设置计算属性值。前面例子定义的计算属性只有一个方法,实际上就是 get函数(也就是默认写的函数就是 get 函数),也就是说通过 get 函数是获取到计算属性的值,不过在需要时你也可以提供一个 set 函数,当然改变了计算属性值时即 set 函数就会被执行,也就是通过计算属性的 set 方法可以监测到计算属性改变

<div id="app">{{msg.split("").reverse().join("")}}{{ReverseMsg}}<input v-model="msg"></div><script>var vm = new Vue({el: "#app", data: {msg: "hello vue"},computed: {//只有一个 get 函数时的写法/* ReverseMsg:function(){return this.msg.split("").reverse().join("")} *///有 get 和 set 函数时的写法ReverseMsg: {get: function () { //方法名固定为 getreturn this.msg.split("").reverse().join("")},set: function (newvalue) {//方法名固定为 set,参数newvalue 为改变后的计算属性值console.log("计算属性值被改变了");console.log("改变后的值为:"+newvalue)//this.ReverseMsg="123"//这里不能改变计算属性值,否则导致死循环。因为值是与通过上面的 msg 计算出来的值比较}}}})console.log(vm.ReverseMsg);//当读取 ReverseMsg 的值时即会调用 get 方法vm.ReverseMsg = "小豆子学堂"//当为 ReverseMsg 设置值时就会调用 set 方法</script>

结果:计算属性与监听器、Vue 实例的生命周期

注意:在 set 方法里面不要去直接改变计算属性(ReverseMsg)的值,否则会导致死循环,因为计算属性值改变了去执行 set 方法,发现又改变了属性值(值是与通过上面的 msg 计算出来的值比较)又要去执行 set,……即死循环,因此要改变计算属性值一般改变它的依赖值。

二、监听属性 watch

监听属性 watch 的基本含义:
监听属性 watch 也是 vue 实例的一个选项,使用 watch 监听器的方法可以用来监测某个数据是否发生变化,如果发生变化则可以执行一系列业务逻辑操作。
监听器以 key-value 的形式定义,key 是一个字符串,它是需要被监测的对象,而 value 则可以是字符串(指方法的名称,是通过 methods 定义好的方法)、函数(可以获取到监听对象改变前的值以及更新后的值)或是一个对象(对象内可以包含回调函数的其它选项,例如是否初始化时执行监听 immediate(是就设置为 true),或是是否执行深度遍历 deep,即是否对对象内部的属性进行监听)。value 实际上是监听到 key 变化后执行的回调函数

2.1、回调值为函数方法

<div id="app">{{msg}}<input v-model="msg" /></div><script>var vm=new Vue({el:"#app",data:{msg:"hello vue"},computed:{},methods:{},watch:{// 监听 msg 的值是否发生改变,发生改变执行相应的回调函数,从而执行业务逻辑(在控制台下输出新的值)msg:function(newValue,oldValue){console.log(`新值:${newValue} --------- 旧值:${oldValue}`)}}});</script>

结果:计算属性与监听器、Vue 实例的生命周期

2.2、回调函数是在 methods 中已定义的方法

<div id="app">{{msg}}<input v-model="msg" /></div><script>var vm=new Vue({el:"#app", data:{msg:"hello vue"},computed:{},methods:{watchMsg:function(newValue,oldValue){console.log(`新值:${newValue} --------- 旧值:${oldValue}`)}},watch:{// 监听 msg 的值是否发生改变,发生改变执行相应的回调函数,从而执行业务逻辑(在控制台下输出新的值)/* msg:function(newValue,oldValue){console.log(`新值:${newValue} --------- 旧值:${oldValue}`)} */msg:'watchMsg' // 单引号不能少哦}});</script>

2.3、回调值为对象

当我们监听的回调值为一个对象时,我们不仅可以设置回调函数,还可以设置一些回调的属性。例如,在下面的例子中,我们监听了User 这个对象,同时执行了执行深度遍历,这时,当我们监听到User.name 这个属性发生改变的时候,我们就可以执行我们的回调函数。注意,深度遍历默认为 false,当不启用深度遍历时,我们是无法监听到对象的内部属性的变化的。

<div id="app">用户姓名:<input type="text" v-model="User.name"></div><script>var vm = new Vue({el: '#app', data: {message: '', User: {name: 'zhangsan', gender: 'male' }},computed: {}, watch: {//回调为对象'User': {handler: function (newValue, oldValue) {console.log(`对象记录:新值:${newValue.name} --------- 旧值:${oldValue.name}`)},deep: true //设置为深度遍历}},methods: {}})</script>

结果:
计算属性与监听器、Vue 实例的生命周期
注意: 不过这里 newValue 与 oldValue 是一样的,因为,当我们监 听的数据为对象或数组时,newValue 和 oldValue 是相等的,因 为对象和数组都为引用类型,这两个的形参指向的也是同一个数据对 象(旧值获取不到)。同时,如果我们不启用深度遍历(deep:false) 我们将无法监听到对象(User)中 属性(name)的变化

2.4、vue 实例方法 vm.$watch 及 watch 使用总结

  • vue 实例方法 vm.$watch 使用

vue 实例方法 vm.$watch 格式如下:
vm.$watch(data,callback[,options])第一个参数为要侦听的数
据,第二个参数为回调,第三个参数为选项,可有可无.

实际上与 vm 实例选项 watch 是一样的,参数是一样的,就是写的位置不一样。实例方法 vm.$watch 写在 new Vue()外面,watch选项写在 new Vue( )里面,另外实例方法前面有$符号。

<div id="app">{{msg}}<input v-model="msg" /></div><script>var vm = new Vue({el: "#app", data: {msg: "hello vue"},computed: {},/* watch: {// 监听 msg 的值是否发生改变,发生改变执行相应的回调函数,从而执行业务逻辑(在控制台下输出新的值)msg: function (newValue, oldValue) {console.log(`新值:${newValue} --------- 旧值:${oldValue}`)}} */})// 注意:下面的 msg 外的单引号不能少,当然双引号也可以vm.$watch('msg', function (newValue, oldValue) {console.log(`新值:${newValue} --------- 旧值:${oldValue}`)})</script>

结果:计算属性与监听器、Vue 实例的生命周期

计算属性与监听属性 watch 使用总结
(1)计算属性的结果会被缓存起来,只有依赖的属性发生变化时才会重新计算,必须返回一个数据,主要用来进行纯数据的操作。
(2)监听器主要用来监听某个数据的变化,从而去执行某些具体的回调业务逻辑,不仅仅局限于返回数据。比如,当需要在数据变化时执行异步发送 ajax 请求或开销较大的操作时,采用监听器很好

三、Vue实例生命周期

3.1、Vue 实例生命周期初步认识

在之前的 Vue 学习中,我们在使用 Vue 时,都会创建一个
Vue 的实例,这个实例不仅是我们挂载 Vue 框架的入口,也是MVVM 思想中的 VM(ViewModel)。而每个 Vue 实例在被创建时都要经过一系列的初始化过程。例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。在这个过程中,Vue 会运行一些生命周期钩子函数,而我们则可以在钩子函数中编写一些自定义方法,用于在 Vue 的整个生命周期中某些阶段实现我们特殊需求。那么,接下来我们就来学习 Vue 实例的生命周期,主要是它的钩子函数的应用。
在我们使用 Vue 的整个过程中,归根结底都是在对这个 Vue
实例进行操作。因此,只有当我们了解 Vue 实例的生命周期之后,才可以更好的实现我们的业务逻辑。

vue 实例从创建到销毁的整个过程,叫 vue 实例生命周期。共 8个阶段 8 个钩子函数。生命周期流程图如下图所示。
8 个钩子函数分别是:beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed。
8 个钩子函数都是 Vue 实例的选项,也就是在 new Vue 时都可以设置。从字面意思我们就可以清楚的看出来,这 8 个钩子函数两个一组分别对应于 Vue 实例的创建、挂载、更新、销毁,接下来,我们就根据这四个阶段,解释 Vue 实例各个阶段中的钩子函数的作用。

在这里插入图片描述

3.2、浅析8个钩子函数

1、前四个钩子函数:

<div id="app">{{msg}}</div><script>var vm = new Vue({el: "#app", data: {msg:'欢迎来到小豆子学堂' },//所有钩子函数都是 vue 实例的一个选项beforeCreate(){alert('组件实例刚刚被创建,还未进行数据的观测和事件配置')},created(){alert('实例已经创建完成,并且已经进行数据观测和事件配置')},beforeMount(){alert('模板编译之前,还未挂载')},mounted(){alert('模板编译之后,已经挂载,此时才会渲染页面,才能看到页面上数据的展示')},beforeUpdate(){alert('数据更新之前')},updated(){alert('数据更新之后')},beforeDestroy(){alert('组件销毁之前')},destroyed(){alert('组件销毁之后')}//上面钩子函数的执行顺序与书写位置顺序没有关系})</script>

运行时前面 4 个钩子函数依次执行。但后面 4 个钩子函数未执行,因为没有组件的更新,也没有销毁组件

2、后四个钩子函数:

<div id="app">{{msg}}<br><button @click="update">更新数据</button><button @click="destroy">销毁组件</button></div><script>var vm = new Vue({el: "#app", data: {msg:'欢迎来到小豆子学堂' },methods:{update(){this.msg="welcome to xdz"},destroy(){this.$destroy();//组件销毁了占用的内容空间都被收回}},//所有钩子函数都是 vue 实例的一个选项,对应一些函数beforeCreate(){alert('组件实例刚刚被创建,还未进行数据的观测和事件配置')},created(){//常用alert('实例已经创建完成,并且已经进行数据观测和事件配置')},beforeMount(){alert('模板编译之前,还未挂载')},mounted(){//常用alert('模板编译之后,已经挂载,此时才会渲染页面,才能看到页面上数据的展示')},beforeUpdate(){alert('数据更新之前')},updated(){alert('数据更新之后')},beforeDestroy(){alert('组件销毁之前')},destroyed(){alert('组件销毁之后')}//上面钩子函数的执行顺序与书写位置顺序没有关系})</script>

单击【更新数据】会执行 beforeUpdate 和 updated 两个钩子函数。
单击【销毁组件】会执行 beforeDestroy 和 destroyed 两个钩子函数,销毁之后,单击【更新数据】就不再有反应了

3.3、钩子函数 beforeCreate & created

3.3.1、 beforeCreate

1、在我们通过 new Vue() 创建了一个 Vue 实例之后,会执行
init 方法,此时只会初始化 Vue 实例所包含的一些默认的事件与生命周期函数,在这个实例还未被完全创建之前,则会执行我们的beforeCreate 钩子函数。
在下面的例子中,我们在实例化 Vue 对象时,自定义了一个
message 属性,同时设定了一个 show 方法,现在我们来看看当实例并没有完全被创建之前,是否能够获取到我们自定义的属性与方法

<div id="app">{{message}}</div><script>var vm = new Vue({el: '#app', data: {message: 'Hello World!' },methods: {show() {console.log('执行了 show 方法');}},beforeCreate() {console.log(`Vue 实例挂载对象 el:${this.$el}`)console.log(`Vue 实例的 data 对象:${this.$data}`)console.log(`Vue 实例的 message 属性值:${this.message}`)console.log(`Vue 实例的 methods 对象:${this.$options.methods}`)this.show();}})</script>

结果:计算属性与监听器、Vue 实例的生命周期

从浏览器的控制台中我们可以看到,此时,Vue 实例中的挂载点元素、 data、message 属性,在 beforeCreated 生命周期钩子函数执行时,都没有进行了初始化,methods 对象产生了,但下面方法不能使用.

注意:说明看到了 hello world!那是因为 vue 实例已经创建完 成了,我们阻止不了 vue 实例时前面 4 个周期,自动执行了哦,我 们主要是从控制台来看下他们的每个阶段做了什么事情。

3.3.1、Created

2、当 beforeCreated 钩子函数执行完成后,Vue 实例已经初步初始化完成,此时将要执行生命周期中的 created 钩子函数来监听我们对于数据的更改或是监听事件

```html<div id="app">{{message}}</div><script>var vm = new Vue({el: '#app', data: {message: 'Hello World!' },methods: {show() {console.log('执行了 show 方法');}},Created() {console.log(`Vue 实例挂载对象 el:${this.$el}`)console.log(`Vue 实例的 data 对象:${this.$data}`)console.log(`Vue 实例的 message 属性值:${this.message}`)console.log(`Vue 实例的 methods 对象:${this.$options.methods}`)this.show();}})</script>

结果:计算属性与监听器、Vue 实例的生命周期

从浏览器控制台打印出的信息可以看出,在执行 Created 钩子函数的过程中,对于自定义的属性 message、自定义的方法 show已经初始化完成,此时,整个 Vue 实例已经初始化完成。但是,对于我们的 Vue 实例的挂载点元素还没有进行初始化。也就是说,当执行完 Created 之后,Vue 实例与 View(视图层)之间依旧是处于隔离的状态,Created 初始化完成的 Vue 实例也依旧没有与 DOM进行绑定

3.4、钩子函数 beforeMount & mounted

当 Vue 实例执行完 beforeCreated、created 钩子函数之后,Vue 实例已经初始化完成,而 Vue 实例并没有挂载到页面的DOM 上 。 在 挂 载 到 页 面 DOM 元 素 之 前 , 则 需 要 执 行beforeMount 钩子函数将我们的实例绑定到模板上进行编译渲染

3.4.1、 beforeMount

<div id="app"><h3 id="h3">{{message}}</h3></div><script>var vm = new Vue({el: '#app', data: {message: 'Hello World!' },methods: {show() {console.log('执行了 show 方法');}},beforeMount() {console.log(document.getElementById('h3').innerText)}})</script>

结果:计算属性与监听器、Vue 实例的生命周期

从控制台输出的信息可以看到,能获取到 h3 元素,也即是当执行到 beforeMount 钩子函数时,已经将模板编译完成,但是尚未挂载到页面上去

3.4.2、 Mounted

当把编译完成的模板挂载到页面上时,则需要执行 mounted
钩子函数,在这个阶段,用户就可以看到已经渲染好的页面。

<div id="app"><h3 id="h3">{{message}}</h3></div><script>var vm = new Vue({el: '#app', data: {message: 'Hello World!' },methods: {show() {console.log('执行了 show 方法');}},mounted() {console.log(document.getElementById('h3').innerText)}})</script>

这里我们可以看到,已经可以获取到 data 数据中的值,即当执行到 mounted 钩子函数时,页面已经渲染完成了

从上面的例子中可以看出,mounted 是创建 Vue 实例过程中
的最后一个生命周期钩子函数,当执行完 mounted 钩子函数之后,实例已经被完成创建好,并已经渲染到页面中,此时,如果我们不对实例进行任何的操作的话,Vue 实例则不会执行新的生命周期钩子函数

3.5、钩子函数 beforeUpdate & updated

在执行完了 mounted 钩子函数之后,Vue 实例实际已经脱离
了实例的创建阶段,进入实例的运行阶段。此时,当我们对实例的data 进行修改时,则会触发 beforeUpdate、updated 这两个钩子函数。

3.5.1、 beforeUpdate

<div id="app"><h3 id="h3">{{message}}</h3></div><script>var vm = new Vue({el: '#app', data: {message: 'Hello World!' },methods: {show() {console.log('执行了 show 方法');}},beforeUpdate() {console.log(`页面上的数据:${document.getElementById('h3').innerText}`)console.log(`data 中的 message 数据:${this.message}`)}})</script>

结果:计算属性与监听器、Vue 实例的生命周期

我们可以看到,当我们对 data 中的 message 属性进行修改
时,在执行 beforeUpdate 钩子函数时,页面上的数据还是旧的数据,而 data 中 message 属性已经将值修改成了最新的值(这里页面上显示的为修改后的数据则是因为执行了后面的钩子函数,将修改后的数据同步渲染到了页面上)

3.5.2、Updated

Vue 作为一个具有数据双向绑定特性的框架,当我们实时修改了页面元素的值之后,肯定希望页面可以同步变更数据。而在执行beforeUpdate 钩子函数之后,我们已经在实例中修改了数据,现在只需要重新渲染到页面就可以了,这时候,则会执行 updated 钩子函数

<div id="app"><h3 id="h3">{{message}}</h3></div><script>var vm = new Vue({el: '#app', data: {message: 'Hello World!' },methods: {show() {console.log('执行了 show 方法');}},updated() {console.log(`页面上的数据:${document.getElementById('h3').innerText}`)console.log(`data 中的 message 数据:${this.message}`)}})</script>

结果:计算属性与监听器、Vue 实例的生命周期

从控制台可以看到,当 updated 钩子函数执行的时候,页面和data 中的数据已经完成了同步,都显示的是最新的数据。此时,整个页面数据实时变更的操作也已经完成了

3.6、钩子函数 beforeDestroy & destroyed

既然有 Vue 实例的创建,那么在我们不需要 Vue 实例的时候就需要将这个实例进行销毁。而 beforeDestroy 以及 destroyed钩子函数则会帮我们实现这一目的。

3.6.1、 beforeDestroy

<div id="app">{{message}}</div><script>var vm = new Vue({el: '#app', data: {message: 'Hello World!' },methods: {show() {console.log('执行了 show 方法');}},beforeDestroy() {console.log(`Vue 实例挂载对象 el:${this.$el}`)console.log(`Vue 实例的 data 对象:${this.$data}`)console.log(`Vue 实例的 message 属性值:${this.message}`)console.log(`Vue 实例的 methods 对象:${this.$options.methods}`)this.show();},destroyed() {console.log(`Vue 实例挂载对象 el:${this.$el}`)console.log(`Vue 实例的 data 对象:${this.$data}`)console.log(`Vue 实例的 message 属性值:${this.message}`)console.log(`Vue 实例的 methods 对象:${this.$options.methods}`)this.show();}})</script>

结果:计算属性与监听器、Vue 实例的生命周期

这里,我们手动销毁 Vue 实例,从控制台的输出内容可以看到,在 beforeDestroy 和 destroyed 钩子函数执行中,我们依旧可以获取到 Vue 实例的相关内容,可是,当我们选择更新 message 属性的值时会发现,此时,页面上显示的值并没有发生改变。原来,这里的销毁并不是把 Vue 实例彻底删除,而是表示将 Vue 实例与页面的 DOM 元素进行’解绑’

3.6.2、Destroyed

vm.$destroy()作用:销毁vue实例,实质就是vm与挂载的dom元素解绑。

<div id="app">{{msg}}</div><script>var vm = new Vue({data: {msg: 'welcome to vue' }}).$mount('#app')vm.$destroy()//销毁 vue 实例,实质就是 vm 与上面 dom 元素解绑了。console.log(vm.msg)//销毁了 vue 实例,但是这个属性本身还是属于 vm 的,所以能够显示出来</script>

结果:计算属性与监听器、Vue 实例的生命周期

6.11 Vule 实例生命周期中钩子函数使用总结

  • beforeCreate
    Vue 实例进行初始化,此时实例的各个组件还没有
    进行初始化完成,因此不能访问到 data、
    computed、watch、methods 上的方法和数据,
    同时,Vue 实例的挂载点也没有进行初始化
  • created
    Vue 实例初始化完成,此时可以访问 data、
    computed、watch、methods 上的方法和数据,
    但是依旧没有进行 Vue 实例的挂载点初始化
  • beforeMount
    将实例绑定到模板并进行渲染,但并不会将实例挂
    载到页面上
  • mounted
    将渲染好的模板绑定到页面上(实例挂载到页面上
    了),此时,Vue 实例已完全创建好
  • beforeUpdate
    数据变更时执行,在实例数据更改之前执行自定义
    逻辑或操作
  • updated
    将 Vue 实例更新完成的数据重新渲染到内存中的
    虚拟 DOM 上,再将虚拟 DOM 应用到页面上
  • beforeDestroy
    Vue 实例进入销毁阶段,此时实例上的 data、
    methods、过滤器、指令等等还是处于可用的状态,
    还没有真正执行销毁的过程(解除与页面 DOM
    元素的绑定)
  • destroyed
    实例被销毁(解除 Vue 实例与页面 DOM 元素的
    绑定,但该 vue 实例的对象、数据还是可以用)

四、 本地存储、钩子函数、watch 等本章综合应用实例

<div id="app">{{msg}}<input v-model="msg" /></div><script>var vm=new Vue({el:"#app", data:{msg:"hello vue"},watch:{}});</script>

此例子中当通过文本框改变 msg 值之后,刷新下又回到了原来的值,因为刷新相当于重新实例化了一个 vue 对象,msg 的值没有存起来

计算属性与监听器、Vue 实例的生命周期

需求:如何做到当改变后,刷新时是改变后的值呢?
思路:当通过文本框改变 msg 值后把改变后的值存储本地,可以借助本地存储对象 localStorag

<div id="app">{{msg}}<input v-model="msg" v-on:keyup="gaibian" /></div><script>var vm = new Vue({el: "#app", data: {msg: "hello vue"},methods: {gaibian: function () {// localStorage 为内置本地存储对象localStorage.setItem("msg", this.msg);}}});</script>

运行结果刷新前:计算属性与监听器、Vue 实例的生命周期
刷新后:
计算属性与监听器、Vue 实例的生命周期
也就是说运行发现这时通过文本框改变 msg 值,在本地
localStorage 里存储起来了,但这时刷新下浏览器,发现上面文本框的值改回去了(为 hello vue),但是下面 localStorage 里存储了改变后的值(比如 hello vue123).

因此刷新后只需要把 localStorage 里存储的值赋给 msg 即可。有两种方法。
第一种:直接把上面data里的
msg: "hello vue
改为下面的代码
msg: localStorage.getItem(“msg”)
第二种:上面的msg 先放空,时间长可以放一个转圈圈的图片之类的,然后当 dom 元素挂载完毕再赋值数据,即是在钩子函数 mounted 时执行,改变后的代码如下

<div id="app">{{msg}}<input v-model="msg" v-on:keyup="gaibian" /></div><script>var vm = new Vue({el: "#app", data: {// msg: "hello vue"// msg: localStorage.getItem("msg")msg:'' },mounted:function(){this.msg=localStorage.getItem("msg")},methods: {gaibian: function () {// localStorage 为内置本地存储对象localStorage.setItem("msg", this.msg);}}});</script>

分析:上面是通过 v-on:keyup="gaibian"来触发“gaibian”方
法,在方法里值存储在本地,是通过 methods 来实现,那么可否通过 watch 来实现呢?当然可以通过 watch 来监听 msg 的值是否改变,只要改变就去把改变的值存储到本地。改变后的代码如下:

主要是上面的 v-on:keyup="gaibian"删除。methods 整个方法选项删除,改为 watch 选项,如下所示

<input v-model="msg"/></div><script>var vm = new Vue({el: "#app", data: {// msg: "hello vue"// msg: localStorage.getItem("msg")msg:'' },mounted:function(){this.msg=localStorage.getItem("msg")}, /* methods: {gaibian: function () {// localStorage 为内置本地存储对象localStorage.setItem("msg", this.msg);}} */watch:{msg:function(newValue){localStorage.setItem("msg",newValue);}}});</script>

计算属性与监听器、Vue 实例的生命周期 创作打卡挑战赛 计算属性与监听器、Vue 实例的生命周期 赢取流量/现金/CSDN周边激励大奖