注意事項:寫法從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等操作準備好了所需要使用到的函數。
mount是比較核心,和vue2差不多,反正一句話就是進行渲染該元件
接下來寫下代碼~(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”));
挂載後的dom對象結構,你可以直接去改data的值控制顯示的樣式~
我貼下全部的代碼:
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;