精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

一本大道亚洲视频| 亚洲欧美日韩小说| 国产不卡精品视男人的天堂| 精品伦精品一区二区三区视频密桃| 日本免费在线一区| 午夜欧美在线一二页| 日韩午夜视频在线观看| 亚洲a视频在线观看| 久久亚洲精选| 久久亚洲精品成人| 欧美日韩高清丝袜| youjizz欧美| 欧美日韩免费高清一区色橹橹| 欧美做暖暖视频| 高清在线观看av| 成人在线视频一区| 成人情趣片在线观看免费| 亚洲天堂日韩av| 91成人影院| 色婷婷亚洲mv天堂mv在影片| 日韩美女天天操| 丁香婷婷激情网| 6699嫩草久久久精品影院| 中文字幕精品综合| 久久66热这里只有精品| 国产aⅴ一区二区三区| 国产精品美女| 欧美国产视频一区二区| 99热6这里只有精品| 亚洲素人在线| 亚洲精品www久久久| 激情成人在线观看| av成人在线观看| 欧美丝袜第一区| 农民人伦一区二区三区| 伊人手机在线| 一区在线观看免费| 亚洲图片都市激情| www.成人.com| 国产精品私人影院| 亚洲天堂一区二区三区| 成人动漫在线观看视频| 五月激情丁香网| 国产日韩在线视频| 成人做爰69片免费| 国产精品99久久免费| 欧美视频在线观看一区| 亚洲精品中文字幕无码蜜桃| 国产激情av在线| 视频精品国内| 91精品久久久久久久99蜜桃| 一级片视频免费观看| 一区二区视频免费完整版观看| 欧美日韩亚洲天堂| 国产91美女视频| 中文字幕在线看高清电影| 丰满大乳少妇在线观看网站| 亚洲免费伊人电影| 看全色黄大色大片| 国产一线二线在线观看| 一区二区不卡在线播放| 国产欧美精品aaaaaa片| 艳妇乳肉豪妇荡乳av| 国产一区二区电影在线观看| 亚洲成人性视频| 91精品久久久久久综合乱菊| 高潮毛片又色又爽免费| 久久精品主播| 国产精品人成电影| 国产女人高潮时对白| 国产v日产∨综合v精品视频| 在线不卡日本| 天堂在线中文资源| 久久久高清一区二区三区| 鲁丝一区二区三区免费| 国产高清视频在线播放| 中文字幕一区二区三区不卡| 亚洲爆乳无码精品aaa片蜜桃| 欧美aaaaaaa| 国产盗摄一区二区| 亚洲福利一二三区| 波多野结衣家庭教师在线播放| 国产免费拔擦拔擦8x高清在线人| 午夜天堂影视香蕉久久| 50路60路老熟妇啪啪| 高清欧美日韩| 黄色成人在线网站| 97视频在线观看免费高清完整版在线观看 | 日韩一区二区电影在线观看| 97在线观看免费观看高清 | 国语精品视频| 亚洲国产日韩欧美在线99| 国产精久久一区二区三区| 欧美99久久| 亲爱的老师9免费观看全集电视剧| 最新国产中文字幕| 成人晚上爱看视频| 先锋在线资源一区二区三区| 日本大胆在线观看| 欧美性淫爽ww久久久久无| 韩国三级在线播放| 国产一区网站| 欧美激情二区三区| 涩涩视频在线观看| 成人少妇影院yyyy| 亚洲最新在线| 久久青青视频| 精品国产乱码久久久久久浪潮 | 天堂在线视频免费观看| 国产精品国产三级国产普通话三级| 国产二区视频在线| 亚洲国产伊人| 国产亚洲精品高潮| 91国产丝袜播放在线| 国内精品伊人久久久久av一坑| 久久伊人资源站| 伦理在线一区| 欧美一区二视频| 欧美另类z0zx974| 国产日韩1区| av一区二区三区四区电影| avav免费在线观看| 色系网站成人免费| 亚洲av成人片无码| 国语自产精品视频在线看8查询8| 国产一区视频在线播放| 免费在线一区观看| 国产精品偷伦免费视频观看的| 性感美女福利视频| 亚洲一区日韩精品中文字幕| 日韩成人精品视频在线观看| 精品免费在线| 国产成人综合一区二区三区| 神马电影在线观看| 亚洲高清在线精品| 日韩黄色一区二区| 欧美日本一区| 国产69精品久久久久9999apgf | 国产一级片一区二区| 久久综合资源网| 能在线观看的av| 美国成人xxx| 久久久人成影片一区二区三区观看 | 亚洲第一区中文字幕| 国产真实乱偷精品视频| 国产1区2区3区精品美女| 欧美一级特黄aaaaaa在线看片| 24小时成人在线视频| 久久九九精品99国产精品| 一级片aaaa| 亚洲天堂网中文字| 国产探花一区二区三区| 午夜精品久久99蜜桃的功能介绍| 97神马电影| 成年人国产在线观看| 亚洲第一中文字幕在线观看| 日本少妇在线观看| 黑人精品无码一区二区三区AV| 亚洲最大av| 97超碰人人模人人爽人人看| 亚洲wwwww| 亚洲国产欧美一区| 亚洲黄色小说图片| 久久精品一区蜜桃臀影院| 日韩手机在线观看视频| 经典一区二区| 成人xxxxx| 1024在线播放| 日韩av一区二区在线| 日本免费在线观看视频| 国产精品国产成人国产三级 | 亚洲性日韩精品一区二区| 日韩电影在线观看一区二区| 国产精品久久久久久久久久久免费看 | 精品亚洲精品福利线在观看| av图片在线观看| 亚洲国产精品成人久久综合一区| 欧美日韩精品区别| 影音国产精品| 色噜噜色狠狠狠狠狠综合色一 | 久久伦理网站| 欧美高清xxx| 久久久免费观看| 大胆av不用播放器在线播放| 日韩手机在线导航| 亚洲欧美综合自拍| 亚洲九九爱视频| 一级黄色片大全| 国产精品一二三在| 色综合av综合无码综合网站| 婷婷亚洲五月| 欧美精品一区在线发布| 国产精品va视频| 国产精品wwwwww| 日本一级理论片在线大全| 国产亚洲欧洲高清一区| 成人免费视频国产免费麻豆| 欧美在线视频不卡| 国产污视频在线看| 亚洲欧洲日产国产综合网| 少妇饥渴放荡91麻豆| 国产精品资源网站| 久久久国产欧美| 亚洲三级电影在线观看| 亚洲综合首页| 国产人妻一区二区| 国产精品婷婷| www.69av| 成人女性视频| 九色综合日本| 伊色综合久久之综合久久| 国产精品成人国产乱一区| 激情黄产视频在线免费观看| 欧美成人免费一级人片100| 激情小视频在线| 亚洲激情中文字幕| 亚洲风情第一页| 欧美高清视频在线高清观看mv色露露十八| 日韩精品――中文字幕| 亚洲黄网站在线观看| 国产成人免费在线观看视频| 国产日韩成人精品| 男生裸体视频网站| 成人av免费在线观看| wwwww在线观看| 精品一区二区三区香蕉蜜桃| 国产视频手机在线播放| 日韩成人免费在线| av免费中文字幕| 夜夜嗨网站十八久久| www插插插无码免费视频网站| 亚洲91久久| 中文字幕欧美日韩一区二区| 精品一区二区三区在线| 日本欧洲国产一区二区| 天天躁日日躁狠狠躁欧美巨大小说| 成人av播放| 91亚洲无吗| 国产精品久久久一区二区三区| 久久久精品区| 亚洲综合在线小说| 996久久国产精品线观看| 91久久久在线| 国产一区 二区| 92国产精品久久久久首页| 国产精品久久久久久久久久辛辛| 国产美女精品视频免费观看| 国产情侣一区二区三区| 国产精品综合不卡av| 国产精品传媒麻豆hd| 国产日韩专区在线| 亚洲久草在线| 99国产在线视频| 风间由美中文字幕在线看视频国产欧美| av资源一区二区| 99re91这里只有精品| 精品卡一卡二| 九九亚洲视频| 亚洲一区二区三区加勒比| 日韩在线欧美| 老司机午夜网站| 999亚洲国产精| 国产精品99久久免费黑人人妻| 免费观看在线综合| 亚洲国产综合av| 91在线观看免费视频| 中文字幕第20页| 亚洲欧美日韩一区二区| 日韩欧美激情视频| 欧美性xxxxxxxx| 精品国产999久久久免费| 亚洲第一男人天堂| 国产系列电影在线播放网址| 按摩亚洲人久久| 国产白丝在线观看| 国产精品久久久久久久久粉嫩av| 99久热在线精品视频观看| 99三级在线| 欧美猛男同性videos| 青少年xxxxx性开放hg| 亚洲国产精品第一区二区| 少妇性l交大片| 国产一区二区视频在线| 日本丰满少妇裸体自慰| 亚洲欧洲99久久| 天堂网av手机版| 91精品国产91综合久久蜜臀| 外国精品视频在线观看| 日韩在线中文字| 久久影院午夜精品| 成人xxxxx| 国产伦精品一区二区三区视频| 欧美 国产 精品| 日韩一区精品视频| 性农村xxxxx小树林| 国产精品卡一卡二| 亚洲 欧美 成人| 日韩精品资源二区在线| www日韩tube| 2021久久精品国产99国产精品| 日韩av黄色| 欧美精品一区二区三区久久| 国产精品啊啊啊| 手机在线成人免费视频| 91小视频在线| 久草资源在线视频| 欧美三级电影网站| 五月婷婷久久久| 欧美福利视频网站| 欧美成人黄色| 日韩欧美一区二区视频在线播放| 1024精品一区二区三区| 一级黄色片在线免费观看| 国产日韩在线不卡| 99精品在线播放| 亚洲成人精品久久| 中文字幕免费高清电视剧网站在线观看| 国产成人精品在线视频| 美女视频免费精品| 成人在线视频一区二区三区| 久久99精品久久久| 精品手机在线视频| 在线这里只有精品| 你懂的在线视频| 日韩av成人在线| 日韩美女毛片| 青青青青草视频| 成人国产精品免费网站| 九九视频在线免费观看| 欧美一区二区三级| 国产cdts系列另类在线观看| 国产日韩在线亚洲字幕中文| 日韩欧美伦理| av污在线观看| 中文字幕中文乱码欧美一区二区| 日本欧美www| 中文字幕精品一区久久久久| 国产精成人品2018| 天堂一区二区三区| 青青草国产精品亚洲专区无| 免费看黄色三级| 欧美日本韩国一区二区三区视频| 成人av毛片| 成人福利在线观看| 911久久香蕉国产线看观看| 一级做a爱视频| 一区二区三区不卡视频在线观看| 精品人妻一区二区三区浪潮在线 | 男的操女的网站| 制服丝袜激情欧洲亚洲| 99久久精品免费观看国产| 亚洲一区二区三区久久| 欧美日韩hd| 亚州av综合色区无码一区| 欧美日韩亚洲精品一区二区三区| 日韩大胆人体| 国产精品欧美日韩久久| 三区四区不卡| 91香蕉国产线在线观看| 亚洲一区二区三区小说| 国产又爽又黄网站亚洲视频123| 欧美性视频精品| 欧美理论视频| 香蕉视频色在线观看| 天天综合网天天综合色| 国产在线观看黄| 成人性生交xxxxx网站| 欧美喷水视频| 老牛影视av老牛影视av| 欧美精品亚洲一区二区在线播放| 伊人手机在线| 欧美人xxxxx| 国产一区欧美日韩| 少妇一级淫片免费放中国| 中文字幕欧美精品在线| 精品一区91| 国产午夜福利视频在线观看| 中文字幕国产一区二区| 亚洲国产精品18久久久久久| 91sao在线观看国产| 99久精品视频在线观看视频| 蜜臀av粉嫩av懂色av| 欧美亚洲动漫精品| 黄视频在线免费看| 亚洲高清在线观看一区| 粉嫩av一区二区三区在线播放| 黄色污污视频软件| 欧美高清不卡在线| 精品久久国产| 欧美xxxxx精品| 欧美日韩国产在线观看| 成av人片在线观看www| 亚洲电影免费| 成人国产免费视频| 国产又粗又猛又爽| 日韩美女视频免费在线观看| 国产综合精品一区| 三级黄色免费观看| 亚洲人成网在线播放| 成人知道污网站|