精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Vue3自定義指令實踐:使用h函數渲染自定義組件到指令中

開發 前端
為了可以應對更多場景,我們期望可以配置加載中的提示信息,不配置使用默認值,如果是 false ,那么僅展示 loading 圖。

?? 關鍵接口介紹

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

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

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

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

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

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

  • h函數,也就是 vue 提供的創建 vNode 的函數
  • render函數:將 vNode 渲染到 真實 dom 里的函數

h函數用法如下:

// 完整參數簽名
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函數創建了一個 VNode,它表示一個包含 div、h1、p 的 DOM 結構。其中,div 的 class 屬性為 container

?? 自定義 loading 組件

然而,當我使用 props 為組件傳遞值時,發現是徒勞的。

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>

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

我的實現如下:

<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

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

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

v-loading: boolean | Props

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

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 階段,則根據情況選擇渲染 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)
}

我們驗證下功能:

  • 默認功能
const loading = ref(true)

setTimeout(() => loading.value = false, 2000)

</script>

<template>
  <div style="width: 300px" v-loading=laoding>
    <h1>加載成功</h1>
  </div>
</template>

圖片圖片

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

圖片圖片

  • 不展示文本
<template>
  <div style="width: 300px" v-loading="{ loading, msg: false }">
    <h1>加載成功</h1>
  </div>
</template>

圖片圖片

?? 最后

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

以下是完整的代碼。

<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>

責任編輯:武曉燕 來源: 萌萌噠草頭將軍
相關推薦

2021-11-30 08:19:43

Vue3 插件Vue應用

2022-07-26 01:06:18

Vue3自定義指令

2021-07-05 15:35:47

Vue前端代碼

2022-02-22 13:14:30

Vue自定義指令注冊

2023-07-21 19:16:59

OpenAIChatGPT

2020-12-28 10:10:04

Vue自定義指令前端

2024-09-26 14:16:07

2022-08-01 11:41:00

Vue插件

2010-10-25 16:05:07

oracle自定義函數

2022-04-24 15:17:56

鴻蒙操作系統

2010-09-14 16:47:23

SQL自定義函數

2017-05-19 10:03:31

AndroidBaseAdapter實踐

2023-12-21 09:00:21

函數React 組件useEffect

2017-05-18 12:36:16

android萬能適配器列表視圖

2010-05-11 13:16:21

Unix awk

2015-02-12 15:33:43

微信SDK

2009-06-24 15:13:36

自定義JSF組件

2023-02-20 15:20:43

啟動頁組件鴻蒙

2021-12-24 15:46:23

鴻蒙HarmonyOS應用

2024-06-03 10:00:51

Vue 3語法插槽
點贊
收藏

51CTO技術棧公眾號

亚洲摸下面视频| 亚洲综合一区二区三区| 国产欧美一区二区三区在线看 | 无码人妻av一区二区三区波多野| 久久不见久久见免费视频7| 欧美在线啊v一区| 久久人妻无码一区二区| 精品视频一二区| 韩国三级在线一区| 97av视频在线| 日本中文在线视频| 亚洲精品一级二级三级| 欧美一区二区精品在线| 国产一区视频免费观看| 暖暖在线中文免费日本| 欧美激情一区二区三区在线| 国产v亚洲v天堂无码| 在线免费一区二区| 伊人激情综合| 久久综合网hezyo| 成年人在线免费看片| 伦理一区二区三区| 欧美一级日韩一级| 少妇网站在线观看| 在线男人天堂| 亚洲国产欧美日韩另类综合| 在线国产精品网| 成人免费在线电影| 26uuu亚洲| 国产欧美一区二区三区另类精品 | 国产精品第72页| 国产精品成人av| 国产香蕉一区二区三区在线视频 | 日日摸天天爽天天爽视频| 色a资源在线| 日韩一区日韩二区| 日韩一区二区三区资源| 三区在线观看| 99re成人精品视频| 国产一区二区高清不卡 | 亚洲欧美国产va在线影院| 国产麻豆剧传媒精品国产| 亚洲精品成a人ⅴ香蕉片| 在线观看不卡视频| 国产裸体舞一区二区三区| 超碰在线视屏| 精品人伦一区二区三区蜜桃免费| 欧美国产视频一区| 影音先锋男人资源在线| 一区二区三区在线视频免费| 亚洲精品偷拍视频| 成a人片在线观看| 亚洲私人影院在线观看| 在线观看成人av| 麻豆视频在线播放| 亚洲色图欧洲色图婷婷| 中文字幕av导航| 成人在线播放免费观看| 亚洲另类春色国产| 亚洲高潮无码久久| 国精一区二区三区| 午夜精品福利在线| 怡红院av亚洲一区二区三区h| 日韩电影毛片| 日本高清不卡aⅴ免费网站| 国产v亚洲v天堂无码久久久| 日本成人片在线| 欧美午夜一区二区三区免费大片| 一区二区三区视频网| 日韩欧国产精品一区综合无码| 欧美日韩国产影片| 婷婷中文字幕在线观看| 538任你躁精品视频网免费| 亚洲成人免费在线视频| 中文字幕一区二区三区人妻不卡| 国产永久精品大片wwwapp| 爽爽爽爽爽爽爽成人免费观看| 欧美另类videoxo高潮| 亚洲在线久久| 国语自产精品视频在免费| 欧美激情黑白配| 麻豆精品在线视频| 99中文视频在线| 五月婷婷在线播放| 中文字幕av一区 二区| 欧美少妇在线观看| 亚洲国产福利| 欧美精品第一页| 国产一卡二卡三卡四卡| 国产a久久精品一区二区三区| 色小说视频一区| 国产无遮挡aaa片爽爽| 另类激情亚洲| 97人人香蕉| 九九在线视频| 亚洲综合一二三区| 久久久不卡影院| 精品国产乱码久久久久久蜜臀 | 视频国产精品| 亚洲另类激情图| 日韩精品123区| 夜久久久久久| 成人精品视频在线| 五十路在线视频| 亚洲天堂福利av| 能看的毛片网站| 亚洲不卡在线| 日韩一区二区av| 五月婷婷视频在线| 福利电影一区二区三区| 亚洲国产欧美一区二区三区不卡| www欧美xxxx| 欧美精品第1页| 法国空姐电影在线观看| 国产精品v欧美精品v日本精品动漫| 国产成人精品免费视频| 丁香六月天婷婷| 最新日韩av在线| 手机看片福利日韩| 小说区图片区色综合区| 色综合久久久888| 亚洲天堂一二三| 国产亚洲午夜高清国产拍精品 | 日韩欧美一级二级三级久久久| 毛片网站免费观看| 亚洲一级网站| 91精品啪aⅴ在线观看国产| 高清日韩av电影| 欧美午夜片欧美片在线观看| 性欧美18—19sex性高清| 综合激情在线| 91夜夜未满十八勿入爽爽影院| 国产在线电影| 色综合欧美在线视频区| 性久久久久久久久久久| 国产一区二区三区四区三区四| 91精品国产自产在线| 国产三区四区在线观看| 欧美午夜丰满在线18影院| 精品一区二区三区四区五区六区| 欧美黄污视频| www.久久艹| 亚洲丝袜一区| 精品三级在线观看| 强乱中文字幕av一区乱码| 国产一区在线不卡| 国产精品99久久久久久大便| 亚洲日韩中文字幕一区| 色噜噜狠狠狠综合曰曰曰| 国产情侣免费视频| 国产日韩精品一区二区三区| 青青在线视频免费| 精品国产99| 国产精品视频自在线| 性开放的欧美大片| 欧美高清视频不卡网| 免费成年人视频在线观看| 国产精品一区不卡| 亚洲精品蜜桃久久久久久| 国产美女撒尿一区二区| 97av在线视频| 成人亚洲性情网站www在线观看| 欧美日韩一区在线观看| 一级片一级片一级片| 国产福利一区二区三区视频在线| av无码久久久久久不卡网站| 性人久久久久| 国产精品亚洲美女av网站| 老司机精品影院| 日韩一区二区在线看| 国产一级片免费看| 久久亚洲精华国产精华液| 国产亚洲天堂网| 日本不卡高清| 亚洲一区二区在线| 成人免费观看在线观看| 日韩av中文字幕在线播放| 精人妻无码一区二区三区| 国产精品黄色在线观看| 不许穿内裤随时挨c调教h苏绵| 精品福利电影| 日韩女优中文字幕| 国产一区一区| 日本欧美精品在线| 超碰在线caoporn| 日韩成人在线视频网站| 中文字幕一区二区三区四区视频| 亚洲精品五月天| 3d动漫精品啪啪一区二区下载| 蜜臀av性久久久久av蜜臀妖精| 精品国产一区二区三区无码| 精品久久一区| 岛国一区二区三区高清视频| 欧美www.| 欧美精品激情blacked18| 国产在线视频资源| 日韩欧美一区二区三区在线| 欧美精品韩国精品| 亚洲精品久久久久久国产精华液| 欧美黑人欧美精品刺激| 国产一区二区视频在线| 欧美精品色婷婷五月综合| 天天做综合网| 日韩欧美精品在线不卡| 国产日韩三级| 亚洲影院色无极综合| 免费观看成人性生生活片 | 免费看av不卡| 久久久久久com| 欧美r级在线| 亚洲天堂av女优| 免费观看国产精品| 欧美日韩一区二区三区高清| 亚洲婷婷综合网| 亚洲v日本v欧美v久久精品| 三级黄色在线观看| 国产婷婷色一区二区三区| 手机在线成人av| 国产成人av一区二区三区在线| 最新中文字幕2018| 免费日韩av| 成人午夜免费在线| 国模 一区 二区 三区| 国产精品av免费| 日本精品三区| 日本精品免费| 婷婷亚洲成人| 久久影院理伦片| 欧美a一欧美| 含羞草久久爱69一区| 91成人入口| 亚洲最大av在线| 伊人久久一区| 91网站在线看| 国产精品日本一区二区不卡视频| 国产精品视频在线播放| 91p九色成人| 国产精品久久久久久久久影视| 日韩三级影视| 日韩免费av一区二区| 波多野结衣久久精品| 全球成人中文在线| 自拍偷拍欧美视频| 国产99视频精品免视看7| 在线毛片观看| 日韩av不卡在线| 欧美日韩国产网站| 国产剧情久久久久久| 久久精品黄色| 91在线国产电影| 亚洲视频国产| 国产视频一区二区不卡| 欧美a一欧美| 蜜桃av久久久亚洲精品| 精品视频免费在线观看| 婷婷五月色综合| 99久久夜色精品国产亚洲狼| 亚洲国产精品影视| 欧美精品三级| 亚洲熟妇国产熟妇肥婆| 久久国产高清| 在线黄色免费看| 国产精品99精品久久免费| 亚洲自拍偷拍精品| 久久综合五月天婷婷伊人| 国产18无套直看片| 亚洲精品你懂的| 精品99在线观看| 欧美日韩裸体免费视频| 亚洲男人天堂网址| 欧美一三区三区四区免费在线看| 高h调教冰块play男男双性文| 日韩电视剧免费观看网站| 国产视频精选在线| 久久精品国产精品亚洲| 国产盗摄精品一区二区酒店| 欧美一性一乱一交一视频| 男人亚洲天堂| 电影午夜精品一区二区三区| 国产成人三级| 青草全福视在线| 国产精品日韩久久久| 特级丰满少妇一级| 岛国精品在线观看| 欧美大波大乳巨大乳| 亚洲毛片av在线| 草久视频在线观看| 欧美精品在线观看一区二区| 色丁香婷婷综合久久| 中文字幕精品在线| av成人 com a| 国产日韩精品电影| 美女午夜精品| 日韩第一页在线观看| 国产日韩免费| 日本亚洲一区二区三区| 久久夜色精品国产噜噜av| 538精品在线视频| 色狠狠一区二区| 欧日韩在线视频| 精品国产一区二区三区在线观看 | 国产日本欧美一区二区三区在线| 亚洲精品在线a| 性刺激综合网| 国产精品视区| 久久黄色一级视频| 国产精品全国免费观看高清| 国产视频91在线| 日韩午夜电影在线观看| 91大神在线网站| 欧美一区二区.| 国产精品45p| 一二三四中文字幕| 蜜臀国产一区二区三区在线播放| 国产精品无码网站| 一个色综合网站| 国产普通话bbwbbwbbw| 永久555www成人免费| 中国字幕a在线看韩国电影| 成人一区二区在线| 91成人看片| 日本国产一级片| 国产精品麻豆视频| 国产主播第一页| 精品亚洲一区二区| 成人bbav| 九九九九九精品| 亚洲国产一区二区精品专区| 在线免费黄色小视频| 18成人在线观看| 影音先锋国产资源| 一区二区欧美激情| 日本欧美一区| 日韩影院一区| 青青草成人在线观看| 99久久久无码国产精品衣服| 色视频欧美一区二区三区| 日本天堂影院在线视频| 欧美专区国产专区| 亚洲国产欧美日韩在线观看第一区 | www.成人av| 中国成人一区| 中文字幕在线视频一区二区| 亚洲另类在线视频| 国产成人av免费看| 综合激情国产一区| 久久精品 人人爱| 一区二区三区日韩视频| 精品一区二区三区影院在线午夜| 操她视频在线观看| 91精品婷婷国产综合久久竹菊| 超碰最新在线| 成人精品水蜜桃| 亚洲一区日韩| 级毛片内射视频| 欧美丝袜自拍制服另类| 麻豆传媒在线观看| 99c视频在线| 亚洲国产专区| 波多野结衣片子| 欧美色综合久久| 超鹏97在线| 国产精品免费在线| 亚洲一区欧美激情| 久久午夜精品视频| 欧美一区二区三区在线视频 | 欧美资源在线观看| 人人狠狠综合久久亚洲婷| 四川一级毛毛片| 精品动漫一区二区三区| www视频在线观看免费| 92福利视频午夜1000合集在线观看| 欧美精品综合| 我和岳m愉情xxxⅹ视频| 欧美日韩亚洲另类| 欧美xxxxhdvideosex| 久久久久久高清| 久久精品理论片| 国产精品第九页| 国产一区二区成人| 欧美经典影片视频网站| 九色在线视频观看| 国产精品三级久久久久三级| 国产wwwwwww| 情事1991在线| 欧美日本不卡高清| 精品成人av一区二区三区| 91精品国产美女浴室洗澡无遮挡| 啊啊啊久久久| 亚洲永久激情精品| 99精品国产视频| 一级特黄aa大片| 8x拔播拔播x8国产精品| 97视频精品| 中文字幕丰满乱子伦无码专区| 制服丝袜激情欧洲亚洲| 中文日产幕无线码一区二区| www婷婷av久久久影片| 国产无一区二区| 六月丁香色婷婷|