Vue 實(shí)例中的生命周期鉤子

Vue 實(shí)例中的生命周期鉤子

本博客版權(quán)歸本人和饑人谷所有,轉(zhuǎn)載需說明來源
Vue 框架的入口就是 Vue 實(shí)例喜最,其實(shí)就是框架中的 view model 偎蘸,它包含頁面中的業(yè)務(wù)
處理邏輯、數(shù)據(jù)模型等瞬内,它的生命周期中有多個(gè)事件鉤子迷雪,讓我們在控制整個(gè)Vue實(shí)例的
過程時(shí)更容易形成好的邏輯。

Vue 實(shí)例

在文檔中經(jīng)常會使用 vm 這個(gè)變量名表示 Vue 實(shí)例虫蝶,在實(shí)例化 Vue 時(shí)章咧,需要傳入一個(gè)選
項(xiàng)對象,它可以包含數(shù)據(jù)(data)能真、模板(template)赁严、掛載元素(el)扰柠、方法(methods)、生
命周期鉤子(lifecyclehook)等選項(xiàng)疼约。

Vue 實(shí)例化的選項(xiàng)

需要注意的是含 this 的函數(shù)大多不要使用箭頭函數(shù)卤档,因?yàn)槲覀兤谕?this 指向 Vue 實(shí)例。

data

Vue 實(shí)例的數(shù)據(jù)都保存在 data 對象中程剥,Vue 將會遞歸將 data 的屬性轉(zhuǎn)換為 getter/setter劝枣,
從而讓 data 的屬性能夠響應(yīng)數(shù)據(jù)變化。

var data = { a: 1 }
// 直接創(chuàng)建一個(gè)實(shí)例
var vm = new Vue({
  data: data
})
vm.a // -> 1
vm.$data === data // -> true

這樣數(shù)據(jù)就綁定在 HTML 中织鲸,Vue 框架監(jiān)視 data 的數(shù)據(jù)變化舔腾,自動更新 HTML 內(nèi)容。

computed

計(jì)算屬性將被混入到 Vue 實(shí)例中搂擦。所有 getter 和 setter 的 this 上下文自動地綁定為 Vue
實(shí)例稳诚。官方API

var vm = new Vue({
  data: { a: 1 },
  computed: {
    // 僅讀取,值只須為函數(shù)
    aDouble: function () {
      return this.a * 2
    },
    // 讀取和設(shè)置
    aPlus: {
      get: function () {
        return this.a + 1
      },
      set: function (v) {
        this.a = v - 1
      }
    }
  }
})
vm.aPlus   // -> 2
vm.aPlus = 3
vm.a       // -> 2
vm.aDouble // -> 4

這里可以省略setter,如果省略了setter瀑踢,那么值就可以是普通函數(shù)扳还,但是必須有返回值。

methods

methods 將被混入到 Vue 實(shí)例中丘损∑瞻欤可以直接通過 VM 實(shí)例訪問這些方法,或者在指令表達(dá)
式中使用徘钥。方法中的 this 自動綁定為 Vue 實(shí)例衔蹲。官方API

var vm = new Vue({
  data: { a: 1 },
  methods: {
    plus: function () {
      this.a++
    }
  }
})
vm.plus()
vm.a // 2

看下面這個(gè)例子,methods 和 computed 看起來可以做同樣的事情呈础,單純看結(jié)果兩種方式確實(shí)是相同的舆驶。
然而,不同的是計(jì)算屬性是基于它們的依賴進(jìn)行緩存的而钞。計(jì)算屬性只有在它的相關(guān)依賴發(fā)生改變
時(shí)才會重新求值沙廉。這就意味著只要 message 還沒有發(fā)生改變,多次訪問 reversedMessage 計(jì)算屬性會
立即返回之前的計(jì)算結(jié)果臼节,而不必再次執(zhí)行函數(shù)撬陵。相比而言,只要發(fā)生重新渲染网缝,method 調(diào)用總會執(zhí)行
該函數(shù)巨税。

var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // a computed getter
    reversedMessage: function () {
      // `this` points to the vm instance
      return this.message.split('').reverse().join('')
    }
  }
})

watch

一個(gè)對象,鍵是需要觀察的表達(dá)式粉臊,值是對應(yīng)回調(diào)函數(shù)草添。值也可以是方法名,或者包含選項(xiàng)的對象扼仲。Vue
實(shí)例將會在實(shí)例化時(shí)調(diào)用 $watch()远寸,遍歷 watch 對象的每一個(gè)屬性抄淑。

var vm = new Vue({
  data: {
    a: 1,
    b: 2,
    c: 3
  },
  watch: {
    // 監(jiān)控a變量變化的時(shí)候,自動執(zhí)行此函數(shù)
    a: function (val, oldVal) {
      console.log('new: %s, old: %s', val, oldVal)
    },
    // 深度 watcher
    c: {
      handler: function (val, oldVal) { /* ... */ },
      deep: true
    }
  }
})
vm.a = 2 // -> new: 2, old: 1

Vue 實(shí)例的生命周期

Vue 實(shí)例有一個(gè)完整的生命周期驰后,也就是從開始創(chuàng)建肆资、初始化數(shù)據(jù)、編譯模板倡怎、掛載Dom→渲染迅耘、更新→渲染贱枣、卸載等一系列
過程监署,我們稱這是 Vue 的生命周期。通俗說就是 Vue 實(shí)例從創(chuàng)建到銷毀的過程纽哥,就是生命周期钠乏。

在Vue的整個(gè)生命周期中,它提供了一些生命周期鉤子春塌,給了我們執(zhí)行自定義邏輯的機(jī)會晓避。

接下來我們用幾個(gè)例子來看看生命周期鉤子是怎么用的:

完整的代碼托管在 codepen

HTML結(jié)構(gòu):
<div id="app">
<p>{{ number }}</p>
<input type="text" name="btnSetNumber" v-model="number">
</div>

我們對 input 和 p 綁定了data 對象的 number 數(shù)據(jù),Vue 實(shí)例構(gòu)建如下:

var app = new Vue({         
    el: '#app',               
    data: {                   
      number: 1
    }
})

在實(shí)例中分別在每個(gè)生命周期鉤子中 console.log('鉤子名稱',this.number) 我們發(fā)現(xiàn)只壳,第一次頁面加載時(shí)
觸發(fā)了 beforeCreate, created, beforeMount, mounted 這幾個(gè)鉤子俏拱,data 數(shù)據(jù)在 created 中可獲取到。

再去 console.log('mounted: ', document.getElementsByTagName('p')[0]) 吼句,DOM 渲染在 mounted 中已經(jīng)
完成锅必。

我們再試著去更改 input 輸入框中的內(nèi)容,可以看到輸入框上方的數(shù)據(jù)同步發(fā)生改變惕艳,這就是數(shù)據(jù)綁定的效果搞隐,在更
新數(shù)據(jù)時(shí)觸發(fā) beforeUpdate 和 updated 鉤子,且在 beforeUpdate 觸發(fā)時(shí)远搪,數(shù)據(jù)已更新完畢劣纲。

而 destroy 僅在調(diào)用app.$destroy();時(shí)觸發(fā),對 vue 實(shí)例進(jìn)行銷毀谁鳍。銷毀完成后癞季,我們再重新改變 number 的值,vue 不再對此動作
進(jìn)行響應(yīng)了倘潜。但是原先生成的dom元素還存在绷柒,可以這么理解,執(zhí)行了destroy操作窍荧,后續(xù)就不再受vue控制了辉巡。

Vue.nextTick

在下次 DOM 更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)。在修改數(shù)據(jù)之后立即使用這個(gè)方法蕊退,獲取更新后的 DOM郊楣。官方API

Vue.nextTick(function () {
  // DOM 更新了
})

官方還提供了一種寫法憔恳,vm.$nextTick,用 this 自動綁定到調(diào)用它的實(shí)例上

created() {
    setTimeout(() => {
          this.number = 100
          this.$nextTick(() => {
            console.log('nextTick', document.getElementsByTagName('p')[0])
          })
    },100)
}

什么時(shí)候需要到Vue.nextTick()

  1. 在 Vue 生命周期的 created() 鉤子函數(shù)進(jìn)行的 DOM 操作一定要放在 Vue.nextTick() 的回調(diào)函數(shù)中净蚤。原因是什么呢钥组,原因是
    在 created() 鉤子函數(shù)執(zhí)行的時(shí)候 DOM 其實(shí)并未進(jìn)行任何渲染,而此時(shí)進(jìn)行 DOM 操作無異于徒勞今瀑,所以此處一定要將 DOM 操作
    的 js 代碼放進(jìn) Vue.nextTick() 的回調(diào)函數(shù)中程梦。與之對應(yīng)的就是 mounted 鉤子函數(shù),因?yàn)樵撱^子函數(shù)執(zhí)行時(shí)所有的 DOM 掛載和
    渲染都已完成橘荠,此時(shí)在該鉤子函數(shù)中進(jìn)行任何DOM操作都不會有問題 屿附。
  2. 在數(shù)據(jù)變化后要執(zhí)行的某個(gè)操作,而這個(gè)操作需要使用隨數(shù)據(jù)改變而改變的 DOM 結(jié)構(gòu)的時(shí)候哥童,這個(gè)操作都應(yīng)該放
    進(jìn) Vue.nextTick() 的回調(diào)函數(shù)中挺份。

生命周期小結(jié)

生命周期鉤子的一些使用方法:

beforecreate : 可以在這加個(gè)loading事件,在加載實(shí)例時(shí)觸發(fā)
created : 初始化完成時(shí)的事件寫在這里贮懈,如在這結(jié)束loading事件匀泊,異步請求也適宜在這里調(diào)用
mounted : 掛載元素,獲取到DOM節(jié)點(diǎn)
updated : 如果對數(shù)據(jù)統(tǒng)一處理朵你,在這里寫上相應(yīng)函數(shù)
beforeDestroy : 可以做一個(gè)確認(rèn)停止事件的確認(rèn)框
nextTick : 更新數(shù)據(jù)后立即操作dom

官方示例中的生命周期鉤子應(yīng)用

一個(gè)極簡的Markdown編輯器

運(yùn)行這個(gè)例子需要marked組件各聘,通過以下方法引入:
在項(xiàng)目目錄下運(yùn)行 npm i marked -S, js 文件中 import marked from 'marked' 即可。
這個(gè)例子沒有用到生命周期鉤子抡医,簡單解讀一下這段代碼躲因,

methods: {
    update: _.debounce(function (e) {
      this.input = e.target.value
    }, 300)
  }

html 中 textarea 綁定了 @input = "update" ,方法中用 debounce 指令設(shè)置了延時(shí)魂拦,在每次輸
入后延時(shí)同步輸入框的數(shù)據(jù)毛仪,減少了更新次數(shù),提高性能芯勘。

GitHub 提交

這個(gè)例子從 Github 的 API 中獲取了最新的 Vue.js 提交數(shù)據(jù)箱靴,并且以列表形式將它們展示了出
來。你可以輕松地切換 master 和 dev 分支荷愕。

created: function () {
    this.fetchData()
  },

在 created 鉤子中用聲明的 fetchData 函數(shù)獲取ajax異步數(shù)據(jù)并渲染到頁面衡怀。

內(nèi)嵌組件

本例中,整合了第三方 jQuery 插件(select2),怎么做到的呢安疗?就是把它內(nèi)嵌在一個(gè)常用組件中

mounted: function () {
    var vm = this
    $(this.$el)
      .val(this.value)
      // init select2
      .select2({ data: this.options })
      // emit event on change.
      .on('change', function () {
        vm.$emit('input', this.value)
      })
  },

這個(gè)例子建立了組件 select2 抛杨,在 mounted 鉤子中增加了 jQuery 插件 select2 的方法,數(shù)據(jù)加載時(shí)給元素增加這幾個(gè)方法荐类,獲取 DOM 數(shù)據(jù)怖现。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子屈嗤,更是在濱河造成了極大的恐慌潘拨,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饶号,死亡現(xiàn)場離奇詭異铁追,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)茫船,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門琅束,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人算谈,你說我怎么就攤上這事涩禀。” “怎么了濒生?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵埋泵,是天一觀的道長幔欧。 經(jīng)常有香客問我罪治,道長,這世上最難降的妖魔是什么礁蔗? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任觉义,我火速辦了婚禮,結(jié)果婚禮上浴井,老公的妹妹穿的比我還像新娘晒骇。我一直安慰自己,他們只是感情好磺浙,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布洪囤。 她就那樣靜靜地躺著,像睡著了一般撕氧。 火紅的嫁衣襯著肌膚如雪瘤缩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天伦泥,我揣著相機(jī)與錄音剥啤,去河邊找鬼。 笑死不脯,一個(gè)胖子當(dāng)著我的面吹牛府怯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播防楷,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼牺丙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了复局?” 一聲冷哼從身側(cè)響起冲簿,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤是整,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸿秆,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡算色,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了事秀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡野舶,死狀恐怖易迹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情平道,我是刑警寧澤睹欲,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站一屋,受9級特大地震影響窘疮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜冀墨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一闸衫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧诽嘉,春花似錦蔚出、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至悦冀,卻和暖如春趋翻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背雏门。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工嘿歌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人茁影。 一個(gè)月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓宙帝,卻偏偏與公主長得像,于是被迫代替她去往敵國和親募闲。 傳聞我的和親對象是個(gè)殘疾皇子步脓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • Vue 框架的入口就是 Vue 實(shí)例,其實(shí)就是框架中的 view model ,它包含頁面中的業(yè)務(wù) 處理邏輯靴患、數(shù)據(jù)...
    云中一樵夫閱讀 1,076評論 0 1
  • Vue 框架的入口就是 Vue 實(shí)例仍侥,其實(shí)就是框架中的 view model ,它包含頁面中的業(yè)務(wù)處理邏輯鸳君、數(shù)據(jù)模...
    阿根廷斗牛閱讀 908評論 0 2
  • Vue 實(shí)例 在文檔中經(jīng)常會使用 vm 這個(gè)變量名表示 Vue 實(shí)例农渊,在實(shí)例化 Vue 時(shí),需要傳入一個(gè)選項(xiàng)對象或颊,...
    鄙人才疏學(xué)淺閱讀 577評論 0 1
  • 前段時(shí)間突然思考起一個(gè)問題:人生的意義是什么砸紊?看完卡耐基《人性的弱點(diǎn)》后,我仿佛找到了答案囱挑。雖然書中重點(diǎn)談及...
    Caroline喬喬閱讀 491評論 0 4
  • 悶熱的天氣依然持續(xù)著醉顽,今天星期天,我決定放飛孩子平挑,讓他玩一下游添,不用寫作業(yè)了,很高興的和小朋友玩去了通熄,九點(diǎn)左右爺爺...
    博碩媽閱讀 206評論 0 0