天天看點

小白視角:vue3自定義指令開發,一步步那種,不會你打我最後如果有不對的地方,各位大佬請見諒并指出,這是弟弟的個人了解而已~小萌新一個,一起加油。

注意事項:寫法從extend替換成了createApp

閱前須知:

vue2 和 vue3 的自定義指令方式有點不一樣

vue2 是 extend 去挂載dom元素

vue3 不再支援 extend 了,要用createApp生成執行個體去挂載

(我也是看文章才知道,大家可以去搜下,然後這個demo我是用TS去寫的,後面會是anyScript,因為剛接觸TS不太懂文法,然後就直接在這個項目上寫來玩了)

不對的地方大家多多體諒哈~小編是小萌新

第一步: 建立loading.vue元件

建立一個.vue 檔案,寫出你loading的樣式,這裡我就不寫了,大家可以網上找下(畢竟需求不一樣)。

第二步: 建立ts檔案

建立一個.ts檔案,作為一個導出檔案。

第三步: 挂載與導出

我們需要在.ts檔案引入我們寫好的

loading.vue 檔案、

createApp方法:

下面展示一些

示例

import Loading from "./loading.vue"
import { createApp } from "vue";
           

随後我們定義一個導出對象,用來暴露在main中的進行注冊,然後方法就可以在裡面書寫了。

const loadingObj = {
}
export default loadingObj;
           

注意: 暴露出來的鈎子函數不太一樣了

vue2: bind,inserted,update,componentUpdated,unbind。

vue3: created,mounted,updated,unmounted

createApp的作用:

建立app執行個體,這個時候是處于遊蕩階段,等待挂載。

這個時候的app執行個體屬于Vue的一個準備階段,為後面的mount等操作準備好了所需要使用到的函數。

小白視角:vue3自定義指令開發,一步步那種,不會你打我最後如果有不對的地方,各位大佬請見諒并指出,這是弟弟的個人了解而已~小萌新一個,一起加油。
mount是比較核心,和vue2差不多,反正一句話就是進行渲染該元件
小白視角:vue3自定義指令開發,一步步那種,不會你打我最後如果有不對的地方,各位大佬請見諒并指出,這是弟弟的個人了解而已~小萌新一個,一起加油。

接下來寫下代碼~(AnyScript了解一下)

// 這段代碼可以放在mounted裡面挂載在el身上,友善操作。但是我試過放在頂部也是可以用的
  const app = createApp(Loading);
  const instance:any = app.mount(document.createElement("div")); // 你也可以挂載在全局的app下,反正就給個dom它
           

然後和vue2的寫法差不多,就是鈎子有點變化而已:

mounted(el:any, bind:any) {
    // 這段代碼我放在mounted裡挂載在el身上,傳參的時候可以友善調用
    const app = createApp(Loading);
    const instance:any = app.mount(document.createElement("div"));
    console.log("instance",instance);
    el.instance = instance;
    // 這裡是我元件裡面的方法,調用這個去更新值,也可以直接改data的值,見仁見智哈~安全而已
    el.instance.setLoading("我是努力加載中");
    if(bind.value) {  // v-loading="true"時候調用添加在元件
      appndChild(el)
    }
  },
           

接下來是更新的時候觸發的事件:

updated(el:any, bind:any){
    if(bind.value !== bind.oldValue){
      bind.value? appndChild(el): remove(el);
    }
  }
           

公共方法:

function appndChild(el:any){
  el.appendChild(el.instance.$el);
}
function remove(el:any){
  el.removeChild(el.instance.$el);
}
           

然後在main.ts中去注冊就行。

import { createApp } from 'vue'
import App from './App.vue'
import direactive from "../src/hooks/direactive"

const app = createApp(App);

app.directive("loading",direactive).mount('#app')
           

接下來談談題外話,自定義指令的注冊方式:

第一種:和以前vue2一樣,通過暴露出一個對象,裡面有install方法,然後通過vue.use去全局注冊,代碼如下:
import { App } from 'vue'
export default {
    install(vue){
      app.directive("loading",{
        created(){
        },
        mounted(){
        }
      })
    }
}
**然後在main.ts注冊就行**
import loading  from './loading'
let app = createApp(App)
app.use(loading)

           
第二種就是我上面寫的方式,在app執行個體下,通過調用app.directive(“loading”,direactive)去使用,這種寫法我感覺就相當于局部建立的一樣,不過這個局部是全局的執行個體而已。(個人了解,不對别打我哈~)
import { createApp } from 'vue'
import App from './App.vue'
import direactive from "../src/hooks/direactive"

const app = createApp(App);

app.directive("loading",direactive).mount('#app')
           

下面列印下挂載後的instance執行個體,友善和我一樣懶的小夥伴

const instance:any = app.mount(document.createElement(“div”));
小白視角:vue3自定義指令開發,一步步那種,不會你打我最後如果有不對的地方,各位大佬請見諒并指出,這是弟弟的個人了解而已~小萌新一個,一起加油。
挂載後的dom對象結構,你可以直接去改data的值控制顯示的樣式~
小白視角:vue3自定義指令開發,一步步那種,不會你打我最後如果有不對的地方,各位大佬請見諒并指出,這是弟弟的個人了解而已~小萌新一個,一起加油。

我貼下全部的代碼:

import Loading from "./loading.vue";
import { createApp } from "vue";

const LoadingObj = {
  mounted(el:any, bind:any) {
    const app = createApp(Loading);
    const instance:any = app.mount(document.createElement("div"));
    el.instance = instance;
    el.instance.setLoading("我是努力加載中");
    if(bind.value) {
      appndChild(el)
    }
  },
  updated(el:any, bind:any){
    if(bind.value !== bind.oldValue){
      bind.value? appndChild(el): remove(el);
    }
  }
 
}
function appndChild(el:any){
  el.appendChild(el.instance.$el);
}
function remove(el:any){
  el.removeChild(el.instance.$el);
}
export default LoadingObj;
           

最後如果有不對的地方,各位大佬請見諒并指出,這是弟弟的個人了解而已~小萌新一個,一起加油。