第十三節:Vue3高級之 render/h函數、jsx、自定義指令、teleport、插件


一. render/h函數(了解)

 詳見:https://v3.cn.vuejs.org/guide/render-function.html#dom-樹

 

 

二. jsx(了解)

  Vue3.x版本創建的項目使用jsx已經不需要配置babel了。

 代碼分享:

<script>
  import HelloWorld from './HelloWorld.vue';
  export default {
    data() {
      return {
        counter: 0
      }
    },
    render() {
      const increment = () => this.counter++;
      const decrement = () => this.counter--;
      return (
        <div>
          <h2>當前計數: {this.counter}</h2>
          <button onClick={increment}>+1</button>
          <button onClick={decrement}>-1</button>
          <HelloWorld>
          </HelloWorld>
        </div>
      )
    }
  }
</script>
View Code

 組件代碼:

<script>
  export default {
    render() {
      return (
        <div>
          <h2>HelloWorld</h2>
          {this.$slots.default ? this.$slots.default(): <span>哈哈哈</span>}
        </div>
      )
    }
  }
</script>
View Code

 

三. 自定義指令

(https://v3.cn.vuejs.org/guide/custom-directive.html#簡介)

1. 說明

(1). 在Vue的模板語法中我們學習過各種各樣的指令:v-show、v-for、v-model等等,除了使用這些指令之外,Vue也允許我們來自定義自己的指令(directive)。

 注意:在Vue中,代碼的復用和抽象主要還是通過組件

 通常在某些情況下,你需要對DOM元素進行底層操作,這個時候就會用到自定義指令

(2). 自定義指令分為兩種:

 局部指令:組件中通過 directives 選項,只能在當前組件中使用;

 全局指令:app的 directive 方法,可以在任意組件中被使用;

補充1個例子:input標簽自動聚焦,原始寫法。

<template>
    <div>
        <input type="text" ref="myInput">
    </div>
</template>

<script>
    import { ref, onMounted } from 'vue';

    export default {
        setup() {
            var myInput = ref(null);
            
            // 掛載完成后
            onMounted(()=>{
                myInput.value.focus();
            })

            return {
                myInput
            }
        }
    }
</script>
View Code

(3). 指令的生命周期

import { createApp } from 'vue'
const app = createApp({})

// 注冊
app.directive('my-directive', {
  // 指令是具有一組生命周期的鈎子:
  // 在綁定元素的 attribute 或事件監聽器被應用之前調用
  created() {},
  // 在綁定元素的父組件掛載之前調用
  beforeMount() {},
  // 綁定元素的父組件被掛載時調用
  mounted() {},
  // 在包含組件的 VNode 更新之前調用
  beforeUpdate() {},
  // 在包含組件的 VNode 及其子組件的 VNode 更新之后調用
  updated() {},
  // 在綁定元素的父組件卸載之前調用
  beforeUnmount() {},
  // 卸載綁定元素的父組件時調用
  unmounted() {}
})
View Code

(4). 生命周期鈎子函數傳遞的參數

directives: {
            focus: {
                mounted(el, bindings, vnode, preVnode) {
                    el.focus();
                }
            }
}

A. el

 指令綁定到的元素。這可用於直接操作 DOM。

B. bindings

C. vnode

 上面作為 el 參數收到的真實 DOM 元素的藍圖

D. preVnode

 上一個虛擬節點,僅在 beforeUpdate 和 updated 鈎子中可用。

2. 局部指令

自定義一個 v-focus 的局部指令

 (1). 這個自定義指令實現非常簡單,我們只需要在組件選項中使用 directives 即可;它是一個對象,在對象中編寫我們自定義指令的名稱注意:這里不需要加v-);

 (2). 自定義指令有一個生命周期,是在組件掛載后調用的 mounted,我們可以在其中完成操作;

代碼分享:

<template>
    <div>
        <input type="text" v-focus>
    </div>
</template>

<script>
    export default {
        // 局部指令
        directives: {
            focus: {
                mounted(el, bindings, vnode, preVnode) {
                    el.focus();
                }
            }
        },
    }
</script>

3. 全局指令 

  一個全局的v-focus指令可以讓我們在任何地方直接使用,在main.js中編寫。

var app =createApp(App);

// 全局自定義指令
app.directive('focus',{
    mounted(el) {
        el.focus();
    }
})

app.mount('#app')

4. 指令參數、修飾符

 通過 bindings 獲取到對應的內容

<template>
    <div>
        <button v-if="counter < 2" v-ypf.aaaa.bbbb="'hello lmr'" @click="increment">當前計數: {{counter}}</button>
    </div>
</template>

<script>
    import { ref } from "vue";

    export default {
        // 局部指令
        directives: {
            ypf: {
                created(el, bindings, vnode, preVnode) {
                    console.log("ypf created", el, bindings, vnode, preVnode);
                    console.log(bindings.value);
                    console.log(bindings.modifiers);
                },
            }
        },
        setup() {
            const counter = ref(0);
            const increment = () => counter.value++;
            return {
                counter,
                increment
            }
        }
    }
</script>
View Code

5. 案例-時間格式化指令

(1). 說明

(2). 實操

 需要安裝dayjs包

import dayjs from 'dayjs';

export default function(app) {
  app.directive("format-time", {
    created(el, bindings) {
      bindings.formatString = "YYYY-MM-DD HH:mm:ss";
      if (bindings.value) {
        bindings.formatString = bindings.value;
      }
    },
    mounted(el, bindings) {
      const textContent = el.textContent;
      let timestamp = parseInt(textContent);
      if (textContent.length === 10) {
        timestamp = timestamp * 1000
      }
      el.textContent = dayjs(timestamp).format(bindings.formatString);
    }
  })
}
View Code

 

四. 內置組件teleport

 

參考官網:https://v3.cn.vuejs.org/guide/teleport.html#與-vue-components-一起使用 

 

 

五. 插件

1. 說明

(1). 通常我們向Vue全局添加一些功能時,會采用插件的模式,它有兩種編寫方式:

 對象類型:一個對象,但是必須包含一個 install 的函數,該函數會在安裝插件時執行;

 函數類型一個function,這個函數會在安裝插件時自動執行;

(2). 插件可以完成的功能沒有限制,比如下面的幾種都是可以的:

 A. 添加全局方法或者 property,通過把它們添加到 config.globalProperties 上實現;

 B. 添加全局資源指令/過濾器/過渡等;

 C. 通過全局 mixin 來添加一些組件選項;

 D. 一個庫,提供自己的 API,同時提供上面提到的一個或多個功能

2. 實戰

(1). 插件代碼

plugins_function.js

// 函數形式
export default function(app) {
  console.log(app);
}

plugins_object.js

// 對象形式
export default {
    name: 'test1',
    install(app) {
        app.config.globalProperties.$name = "ypf"
    }
}

(2). 使用

import { createApp } from 'vue'

var app =createApp(App);
// 插件的調用
import pluginsfunction from './components/05_插件/plugins_function.js';
import pluginsobject from './components/05_插件/plugins_object.js';
app.use(pluginsfunction);
app.use(pluginsobject);

app.mount('#app')

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鵬飛)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 聲     明1 : 如有錯誤,歡迎討論,請勿謾罵^_^。
  • 聲     明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM