vue 基礎(chǔ)(八)

生命周期、插槽

介紹: 每個(gè) Vue 實(shí)例/組件在被創(chuàng)建時(shí)都要經(jīng)過一系列的初始化過程——例如剪菱,需要設(shè)置數(shù)據(jù)監(jiān)聽挠阁、編譯模板、將實(shí)例掛載到 DOM 并在數(shù)據(jù)變化時(shí)更新 DOM 等塑崖。同時(shí)在這個(gè)過程中的某些階段也會(huì)運(yùn)行一些特定的函數(shù),這些函數(shù)就被叫做生命周期鉤子,這給了用戶在不同階段添加自己的代碼的機(jī)會(huì)痛倚。

生命周期鉤子函數(shù)詳解(前面帶*號(hào)的生命周期表示非常用生命周期)

*beforeCreate: 在實(shí)例初始化之后规婆,數(shù)據(jù)觀測 (data observer) 和 event/watcher 事件配置之前被調(diào)用。該生命周期中無法訪問data 計(jì)算屬性 props

new Vue({
           el: '#app',
           data: {
               name: '小明',
               age: 18
           },
           beforeCreate() {
               console.log(
                   '組件被實(shí)例化后觸發(fā),但是該生命周期階段數(shù)據(jù)還沒有初始化完成',
                   this,
                   this.$data // undefined
               )
           }
       })

created: 在實(shí)例創(chuàng)建完成后被立即調(diào)用蝉稳。在這一步抒蚜,實(shí)例已完成以下的配置:數(shù)據(jù)觀測 (data observer),property 和方法的運(yùn)算耘戚,watch/event 事件回調(diào)嗡髓。然而,掛載階段還沒開始收津,$el 目前尚不可用饿这。(在這個(gè)生命周期中不要操作頁面中DOM元素,因?yàn)樵剡€沒有被渲染出來)

new Vue({
            el: '#app',
            data: {
                name: '小明',
                age: 18
            },
            created() {
                console.log(
                    '組件被實(shí)例化后觸發(fā),data/計(jì)算屬性/watch/methods已經(jīng)配置完成,這里可以執(zhí)行一些初始網(wǎng)絡(luò)請求操作',
                    this,
                    this.$data 
                )
                this.getDataFromServer()
            },
            methods: {
                getDataFromServer() {
                    console.log('開啟網(wǎng)絡(luò)請求,向服務(wù)器請求數(shù)據(jù)')
                }
            }
        })

*beforeMount: 在掛載(渲染)開始之前被調(diào)用: 相關(guān)的 render 函數(shù)首次被調(diào)用。

mounted: 實(shí)例被掛載后調(diào)用撞秋,這時(shí) el 被新創(chuàng)建的 vm.$el 替換了长捧。如果根實(shí)例掛載到了一個(gè)文檔內(nèi)的元素上,當(dāng) mounted 被調(diào)用時(shí) vm.$el 也在文檔內(nèi)吻贿。

注意: mounted 不會(huì)保證所有的子組件也都一起被掛載串结。如果你希望等到整個(gè)視圖都渲染完畢,可以在 mounted 內(nèi)部使用 vm.$nextTick

new Vue({
            el: '#app',
            data: {
                name: '小明',
                age: 18
            },
            beforeMount() {
                console.log('實(shí)例將要被渲染',this.$refs) // this.$refs空對(duì)象
            },
            mounted() {
                console.log('組件掛載完畢,掛載的意思就是實(shí)例第一次渲染完成,這里是一個(gè)操作DOM的好時(shí)機(jī)', this.$refs) 
                //this.$refs元素已經(jīng)獲取完畢 
                this.$nextTick(()=> {
                    // 這里所有子組件全部掛載完畢
                })
            }
        })

beforeUpdate: 數(shù)據(jù)更新時(shí)調(diào)用舅列,發(fā)生在虛擬 DOM更新渲染之前奉芦。這里適合在更新之前訪問現(xiàn)有的 DOM,比如手動(dòng)移除已添加的事件監(jiān)聽器剧蹂。

updated: 由于數(shù)據(jù)更改導(dǎo)致的虛擬 DOM 重新渲染和打補(bǔ)丁声功,在DOM更新渲染之后會(huì)調(diào)用該鉤子。

當(dāng)這個(gè)鉤子被調(diào)用時(shí)宠叼,組件 DOM 已經(jīng)更新先巴,所以你現(xiàn)在可以執(zhí)行依賴于 DOM 的操作其爵。然而在大多數(shù)情況下,你應(yīng)該避免在此期間更改狀態(tài)伸蚯。如果要相應(yīng)狀態(tài)改變摩渺,通常最好使用計(jì)算屬性或 watcher 取而代之。

注意: updated 不會(huì)保證所有的子組件也都一起被重繪剂邮。如果你希望等到整個(gè)視圖都重繪完畢摇幻,可以在 updated 里使用 vm.$nextTick

 new Vue({
            el: '#app',
            data: {
                name: '小明',
                age: 18
            },
          beforeUpdate() {},  
          updated: function () {
              // 不能保證所有子組件更新完畢
              this.$nextTick(function () {
                //保證所有子組件更新完畢
              })
            }
        }) 

beforeDestroy: 實(shí)例銷毀之前調(diào)用。在這一步挥萌,實(shí)例仍然完全可用绰姻。(在該生命周期中我們?nèi)匀豢梢栽L問,實(shí)例對(duì)象的屬性 方法 計(jì)算屬性 DOM節(jié)點(diǎn)等)。

該生命周期中應(yīng)該去做一些清理工作如:解綁計(jì)時(shí)器引瀑,取消網(wǎng)絡(luò)請求狂芋,清理掉哪些原生事件監(jiān)聽或者在mounted階段創(chuàng)建DOM節(jié)點(diǎn)

new Vue({
            el: '#app',
            data: {
                name: '小明',
                age: 18,
                index: 0
            },
            mounted() {
                // 模擬啟動(dòng)輪播圖
               this.timer = setInterval(() => {
                   this.index++
               }, 1000);
            },
            beforeDestroy() {
                // 解綁計(jì)時(shí)器
                clearInterval(this.timer)
            }
})

*destroyed: 實(shí)例銷毀后調(diào)用。該鉤子被調(diào)用后憨栽,對(duì)應(yīng) Vue 實(shí)例的所有指令都被解綁帜矾,所有的事件監(jiān)聽器被移除,所有的子實(shí)例也都被銷毀屑柔。

activated: 被 keep-alive 緩存的組件激活時(shí)調(diào)用屡萤。

deactivated: 被 keep-alive 緩存的組件停用時(shí)調(diào)用。

<div id="app">
        <keep-alive>
            <component :is="show? 'demo': 'test'"></component>
        </keep-alive>
       
        <button @click="show = !show">show/hidden</button>
    </div>

    <script>
        new Vue({
            el: '#app',
            data: {
                show: true
            },
            components: {
                demo: {
                    template: '<div>我是一個(gè)demo組件</div>',
                    mounted() {
                        console.log('組件第一次掛載完畢')
                    },
                    beforeDestroy() {
                        console.log('組件將要被銷毀')
                    },
                    activated() {
                        console.log('demo組件被激活')
                    },
                    deactivated() {
                        console.log('demo組件被停用')
                    }
                },
                test: {
                    template: '<h2 @click="count++">count{{count}}</h2>',
                    data() {
                        return {
                            count: 7
                        }
                    },
                    activated() {
                        console.log('test組件被激活')
                    },
                    deactivated() {
                        console.log('test組件被停用')
                    }
                }
            }
        })
    </script>

插槽

概念: Vue 實(shí)現(xiàn)了一套內(nèi)容分發(fā)的 API掸宛,為組件提供了一個(gè) <slot> 元素作為承載分發(fā)內(nèi)容的出口死陆。

語法:

 <script>
 Vue.component('login-component',{
                 template: `
                 <div>
                     <div>
                         // 分發(fā)內(nèi)容的內(nèi)容會(huì)被承載到這個(gè)slot標(biāo)簽位置 
                         <slot></slot>
                     </div>
                     <p>
                         賬號(hào): <input>
                     </p>
                     <p>
                         密碼: <input type="password">
                     </p>
                     <button>登錄</button>
                 </div>
                `
             })
 </script> 
 
 // 這時(shí)你可以這樣使用組件       
 <login-component>
          <h2>科技</h2>
 </login-component>      
 // 渲染在瀏覽器的結(jié)果是  
 <div>
         <div>
             <!--分發(fā)內(nèi)容的內(nèi)容會(huì)被承載到這個(gè)slot標(biāo)簽位置 -->
            <h2>科技</h2>
         </div>
         <p>
             賬號(hào): <input>
         </p>
         <p>
             密碼: <input type="password">
         </p>
         <button>登錄</button>
 </div>      
     

注意:

  1. 如果 <login-component> 的 template 中沒有包含一個(gè) <slot> 元素,則該組件對(duì)稱標(biāo)簽內(nèi)部的任何內(nèi)容都會(huì)被拋棄旁涤。

  2. <slot> 元素內(nèi)部可以設(shè)置后備內(nèi)容,如果當(dāng)前組件對(duì)稱標(biāo)簽內(nèi)部沒有插入任何內(nèi)容的話,組件最終會(huì)渲染后備內(nèi)容

  Vue.component('login-component',{
     
                 template: `
                 <div>
                     <div>
                         <slot>后備內(nèi)容</slot>
                     </div>
                     <p>
                         賬號(hào): <input>
                     </p>
                     <p>
                         密碼: <input type="password">
                     </p>
                     <button>登錄</button>
                 </div>
                 `
             })

具名插槽

概念: 有時(shí)我們組件需要多個(gè)插槽翔曲∑认瘢可以將不同的組件插入到不同插槽內(nèi)部劈愚,實(shí)現(xiàn)方法是使用具名插槽,給組件中的<slot> 元素設(shè)置一個(gè)name屬性闻妓。在向具名插槽提供內(nèi)容的時(shí)候菌羽,我們可以在一個(gè) <template> 元素上使用 v-slot 指令將對(duì)應(yīng)的內(nèi)容插入到指定的<slot> 元素上

語法:

<script>
     Vue.component('login-component',{
     
         template: `
                 <div>
                     <div>
                         <slot>后備內(nèi)容</slot>
                     </div>
                     <p>
                         賬號(hào): <slot name="user"></slot>
                     </p>
                     <p>
                         密碼: <slot name="psd"></slot>
                     </p>
         
                     <button>登錄</button>
                     <slot></slot>
                 </div>
                 `
     })
 </script>
 
 <login-component>
     <h2>科技</h2>
     
     <template v-slot:user>    
     <!-- 這里所有的內(nèi)容都會(huì)被插入到name="user" 插槽中 -->
         <div>
             123
         </div>
     </template>
     
     
     <input slot="psd" type="password" placeholder="這個(gè)元素會(huì)被插入到name=psd 插槽中">
     <component-a slot="psd"></component-a> 
     
 </login-component>
 

注意:跟 v-onv-bind 一樣,v-slot 也有縮寫由缆,即把參數(shù)之前的所有內(nèi)容 v-slot: 替換為字符 #注祖。
例: v-slot:header 可以被縮寫為 #header

  <login-component>
                 <h2>科技</h2>
     
                 <template #user>    
                     這里所有的內(nèi)容都會(huì)被插入到name="user" 插槽中
                     <div>
                         123
                     </div>
                 </template>
     
     
                 <template #psd>    
                    <input type="password" placeholder="這個(gè)元素會(huì)被插入到name=psd 插槽中">
                 </template>
     </login-component>

注意:插槽在項(xiàng)目開發(fā)中不太常用,常用于一些UI庫的開發(fā)均唉。如果想對(duì)插槽有更深的了解可以查閱官方文檔

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末是晨,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子舔箭,更是在濱河造成了極大的恐慌罩缴,老刑警劉巖蚊逢,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異箫章,居然都是意外死亡烙荷,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門檬寂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來终抽,“玉大人,你說我怎么就攤上這事桶至≈绨椋” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵塞茅,是天一觀的道長亩码。 經(jīng)常有香客問我,道長野瘦,這世上最難降的妖魔是什么描沟? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮鞭光,結(jié)果婚禮上吏廉,老公的妹妹穿的比我還像新娘。我一直安慰自己惰许,他們只是感情好席覆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著汹买,像睡著了一般佩伤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上晦毙,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天生巡,我揣著相機(jī)與錄音,去河邊找鬼见妒。 笑死孤荣,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的须揣。 我是一名探鬼主播盐股,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼耻卡!你這毒婦竟也來了疯汁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤卵酪,失蹤者是張志新(化名)和其女友劉穎幌蚊,沒想到半個(gè)月后秸谢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡霹肝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年估蹄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沫换。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡臭蚁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出讯赏,到底是詐尸還是另有隱情垮兑,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布漱挎,位于F島的核電站系枪,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏磕谅。R本人自食惡果不足惜私爷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望膊夹。 院中可真熱鬧衬浑,春花似錦、人聲如沸放刨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽进统。三九已至助币,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間螟碎,已是汗流浹背眉菱。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抚芦,地道東北人倍谜。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓迈螟,卻偏偏與公主長得像叉抡,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子答毫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

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