欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue3自定義指令的實踐示例

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

關(guān)鍵接口介紹

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

const?myDirective?=?{
//?在綁定元素的?attribute?前?
//?或事件監(jiān)聽器應(yīng)用前調(diào)用
created(el,?binding,?vnode,?prevVnode)?
{?//?下面會介紹各個參數(shù)的細(xì)節(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 組件

然而,當(dāng)我使用 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 動畫,當(dāng)然你也可以直接使用組件庫的 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)對更多場景,我們期望可以配置加載中的提示信息,不配置使用默認(rèn)值,如果是 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)
}

如果進(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)
}

我們驗證下功能:

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>

最后

今天的分享就到這了,如果有問題,可以評論區(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自定義指令的實踐示例的詳細(xì)內(nèi)容,更多關(guān)于Vue3自定義指令的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue 設(shè)置axios請求格式為form-data的操作步驟

    Vue 設(shè)置axios請求格式為form-data的操作步驟

    今天小編就為大家分享一篇Vue 設(shè)置axios請求格式為form-data的操作步驟,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-10-10
  • Vue的computed計算屬性你了解嗎

    Vue的computed計算屬性你了解嗎

    這篇文章主要為大家詳細(xì)介紹了Vue的computed計算屬性,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • 如何使用Vue的思想封裝一個Storage

    如何使用Vue的思想封裝一個Storage

    作為Web Storage API的接口,Storage 提供了訪問特定域名下的會話存儲或本地存儲的功能,例如可以添加、修改或刪除存儲的數(shù)據(jù)項,這篇文章主要給大家介紹了關(guān)于如何使用Vue的思想封裝一個Storage的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • vue3中使用vuex和vue-router的詳細(xì)步驟

    vue3中使用vuex和vue-router的詳細(xì)步驟

    這篇文章主要介紹了vue3中使用vuex和vue-router的步驟,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-12-12
  • Vue實現(xiàn)Tab標(biāo)簽路由效果并用Animate.css做轉(zhuǎn)場動畫效果的代碼

    Vue實現(xiàn)Tab標(biāo)簽路由效果并用Animate.css做轉(zhuǎn)場動畫效果的代碼

    這篇文章主要介紹了Vue實現(xiàn)Tab標(biāo)簽路由效果,并用Animate.css做轉(zhuǎn)場動畫效果,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • Vue下拉選擇框Select組件使用詳解(二)

    Vue下拉選擇框Select組件使用詳解(二)

    這篇文章主要為大家詳細(xì)介紹了Vue下拉選擇框Select組件的使用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • vue2實現(xiàn)可復(fù)用的輪播圖carousel組件詳解

    vue2實現(xiàn)可復(fù)用的輪播圖carousel組件詳解

    這篇文章主要為大家詳細(xì)介紹了vue2實現(xiàn)可復(fù)用的輪播圖carousel組件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Vue父子組件通信全面詳細(xì)介紹

    Vue父子組件通信全面詳細(xì)介紹

    這篇文章主要介紹了React中父子組件通信詳解,在父組件中,為子組件添加屬性數(shù)據(jù),即可實現(xiàn)父組件向子組件通信,文章通過圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-10-10
  • vue中分割線的實現(xiàn)方式

    vue中分割線的實現(xiàn)方式

    這篇文章主要介紹了vue中分割線的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • vue-class-setup?編寫?class?風(fēng)格組合式API

    vue-class-setup?編寫?class?風(fēng)格組合式API

    這篇文章主要為大家介紹了vue-class-setup?編寫?class?風(fēng)格組合式API,支持Vue2和Vue3,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09

最新評論