vue 高級特性

一 自定義v-model屬性

vue在表單等domm模型中默認綁定了v-model的特性,而父組件中封裝了有input的子組件,那么如何使父子組件都能進行雙向綁定呢?這里提供一個案例:

父組件有一個custom-model子組件:

<template>
    <div>
        <p>{{name}}</p>
        <custom-model v-model="name" />
    </div>
</template>

<script>
import customModel from './CustomModel';
export default {
    components: {
        customModel
    },
    data() {
        return {
            name: ''
        }
    }
}
</script>

子組件custom-model:

<template>
    <input type="text" 
      :value="text1" 
      @input="$emit('change1', $event.target.value)" 
    />
    <!-- 上面的input使用了:value而非v-model -->
    <!-- 上面的change1和model.event對應(yīng)起來 -->
    <!-- text1屬性對應(yīng)起來 -->
</template>

<script>
export default {
    model: {
        prop: 'text1',
        event: 'change1'
    },
    props: {
        text1: String,
        default() {
            return ''
        }
    }
}
</script>

父組件中的子組件自定義v-model,該值會與子組件model中的prop進行雙向數(shù)據(jù)綁定,同時提供event作為事件名進行事件注冊。

二 $nextTick

由于vue是異步渲染的,所以在修改vue的data等數(shù)據(jù)之后,等所有函數(shù)執(zhí)行完才會進行dom渲染,所以在函數(shù)執(zhí)行中,要在dom渲染后執(zhí)行外面要包裹一層$nextTick,下面有一個案例:

<template>
    <div>
        <ul ref="ul1">
            <li v-for="(item,index) in list" :key="index">
                {{item}}
            </li>
        </ul>
        <button @click="add">add</button>
    </div>
</template>

<script>
export default {
    data() {
        return {
            list: ['a', 'b', 'c']
        }
    },
    methods: {
        add() {
            this.list.push(`${Date.now()}`)
            this.list.push(`${Date.now()}`)
            this.list.push(`${Date.now()}`)
            // 異步渲染  $nextTick等待dom渲染完成后執(zhí)行
            // 頁面渲染時將會對data的修改做整合,多次data修改只會修改一次
            this.$nextTick(() => {
                const ul1 = this.$refs.ul1
                console.log(ul1.childNodes.length)
            })
        }
    }
}
</script>

如果去掉this.$nextTick,在函數(shù)中打印的dom長度就不是6而是3,可以嘗試一下。

三 slot插槽

高級的插槽使用作用域插槽和具名插槽,案例:

父組件

<template>
    <slot-name>
        <!-- 作用域插槽 -->
        <template v-slot="slotProps">
            {{slotProps.slotData.name}}
        </template>
        <!-- 具名插槽 -->
        <template v-slot:footer>
            <p>aaa</p>
        </template>
    </slot-name>
</template>

<script>
import slotName from './slotName';
export default {
    components: {
        slotName
    }
}
</script>

子組件

<template>
    <div>
        <a :href="website.url">
            <slot :slotData="website">
                哈哈哈
            </slot>
        </a>
        <slot name="footer"></slot>
    </div>
</template>

<script>
export default {
    data() {
        return {
            website: {
                url: 'http://www.baidu.com',
                name: '百度'
            }
        }
    }
}
</script>

子組件在slot中傳入slotData屬性和對應(yīng)的value,到父組件v-slot的名稱.slotData屬性就是子組件website的值,這里注意一下在具名插槽footer里的插槽不能使用slotData的值,所以交作用域插槽,只是在這個slot內(nèi)可以使用的變量

四 動態(tài)組件,異步組件

動態(tài)組件:

<Component :is="'text'" />

在子組件不確定的情況下,通過字符串傳參表示所對應(yīng)的類的名稱,組件能夠直接渲染出來,照常引用、注冊組件,使用component標簽并添加:is屬性,屬性值為組件名

異步組件:

普通組件采用import xx from xx的方式加載,為同步加載,當項目需要引入很大的組件時,同步加載性能會十分差,體驗也很不理想,所以此時需要采用異步加載組件的方法。
方法:直接在components里定義組件名,使用import()方法

export default{
    components:{
        ${組件名}:()=>import(${組件路徑})
    }
}

能夠在組件初始化時不用渲染而等到需要使用的時候再進行渲染,在路由的配置中經(jīng)常使用。

五 keep-alive

使用場景:頻繁切換,不需要重復(fù)渲染的組件
被包裹的組件會被緩存,在頻繁切換但不需要重復(fù)渲染的情況下使用,通常是vue其中一個性能優(yōu)化的方向
用法:需要頻繁切換的組件外層添加keep-alive標簽,添加后組件切換時不會被銷毀,會緩存起來,大幅提高渲染性能。
案例:
這是父組件,會同時切換兩個組件

<template>
    <div>
        <keep-alive>
            <template v-if="data === 'c'">
                <c /> 
            </template>
            <template v-if="data === 'd'">
                <d />
            </template>
        </keep-alive>
        <button @click="handle">提交</button>
    </div>
</template>

<script>
import c from './c';
import d from './d';
export default {
    components: {
        c,
        d
    },
    data() {
        return {
            data: 'c'
        }
    },
    methods: {
        handle() {
            this.data === 'c' ? this.data = 'd' : this.data = 'c'
        }
    }
}
</script>

其中c組件和d組件基本相同只展示其中一個

<template>
  <div>c</div>
</template>

<script>
export default {
    mounted() {
        console.log('c mounted')
    },
    destroyed() {
        console.log('c destoryed')
    }
}
</script>
test

如果沒有keep-alive,那么切換的時候destoryed函數(shù)也會執(zhí)行,但是有的情況destoryed函數(shù)就不執(zhí)行了,原因就在于keep-alive會緩存組件,組件在其中不會銷毀。

六 mixin

組件抽離公共邏輯
多個組件有相同的邏輯可以抽離出來的時候就可以使用。但是目前mixin并不是完美的解決方案,會有一些問題?,F(xiàn)在的Vue3意在解決這些問題。
案例:

<template>
   <div>
       {{a}}--{}
       <button @click="handle">提交</button>
   </div>
</template>

<script>
import myMixins from './mixins';
export default {
   mixins: [ myMixins ],
   data() {
       return {
           a: 'aaa'
       }
   }
}
</script>

export default {
    data() {
        return {
            b: 'bbb'
        }
    },
    methods: {
        handle() {
            console.log(this.b)
        }
    }
}

mixin目前存在的缺點:

  • 變量來源不明確,不利于閱讀。
  • 多mixin可能會造成命名沖突。
  • mixin可能存在多對多的關(guān)系,復(fù)雜度較高。

七 watch進階

從我們剛開始學(xué)習Vue的時候,對于偵聽屬性,都是簡單地如下面一般使用:

watch:{
    a(){
     //doSomething
    }
}

實際上,Vue對watch提供了很多進階用法。

handler函數(shù)

以對象和handler函數(shù)的方式來定義一個監(jiān)聽屬性,handler就是處理監(jiān)聽變動時的函數(shù):

watch:{
    a:{
        handler:'doSomething'
    }
},
methods:{
    doSomething(){
        //當 a 發(fā)生變化的時候,做些處理
    }
}

handler有啥用?是多此一舉么?用途主要有兩點:

  • 將處理邏輯抽象出去了,以method的方式被復(fù)用
  • 給定義下面兩個重要屬性留出了編寫位置

deep屬性

當watch的是一個Object類型的數(shù)據(jù),如果這個對象內(nèi)部的某個值發(fā)生了改變,并不會觸發(fā)watch動作!

也就是說,watch默認情況下,不監(jiān)測內(nèi)部嵌套數(shù)據(jù)的變動。但是很多情況下,我們是需要監(jiān)測的!

為解決這一問題,就要使用deep屬性:

watch:{
    obj:{
        handler:'doSomething',
        deep:true
    }
},
methods:{
    doSomething(){
        //當 obj 發(fā)生變化的時候,做些處理
    }
}

deep屬性默認為false,也就是我們常用的watch模式。

immediate屬性

watch 的handler函數(shù)通常情況下只有在監(jiān)聽的屬性發(fā)生改變時才會觸發(fā)。

但有些時候,我們希望在組件創(chuàng)建后,或者說watch被聲明和綁定的時候,立刻執(zhí)行一次handler函數(shù),這就需要使用immediate屬性了,它默認為false,改為true后,就會立刻執(zhí)行handler。

watch:{
    obj:{
        handler:'doSomething',
        deep:true,
        immediate:true
    }
},
methods:{
    doSomething(){
        //當 obj 發(fā)生變化的時候,做些處理
    }
}

同時執(zhí)行多個方法

使用數(shù)組可以設(shè)置多項,形式包括字符串、函數(shù)、對象

watch: {
   // 你可以傳入回調(diào)數(shù)組,它們會被逐一調(diào)用
   a: [
       
     'handle1',
       
     function handle2 (val, oldVal) { /* ... */ },
       
     {
       handler: function handle3 (val, oldVal) { /* ... */ },
       /* ... */
     }
       
   ],
   
 }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文使用的Vue版本:2.6.10 Vue為我們提供了很多高級特性,學(xué)習和掌握它們有助于提高你的代碼水平。 一、w...
    liujiangblog閱讀 490評論 1 1
  • Vue高級特性 未經(jīng)同意 禁止轉(zhuǎn)載 自定義v-model $nextTick 1. vue是異步渲染 2. dat...
    吾名劉斬仙閱讀 376評論 0 0
  • v-model $nextTick 匯總data的修改,一次性做視圖更新減少DOM操作次數(shù),提高性能 slot 父...
    卷村隊隊員閱讀 176評論 0 0
  • 1、使用v-model進行父子傳值 2、nextTick()異步加載dom元素 3、使用slot,分為匿名插槽、作...
    枸杞_7422閱讀 118評論 0 0
  • 基本使用 父組件在引用的子組件中添加內(nèi)容 子組件 slotDemo.vue 作用域插槽 父組件可以拿到子組件的數(shù)據(jù)...
    loushumei閱讀 869評論 0 6

友情鏈接更多精彩內(nèi)容