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

Vue3自定義指令的實(shí)踐示例

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

關(guān)鍵接口介紹

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

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

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

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

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

我想起了我之前看到的幾個(gè) vue 接口,

  • h函數(shù),也就是 vue 提供的創(chuàng)建 vNode 的函數(shù)
  • render函數(shù):將 vNode 渲染到 真實(shí) 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)建了一個(gè) VNode,它表示一個(gè)包含 div、h1、p 的 DOM 結(jié)構(gòu)。其中,div 的 class 屬性為 container

自定義 loading 組件

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

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

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

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

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

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

我的實(shí)現(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)對(duì)更多場景,我們期望可以配置加載中的提示信息,不配置使用默認(rèn)值,如果是 false ,那么僅展示 loading 圖。所以參數(shù)類型如下:

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

由于可能是布爾值,也可能是對(duì)象,我們需要初始化配置參數(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)
}

如果進(jìn)入 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)
}

我們驗(yàn)證下功能:

1.默認(rèn)功能

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>

最后

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

以下是完整的代碼。

<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自定義指令的實(shí)踐示例的詳細(xì)內(nèi)容,更多關(guān)于Vue3自定義指令的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

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

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

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

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

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

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

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

    vue解決使用$http獲取數(shù)據(jù)時(shí)報(bào)錯(cuò)的問題

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

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

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

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

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

    vue中對(duì)token有效期的深入理解

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

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

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

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

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

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

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

最新評(píng)論

东至县| 苏尼特左旗| 巍山| 北海市| 城固县| 武强县| 长沙县| 昭苏县| 关岭| 屏东县| 航空| 连云港市| 富锦市| 庆云县| 乐安县| 登封市| 小金县| 红原县| 监利县| 莱州市| 沙雅县| 繁峙县| 偃师市| 莒南县| 旺苍县| 庆元县| 泸州市| 亚东县| 新郑市| 乌什县| 邵武市| 阳山县| 依安县| 四川省| 渝北区| 汕尾市| 岑巩县| 绥滨县| 营山县| 城口县| 美姑县|