最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3自定義指令的實踐示例

 更新時間:2023年06月28日 10:10:22   作者:萌萌噠草頭將軍  
這篇文章主要為大家詳細介紹了Vue3中自定義指令的實踐,文中的示例代碼講解詳細,具有一定的借鑒價值,感興趣的小伙伴可以了解一下

關(guān)鍵接口介紹

最近想體驗下自定義指令功能,看了看文檔和 vue2 差異不大,語法如下:

const?myDirective?=?{
//?在綁定元素的?attribute?前?
//?或事件監(jiān)聽器應(yīng)用前調(diào)用
created(el,?binding,?vnode,?prevVnode)?
{?//?下面會介紹各個參數(shù)的細節(jié)?},?
//?在元素被插入到?DOM?前調(diào)用
beforeMount(el,?binding,?vnode,?prevVnode)?{},
//?在綁定元素的父組件
//?及他自己的所有子節(jié)點都掛載完成后調(diào)用
mounted(el,?binding,?vnode,?prevVnode)?{},
//?綁定元素的父組件更新前調(diào)用
beforeUpdate(el,?binding,?vnode,?prevVnode)?{},
//?在綁定元素的父組件
//?及他自己的所有子節(jié)點都更新后調(diào)用
updated(el,?binding,?vnode,?prevVnode)?{},
//?綁定元素的父組件卸載前調(diào)用
beforeUnmount(el,?binding,?vnode,?prevVnode)?{},
//?綁定元素的父組件卸載后調(diào)用
unmounted(el,?binding,?vnode,?prevVnode)?{}
}

起初,最大的痛點是需要手動創(chuàng)建 dom ,然后插入 el 中。

const?loadingDom?=?document.createElement('div',?{calss:?'loading'})
el.append(loadingDom)

這樣好難受啊,我不想寫原生 dom ,能不能寫個組件渲染到指令里呢?

我想起了我之前看到的幾個 vue 接口,

  • h函數(shù),也就是 vue 提供的創(chuàng)建 vNode 的函數(shù)
  • render函數(shù):將 vNode 渲染到 真實 dom 里的函數(shù)

h函數(shù)用法如下:

//?完整參數(shù)簽名
function?h(
????type:?string?|?Component,
????props?:?object?|?null,
????children?:?Children?|?Slot?|?Slots
):?VNode

例如:

import?{?h?}?from?'vue'
const?vnode?=?h('div',?{?class:?'container'?},?[
??h('h1',?'Hello,?Vue?3'),
??h('p',?'This?is?a?paragraph')
])

我們使用h函數(shù)創(chuàng)建了一個 VNode,它表示一個包含 div、h1、p 的 DOM 結(jié)構(gòu)。其中,div 的 class 屬性為 container

自定義 loading 組件

然而,當我使用 props 為組件傳遞值時,發(fā)現(xiàn)是徒勞的。

import?Loading?from?'./components/Loading.vue';
cconst?option?=?{
????msg:?'一大波僵尸來襲',
????loading:?true
}
const?vnode?=?h(
????Loading,
????{?id:?'loading',?...option}
)

僅僅如下圖一樣,我以為是給組件的 props,實際上是 dom 的 props。

此時我們的組件只能通過 $attrs 來獲取這些 props 了,如下:

<template>
??<div?class="loading">
????<div></div>
????<span?v-if="$attrs.msg?!==?false">{{?$attrs.msg?}}</span>
??</div>
</template>

接著我們給組件實現(xiàn) loading 動畫,當然你也可以直接使用組件庫的 loading 組件。

我的實現(xiàn)如下:

<style>
??@keyframes?identifier?{
????100%?{
??????-webkit-transform:?rotate(360deg);
??????transform:?rotate(360deg);
????}
??}
??.loading?{
????height:?100px;
????width:?100%;
??}
??.loading?div?{
????width:?50px;
????height:?50px;
????border-radius:?50%;
????border:?2px?solid?green;
????margin:?25px?auto;
????border-top:?none;
????border-left:?none;
????animation:?identifier?1s?infinite?linear;
??}
</style>

自定義指令

接下來我們封裝自定義指令。

我們的思路是:

  • mounted 階段,如果是 true,那么渲染組件,否則什么都不做。
  • update 階段,如果 true 則重新渲染組件,如果 false 則渲染 vnode

為了可以應(yīng)對更多場景,我們期望可以配置加載中的提示信息,不配置使用默認值,如果是 false ,那么僅展示 loading 圖。所以參數(shù)類型如下:

interface?Props??{loading:?boolean,?msg?:?string?|?false}
v-loading:?boolean?|?Props

由于可能是布爾值,也可能是對象,我們需要初始化配置參數(shù)

function?formatOption?(value:?boolean?|?Props)?{
??const?loading?=?typeof?value?===?'boolean'
????????value?
??????:?value.loading
??const?option?=?typeof?value?!==?'boolean'
??????Object.assign(defaultOption,?value)
????:?{
??????loading,
??????...defaultOption
????}
??return?{?loading,?option?}
}

接著再 mounted 階段獲取格式化后的 loading 和 option,如果為 true 則直接渲染組件。

const?vLoading:?Directive<HTMLElement,?boolean?|?Props>?=?{
??mounted(el,?binding)?{
????const?{?loading,?option?}?=?formatOption(binding.value)
????loading?&&?renderLoading(el,?option)
??}
}
function?renderLoading?(el:?HTMLElement,?option:?Props)?{
??const?vnode?=?h(
????Loading,
????{?id:?'loading',?...option}
??)
??el.removeChild(el.children[0])
??render(vnode,?el)
}

如果進入 update 階段,則根據(jù)情況選擇渲染 laoding 組件還是 vnode。

const?vLoading:?Directive<HTMLElement,?boolean?|?Props>?=?{
??mounted(el,?binding)?{
????const?{?loading,?option?}?=?formatOption(binding.value)
????loading?&&?renderLoading(el,?option)
??},
??updated(el:?HTMLElement,?binding,?vnode)?{
????const?{?loading,?option?}?=?formatOption(binding.value)
????if?(loading)?{
??????renderLoading(el,?option)
????}?else?{
??????renderVNode(el,?vnode)
????}
??},
}
function?renderLoading?(el:?HTMLElement,?option:?Props)?{
??const?vnode?=?h(
????Loading,
????{?id:?'loading',?...option}
??)
??el.removeChild(el.children[0])
??render(vnode,?el)
}
function?renderVNode?(el:?HTMLElement,?vnode:?VNode)?{
??el.querySelector('#loading')?.remove()
??render(vnode,?el)
}

我們驗證下功能:

1.默認功能

const?loading?=?ref(true)
setTimeout(()?=>?loading.value?=?false,?2000)
</script>
<template>
??<div?style="width:?300px"?v-loading=laoding>
????<h1>加載成功</h1>
??</div>
</template>

2.自定義文本

<template>
??<div?style="width:?300px"?v-loading="{?loading,?msg:?'一大波僵尸來襲'?}">
????<h1>加載成功</h1>
??</div>
</template>

3.不展示文本

<template>
??<div?style="width:?300px"?v-loading="{?loading,?msg:?false?}">
????<h1>加載成功</h1>
??</div>
</template>

最后

今天的分享就到這了,如果有問題,可以評論區(qū)告訴我,我會及時更正。

以下是完整的代碼。

<template>
??<div?class="loading">
????<div></div>
????<span?v-if="$attrs.msg?!==?false">{{?$attrs.msg?}}</span>
??</div>
</template>
<script?lang="ts">
export?default?{??
}
</script>
<style>
??@keyframes?identifier?{
????100%?{
??????-webkit-transform:?rotate(360deg);
??????transform:?rotate(360deg);
????}
??}
??.loading?{
????height:?100px;
????width:?100%;
??}
??.loading?div?{
????width:?50px;
????height:?50px;
????border-radius:?50%;
????border:?2px?solid?green;
????margin:?25px?auto;
????border-top:?none;
????border-left:?none;
????animation:?identifier?1s?infinite?linear;
??}
</style>
<script?setup?lang="ts">
import?{?Directive,?VNode,?h,?ref,?render??}?from?'vue';
import?Loading?from?'./components/Loading.vue';
const?defaultOption:?{msg?:?string?|?false}?=?{
??msg:?'努力加載中'
}
interface?Props??{loading:?boolean,?msg?:?string?|?false}
function?formatOption?(value:?boolean?|?Props)?{
??const?loading?=?typeof?value?===?'boolean'
????????value?
??????:?value.loading
??const?option?=?typeof?value?!==?'boolean'
??????Object.assign(defaultOption,?value)
????:?{
??????loading,
??????...defaultOption
????}
??return?{?loading,?option?}
}
function?renderLoading?(el:?HTMLElement,?option:?Props)?{
??const?vnode?=?h(
????Loading,
????{?id:?'loading',?...option}
??)
??el.removeChild(el.children[0])
??render(vnode,?el)
}
function?renderVNode?(el:?HTMLElement,?vnode:?VNode)?{
??el.querySelector('#loading')?.remove()
??render(vnode,?el)
}
const?vLoading:?Directive<HTMLElement,?boolean?|?Props>?=?{
??mounted(el,?binding)?{
????const?{?loading,?option?}?=?formatOption(binding.value)
????loading?&&?renderLoading(el,?option)
??},
??updated(el:?HTMLElement,?binding,?vnode)?{
????const?{?loading,?option?}?=?formatOption(binding.value)
????if?(loading)?{
??????renderLoading(el,?option)
????}?else?{
??????renderVNode(el,?vnode)
????}
??},
}
const?loading?=?ref(true)
setTimeout(()?=>?loading.value?=?false,?2000)
</script>
<template>
??<div?style="width:?300px"?v-loading="{?loading,?msg:?'一大波僵尸來襲'?}">
????<h1>加載成功</h1>
??</div>
</template>

以上就是Vue3自定義指令的實踐示例的詳細內(nèi)容,更多關(guān)于Vue3自定義指令的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue?Mock.js介紹和使用與首頁導(dǎo)航欄左側(cè)菜單搭建過程

    Vue?Mock.js介紹和使用與首頁導(dǎo)航欄左側(cè)菜單搭建過程

    Mock.js是一個模擬數(shù)據(jù)的生成器,用來幫助前端調(diào)試開發(fā)、進行前后端的原型分離以及用來提高自動化測試效率,這篇文章主要介紹了Vue?Mock.js介紹和使用與首頁導(dǎo)航欄左側(cè)菜單搭建,需要的朋友可以參考下
    2023-09-09
  • Vue.js表單標簽中的單選按鈕、復(fù)選按鈕和下拉列表的取值問題

    Vue.js表單標簽中的單選按鈕、復(fù)選按鈕和下拉列表的取值問題

    這篇文章主要介紹了Vue.js表單標簽中的單選按鈕、復(fù)選按鈕和下拉列表的取值問題,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-11-11
  • Vue.js axios響應(yīng)攔截如何獲取返回狀態(tài)碼

    Vue.js axios響應(yīng)攔截如何獲取返回狀態(tài)碼

    這篇文章主要介紹了Vue.js axios響應(yīng)攔截如何獲取返回狀態(tài)碼問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • vue解決使用$http獲取數(shù)據(jù)時報錯的問題

    vue解決使用$http獲取數(shù)據(jù)時報錯的問題

    今天小編就為大家分享一篇vue解決使用$http獲取數(shù)據(jù)時報錯的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-10-10
  • Vue中圖片上傳組件封裝-antd的a-upload二次封裝的實例

    Vue中圖片上傳組件封裝-antd的a-upload二次封裝的實例

    這篇文章主要介紹了Vue中圖片上傳組件封裝-antd的a-upload二次封裝的實例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • vue3.0在子組件中觸發(fā)的父組件函數(shù)方式

    vue3.0在子組件中觸發(fā)的父組件函數(shù)方式

    這篇文章主要介紹了vue3.0在子組件中觸發(fā)的父組件函數(shù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • vue中對token有效期的深入理解

    vue中對token有效期的深入理解

    本文主要介紹了vue中對token有效期的深入理解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • vue3.0透傳屬性和事件的使用方式舉例

    vue3.0透傳屬性和事件的使用方式舉例

    這篇文章主要給大家介紹了關(guān)于vue3.0透傳屬性和事件使用的相關(guān)資料,透傳attribute指的是傳遞給一個組件,卻沒有被該組件聲明為props或emits的attribute或者v-on事件監(jiān)聽器,需要的朋友可以參考下
    2024-01-01
  • vue引入組件的幾種方法匯總

    vue引入組件的幾種方法匯總

    這篇文章主要介紹了vue引入組件的幾種方法匯總,包括常用的局部引入,這里需要注意在哪個頁面需要就在那個頁面引入、注冊、使用,本文結(jié)合示例代碼給大家介紹的非常詳細,需要的朋友參考下吧
    2023-10-10
  • vue 如何實現(xiàn)表單校驗

    vue 如何實現(xiàn)表單校驗

    這篇文章主要介紹的是vue 如何實現(xiàn)表單校驗的方法,又代碼詳細解說,感興趣的小伙伴可以參考下面文章的具體內(nèi)容
    2021-09-09

最新評論

璧山县| 赣州市| 香河县| 福泉市| 丁青县| 木里| 荃湾区| 拉萨市| 乌兰察布市| 安徽省| 龙海市| 芮城县| 石棉县| 长葛市| 延寿县| 得荣县| 新密市| 本溪市| 蓝田县| 中江县| 二连浩特市| 加查县| 兴和县| 东源县| 安图县| 兴宁市| 墨江| 上杭县| 黎平县| 杭锦后旗| 临澧县| 景宁| 海丰县| 伊宁市| 西峡县| 任丘市| 沛县| 德庆县| 县级市| 壶关县| 凌源市|