<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【Vue.js】1711- 深入淺出 Vue3 自定義指令

          共 12181字,需瀏覽 25分鐘

           ·

          2023-06-12 11:13

          28baf8805859331f85e4615018735bde.webp

          Vue.js[1] 提供了豐富的指令來簡(jiǎn)化開發(fā)者的工作。除了內(nèi)置指令外,Vue.js 還支持自定義指令,開發(fā)者可以根據(jù)自己的需求擴(kuò)展 Vue.js 的指令庫(kù)。Vue.js 3.x 相較于 Vue.js 2.x 在自定義指令方面進(jìn)行了一些改進(jìn),本文將介紹 Vue.js 3.x 中自定義指令的使用方法。

          ? 什么是自定義指令

          1. 概念介紹

          在 Vue.js 中,指令 (Directives) 是一種帶有 v- 前綴的特殊屬性。它的作用是「當(dāng)其綁定的元素被插入到 DOM 中時(shí),會(huì)立即執(zhí)行一些行為」。 Vue.js 中有許多內(nèi)置指令,比如:

          • v-model:在表單元素上創(chuàng)建「雙向數(shù)據(jù)綁定」
          • v-show:根據(jù)表達(dá)式之真假值,「切換元素的 display CSS 屬性」
          • v-if:根據(jù)表達(dá)式之真假值「渲染或銷毀元素」
          • v-for:基于一個(gè)數(shù)組來渲染一個(gè)列表。

          這些指令讓我們可以更加聲明式地操作 DOM,隱藏復(fù)雜的 DOM 操控邏輯。 除了內(nèi)置的指令,Vue.js 也允許我們注冊(cè)自定義指令[2]。自定義指令「允許我們?cè)阡秩镜?DOM 元素上應(yīng)用自定義的行為」

          2. 基礎(chǔ)使用

          以全局自定義指令為例,通過全局方法 app.directive(name, options) 進(jìn)行注冊(cè),并使用 v- 前綴在模板中應(yīng)用。directive() 方法接收兩個(gè)參數(shù):

          • name:指令名稱,如 focus
          • options:指令配置對(duì)象,其中包含「指令的鉤子函數(shù)」

          下面以自定義指令 v-focus作為示例介紹,首先創(chuàng)建 v-focus指令:

                
                const?app?=?createApp({});
          app.directive("focus",?{
          ??//?當(dāng)綁定元素插入到?DOM?中時(shí)......
          ??mounted(el)?{
          ????//?聚焦元素
          ????el.focus();
          ??},
          });

          然后在模板中使用:

                
                
                  <input?v-focus?/>
                  

          當(dāng)輸入框掛載到 DOM 時(shí),它將自動(dòng)獲得焦點(diǎn)。 一個(gè)自定義指令定義對(duì)象可以提供以下「鉤子函數(shù)」

                
                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)?{},
          };

          每個(gè)鉤子函數(shù)的參數(shù)包括:

          • el:指令綁定到的元素。可以用于直接操作 DOM。
          • binding:一個(gè)對(duì)象,包含valueoldValueargmodifiersinstancedir屬性。
          • vnode:代表綁定元素的底層 VNode。
          • prevNode:之前的渲染中代表指令所綁定元素的 VNode。僅在 beforeUpdateupdated 鉤子中可用。

          參數(shù)的詳細(xì)介紹,可以查看文檔《Hook Arguments[3]》。

          ??? 自定義指令分類

          1. 按指令注冊(cè)方式分類

          自定義指令按「指令注冊(cè)方式」可以分為:「全局指令」「局部指令」

          • 「全局指令」

          全局注冊(cè)的指令可以「在應(yīng)用程序的任何組件中使用」,通常在 Vue 的 app 實(shí)例上通過 directive()進(jìn)行注冊(cè):

                
                const?app?=?createApp({});
          app.directive("focus",?{
          ??//?當(dāng)綁定元素插入到?DOM?中時(shí)......
          ??mounted(el)?{
          ????//?聚焦元素
          ????el.focus();
          ??},
          });
          • 「局部指令」

          局部注冊(cè)的指令僅「在其注冊(cè)的組件中可用」,通常在組件配置對(duì)象中進(jìn)行注冊(cè):

                
                const?Component?=?defineComponent({
          ??directives:?{
          ????focus:?{
          ??????mounted(el)?{
          ????????el.focus();
          ??????},
          ????},
          ??},
          ??render()?{
          ????const?{?directives?}?=?this.$options;
          ????return?[withDirectives(h("input"),?[[directives.focus]])];
          ??},
          });

          2. 按指令實(shí)現(xiàn)方式分類

          自定義指令按「指令實(shí)現(xiàn)方式」可以分為:「對(duì)象指令」「函數(shù)指令」

          • 「對(duì)象指令 ObjectDirective」

          對(duì)象指令以對(duì)象形式實(shí)現(xiàn),提供了更多的選項(xiàng)和生命周期方法:

                
                const?app?=?createApp({});
          app.directive("focus",?{
          ??//?當(dāng)綁定元素插入到?DOM?中時(shí)......
          ??mounted(el)?{
          ????//?聚焦元素
          ????el.focus();
          ??},
          });

          在源碼里面接口類型定義如下:

                
                export?interface?ObjectDirective<T?=?any,?V?=?any>?{
          ??created?:?DirectiveHook<T,?null,?V>;
          ??beforeMount?:?DirectiveHook<T,?null,?V>;
          ??mounted?:?DirectiveHook<T,?null,?V>;
          ??beforeUpdate?:?DirectiveHook<T,?VNode<any,?T>,?V>;
          ??updated?:?DirectiveHook<T,?VNode<any,?T>,?V>;
          ??beforeUnmount?:?DirectiveHook<T,?null,?V>;
          ??unmounted?:?DirectiveHook<T,?null,?V>;
          ??getSSRProps?:?SSRDirectiveHook;
          }
          • 「函數(shù)指令 FunctionDirective」

          函數(shù)指令是對(duì)象指令的簡(jiǎn)化形式,使用起來更加簡(jiǎn)單,適合于只需執(zhí)行一些操作的場(chǎng)景。 通常僅僅需要在 mountedupdated 上實(shí)現(xiàn)相同的行為,除此之外并不需要其他鉤子。這種情況下可以直接用一個(gè)函數(shù)來定義指令,如下所示:

                
                app.directive("color",?(el,?binding)?=>?{
          ??//?這會(huì)在?`mounted`?和?`updated`?時(shí)都調(diào)用
          ??el.style.color?=?binding.value;
          });

          在源碼里面接口類型定義如下:

                
                export?type?FunctionDirective<T?=?any,?V?=?any>?=?DirectiveHook<T,?any,?V>;

          export?type?DirectiveHook<T?=?any,?Prev?=?VNode<any,?T>?|?null,?V?=?any>?=?(
          ??el:?T,
          ??binding:?DirectiveBinding<V>,
          ??vnode:?VNode<any,?T>,
          ??prevVNode:?Prev
          )?=>?void;

          ?? 注意事項(xiàng)

          在使用自定義指令時(shí),有一些注意事項(xiàng)需要牢記。這些包括指令命名的規(guī)則、指令的生命周期和鉤子函數(shù)的執(zhí)行順序等。 以下是 5 個(gè)常見注意事項(xiàng):

          • 指令需要使用多個(gè)參數(shù)時(shí),可以傳遞一個(gè) JS 對(duì)象字面量
                
                <div?v-demo="{?color:?'white',?text:?'hello!'?}"></div>;

          app.directive("demo",?(el,?binding)?=>?{
          ??console.log(binding.value.color);?/
          /?=>?"white"
          ??console.log(binding.value.text);?/
          /?=>?"hello!"
          });
          1. 不推薦在組件上使用自定義指令,因?yàn)榻M件可能含有多個(gè)根節(jié)點(diǎn)

          attribute 不同,指令不能通過 v-bind="$attrs" 來傳遞給一個(gè)不同的元素。

                
                
                  <MyComponent?v-demo="test"?/>
                  
                
                <!--?MyComponent?的模板?-->

          <div>
          ??<!--?v-demo?指令會(huì)被應(yīng)用在此處?-->
          ??<span>My?component?content</span>
          </div>
          1. 自定義指令第二個(gè)參數(shù)支持一個(gè)對(duì)象配置

          定義指令時(shí),第一個(gè)參數(shù)除了指令名稱外,還接受一個(gè)對(duì)象,該對(duì)象包含指令鉤子函數(shù),這與 Vue2 不同,需要注意。

                
                app.directive("focus",?{
          ??mounted(el)?{
          ????el.focus();
          ??},
          });
          1. v-for 渲染的元素上,指令鉤子多次調(diào)用
                
                <ul>
          <li v-for="item in list" v-focus>
          </ul>

          focus 指令的鉤子函數(shù)會(huì)以每個(gè) li 元素為參數(shù)調(diào)用多次。

          1. v-on 修飾符 .native 不再支持

          編輯器會(huì)提示警告“'.native' modifier on 'v-on' directive is deprecated.

                
                <!-- 會(huì)產(chǎn)生警告, .native 修飾符已廢除 -->
          <input @click.native="doSomething">

          在 Vue3 中直接使用 @click 即可監(jiān)聽原生事件。

          ?? 使用示例

          接下來以 3 個(gè)使用示例做演示:

          v-preview

          通過 v-preview 自定義指令,實(shí)現(xiàn)「圖片預(yù)覽功能」。 指令實(shí)現(xiàn):

                
                //?指令實(shí)現(xiàn)
          export?default?{
          ??mounted(el)?{
          ????el.addEventListener("mouseenter",?(e)?=>?{
          ??????const?img?=?e.target;
          ??????const?src?=?img.src;
          ??????const?parent?=?img.closest(".img-preview-container");
          ??????parent.style.position?=?"relative";
          ??????const?preview?=?document.createElement("div");
          ??????preview.style.position?=?"absolute";
          ??????preview.style.top?=?0;
          ??????preview.style.left?=?0;
          ??????preview.style.background?=?"url("?+?src?+?")?no-repeat?center?center";
          ??????preview.style.backgroundSize?=?"contain";
          ??????preview.style.width?=?"100%";
          ??????preview.style.height?=?"100%";
          ??????parent.append(preview);
          ????});
          ????el.addEventListener("mouseleave",?(e)?=>?{
          ??????const?parent?=?e.target.closest(".img-preview-container");
          ??????parent.style.position?=?"";
          ??????const?preview?=?parent.querySelector("div");
          ??????preview.remove();
          ????});
          ??},
          };

          注冊(cè)指令:

                
                import?{?createApp?}?from?"vue";
          import?vPreview?from?"./directives/vPreview";
          import?App?from?"./App.vue";
          const?app?=?createApp(App);

          //?注冊(cè)指令
          app.directive("preview",?vPreview);

          app.mount("#app");

          使用指令:

                
                <div?class="img-preview-container">
          ??<img?v-for="src?in?imgSrcs"?:src="src"?v-preview?/>
          </div>

          當(dāng)鼠標(biāo)移入 img 元素時(shí),會(huì)根據(jù)其 src 展示對(duì)應(yīng)的圖片預(yù)覽。當(dāng)鼠標(biāo)移出時(shí),圖片預(yù)覽會(huì)消失。這個(gè) v-preview 自定義指令可以讓我們快速實(shí)現(xiàn)圖片預(yù)覽的交互效果。 指令中通過監(jiān)聽 mouseentermouseleave 事件展示和隱藏圖片預(yù)覽,使用 closest 方法獲取 img 元素的父容器,并在其上添加預(yù)覽圖片。

          2. v-uppercase

          通過 v-uppercase 自定義指令,實(shí)現(xiàn)「將文本自動(dòng)轉(zhuǎn)成大寫功能」。 指令實(shí)現(xiàn):

                
                export?default?{
          ??created(el,?binding)?{
          ????el.innerHTML?=?binding.value.toUpperCase();
          ??},
          ??update(el,?binding)?{
          ????el.innerHTML?=?binding.value.toUpperCase();
          ??},
          };

          注冊(cè)指令:

                
                import?{?createApp?}?from?"vue";
          import?vUppercase?from?"./directives/vUppercase";
          import?App?from?"./App.vue";
          const?app?=?createApp(App);

          //?注冊(cè)指令
          app.directive("uppercase",?vUppercase);

          app.mount("#app");

          使用指令:

                
                <p v-uppercase>hello</p>

          在頁(yè)面上顯示的是 “HELLO” 文本。v-uppercase 自定義指令在 createdupdate 鉤子中調(diào)用了 toUpperCase() 方法將文本轉(zhuǎn)換為大寫,并更新 innerHTML

          3. v-resize

          通過 v-resize 自定義指令,實(shí)現(xiàn)「監(jiān)聽窗口寬度變化」,執(zhí)行回調(diào)方法的功能。 指令實(shí)現(xiàn):

                
                export?default?{
          ??mounted(el,?binding)?{
          ????const?callback?=?binding.value;
          ????window.addEventListener("resize",?()?=>?{
          ??????callback(el.offsetWidth);
          ????});
          ??},
          };

          注冊(cè)指令:

                
                import?{?createApp?}?from?"vue";
          import?vResize?from?"./directives/vResize";
          import?App?from?"./App.vue";
          const?app?=?createApp(App);

          //?注冊(cè)指令
          app.directive("resize",?vResize);

          app.mount("#app");

          使用指令:

                
                <script setup lang="ts">
          const onResize = (width) => {
          console.log(width);
          };
          </script>

          <template>
          <div v-resize="onResize">寬度</div>
          </template>

          v-resize 自定義指令會(huì)在窗口尺寸發(fā)生變化時(shí),調(diào)用綁定的回調(diào)函數(shù),并傳入元素的 offsetWidth 值。在方法 onResize 中,我們可以根據(jù)元素的新的寬度 width 進(jìn)行相應(yīng)處理,例如:

          • 調(diào)整樣式
          • 調(diào)用 API 重新獲取數(shù)據(jù)
          • 重新布局頁(yè)面等

          這些指令比較簡(jiǎn)單,但在實(shí)際項(xiàng)目中使用卻非常廣泛,我們可以運(yùn)用相同思路編寫其他常用的指令,例如:

          • v-scroll 滾動(dòng)事件指令;
          • v-mouseenter / v-mouseleave 鼠標(biāo)進(jìn)入/離開事件指令;
          • v-longpress 長(zhǎng)按事件指令;

          這可以很好的幫助我們簡(jiǎn)化代碼并提高開發(fā)效率。

          ??? 渲染函數(shù)中如何使用

          1. 概念介紹

          如果要在 Vue3 渲染函數(shù)中使用自定義指令,就需要使用 [withDirectives](https://vuejs.org/api/render-function.html#withdirectives "withDirectives")函數(shù),其函數(shù)簽名如下:

                
                function?withDirectives(
          ??vnode:?VNode,?//?需要綁定自定義指令的元素
          ??directives:?DirectiveArguments
          ):?VNode
          ;

          //?自定義指令數(shù)組,數(shù)組形式:[Directive,?value,?argument,?modifiers]
          //?如果不需要,可以省略數(shù)組的尾元素。
          type?DirectiveArguments?=?Array<
          ??|?[Directive]
          ??|?[Directive,?any]
          ??|?[Directive,?any,?string]
          ??|?[Directive,?any,?string,?DirectiveModifiers]
          >;

          簡(jiǎn)單的使用示例:

                
                import?{?h,?withDirectives?}?from?"vue";

          //?一個(gè)自定義指令
          const?pin?=?{
          ??mounted()?{
          ????/*?...?*/
          ??},
          ??updated()?{
          ????/*?...?*/
          ??},
          };

          //?<div?v-pin:top.animate="200"></div>
          const?vnode?=?withDirectives(h("div"),?[[pin,?200,?"top",?{?animate:?true?}]]);

          2. 使用示例

          v-focus 自定義指令為例,可以按照以下步驟實(shí)現(xiàn):

          1. 導(dǎo)入 withDirectives 和自定義指令函數(shù):
                
                import?{?withDirectives?}?from?"vue";
          import?{?focus?}?from?"./directives";
          1. 在渲染函數(shù)中使用 withDirectives 函數(shù),并按順序傳遞參數(shù):
                
                const?vnode?=?h("input",?{
          ??type:?"text",
          ??modelValue:?"example",
          ??onInput:?(event)?=>?{
          ????//?...
          ??},
          });

          const?app?=?{
          ??render()?{
          ????return?withDirectives(vnode,?[[focus,?true]]);
          ??},
          };

          這個(gè)示例代碼中的 vnode 是一個(gè) input 元素的虛擬節(jié)點(diǎn),focusv-focus 自定義指令的函數(shù),true 是傳遞給自定義指令的參數(shù)數(shù)組,表示在元素插入文檔后自動(dòng)聚焦。

          ?? 總結(jié)

          本文介紹了 Vue.js 3.x 中自定義指令的基本使用方法,包括自定義指令函數(shù)的定義和注冊(cè)、指令函數(shù)中的參數(shù)和鉤子函數(shù)等內(nèi)容。自定義指令是 Vue.js 框架的一個(gè)非常重要的擴(kuò)展,開發(fā)者可以根據(jù)自己的需求自定義指令來簡(jiǎn)化開發(fā)工作、提高開發(fā)效率。 希望本文對(duì)您學(xué)習(xí) Vue.js 自定義指令有所幫助。

          ?? 學(xué)習(xí)資料

          以下是一些我個(gè)人認(rèn)為不錯(cuò) Vue3 自定義指令的學(xué)習(xí)資料:

          1. Vue.js 官方文檔:自定義指令[4]

          Vue.js 官方文檔是學(xué)習(xí) Vue.js 自定義指令的最佳入門資料,其中包括了自定義指令的定義、注冊(cè)和鉤子函數(shù)等方面的內(nèi)容,以及一些實(shí)際應(yīng)用的示例。

          1. Vue Mastery: Vue 3 Custom Directives[5]

          Vue Mastery 是一個(gè)非常優(yōu)秀的 Vue.js 在線教育平臺(tái),他們的 Vue 3 Custom Directives 課程是一份非常棒的學(xué)習(xí)資料,其中詳細(xì)介紹了 Vue.js 3.x 中自定義指令的使用方法和實(shí)踐技巧。

          1. Vue 3 Directives: A Comprehensive Guide In Depth[6]

          介紹了 Vue.js 3.x 中指令的使用方法和實(shí)踐技巧。該文章從指令的基礎(chǔ)知識(shí)入手,詳細(xì)介紹了 Vue.js 中內(nèi)置指令和自定義指令的使用方法,并通過實(shí)際應(yīng)用場(chǎng)景和示例來說明指令的作用和用法。

          Reference

          [1]

          Vue.js: https://vuejs.org/

          [2]

          自定義指令: https://vuejs.org/guide/reusability/custom-directives.html

          [3]

          Hook Arguments: https://vuejs.org/guide/reusability/custom-directives.html#directive-hooks

          [4]

          Vue.js 官方文檔:自定義指令: https://vuejs.org/guide/reusability/custom-directives.html

          [5]

          Vue Mastery: Vue 3 Custom Directives: https://www.vuemastery.com/courses/vue-3-essentials/custom-directives

          [6]

          Vue 3 Directives: A Comprehensive Guide In Depth: https://www.sciredev.com/blog/vue-3-directives-guide-in-depth


          往期回顧
          #

          如何使用 TypeScript 開發(fā) React 函數(shù)式組件?

          #

          11 個(gè)需要避免的 React 錯(cuò)誤用法

          #

          6 個(gè) Vue3 開發(fā)必備的 VSCode 插件

          #

          3 款非常實(shí)用的 Node.js 版本管理工具

          #

          6 個(gè)你必須明白 Vue3 的 ref 和 reactive 問題

          #

          6 個(gè)意想不到的 JavaScript 問題

          #

          試著換個(gè)角度理解低代碼平臺(tái)設(shè)計(jì)的本質(zhì)

          回復(fù)“加群”,一起學(xué)習(xí)進(jìn)步

          瀏覽 78
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  人人撸人人挺 | 成人做爰黄 片免费看 | 激情婷婷视频在线 | 日韩乱伦图片区 | 女人裸体一级片久久久 |