Vue3.0(B站李南江)


參考:

  https://vue-composition-api-rfc.netlify.app/zh/#%E6%A6%82%E8%BF%B0

  https://www.yuque.com/gdnnth/vue-v3/xvrc7e

  https://www.jianshu.com/p/4725441aff5f

  https://blog.csdn.net/wanghuan1020/article/details/109362810

一、 Vue3.0六大兩點

  1.   Performance:性能比Vue2.x快1.2~2倍
  2.   Tree shaking support:按需編譯,體積比Vue2.x更小
  3.   Composition API:組合API(類似React Hooks)
  4.   Better TypeScript support:更好的 Ts 支持
  5.   Custom Renderer API:暴露了自定義渲染API
  6.   Fragment,Teleport(Protal),Suspense:更先進的組件

 

二、VUE3.0是如何變快的

  1.diff方法優化:http://vue-next-template-explorer.netlify.app/

    • Vue2 中的虛擬dom是進行全量的對比
    • Vue3 新增了靜態標記(PatchFlag)

    在與上次虛擬節點進行對比時候,只對比帶有 patch flag 的節點

    並且可以通過 flag 的信息得知當前節點要對比的具體內容

    在創建虛擬dom的時候,會根據DOM中的內容會不會發生變化,添加靜態標記

 

  2.hoistStatic 靜態提升

    • Vue2中無論元素是否參與更新,每次都會重新創建,然后再渲染
    • Vue3中對不參與更新的元素,會做靜態提升,只會被創建一次,在渲染時直接復用即可

  

  3.cacheHandlers 事件偵聽緩存

    • 默認情況下 onClick 會被視為動態綁定,所以每次都會去追蹤它的變化
    • 但是因為是同一個函數,所以沒有追蹤變化,直接緩存起來復用即可
    • 在Vue3中的diff算法中,只有存在靜態標記的節點才會進行追蹤,事件偵聽緩存本質上是去除了不必要的diff比較

  

  4.SSR渲染

    • 當有大量靜態的內容時候,這些內容會被當做純字符串推進一個Buffer里面,即使存在動態的綁定,會通過模板插值嵌入進去。這樣會比通過虛擬dom來渲染快上很多。
    • 當靜態內容達到一定量級時候,會使用_createStaticVNode方法在客戶端dom來渲染一個static node,這些靜態node,會被直接innerHtml,就不需要創建對象,然后根據對象渲染。

 

三、VUE3.0的創建

  1.VUE-CLI

1 npm install -g @vue/cli
2 vue create projectName 3 cd projectName 4 npm run serve

 

  2.Webpack

git clone https://github.com/vuejs/vue-next-webpack-preview.git projectName
cd projectName npm install npm run dev

 

  3.Vite

  Vite是Vue作者開發的一款意圖取代webpack的工具

  其實現原理是利用ES6的import會發送請求去加載文件的特性,攔截這些請求,做一些預編譯,省去webpack冗長的打包時間

// 1. 安裝Vite
npm install -g create-vite-app // 2. 創建Vue3項目
create-vite-app projectName // 3. 安裝依賴運行項目
cd projectName npm install npm run dev

 

四、Composition API

<template>
    <div>
        <p>{{ count }}</p>
        <button @click="myFun">按鈕</button>
    </div>
</template>

<script>
// ref函數只能監聽簡單類型的變化,不能監聽復雜類型的變化(對象,數組),監聽復雜類型引入並使用reactive
import { ref } from 'vue' export default { name: 'App', // setup 函數是組合api的入口函數,執行時間在beforeCreate和created之間
 setup() { // 定義了一個count變量,初始值為0
        // 該變量發生改變后,Vue會自動更新UI
        let count = ref(0) // 在組合api中,如果定義方法,不需要定義到methods,直接定義即可
        function myFun() { count.value += 1    // 修改值,count.value而不是count
 } /** * 注意點: * 在組合api中定義的變量/方法,要想在外界使用,必須通過return { xxx, xxx } 暴露出去 */
        return { count, myFun } }, } </script>

 

  1.setup:入口函數

    • 由於在執行setup函數的時候,還沒有執行 created 生命周期方法,所以在 setup 函數中,是無法使用 data 和 methods
    • 由於不能再 setup 函數中使用 data 和 methods,所以 Vue 為了避免我們的錯誤使用,它直接將 setup 函數中的 this 修改成了 undefined
    • setup 函數只能是同步的,不能是異步的,async setup() {} 錯誤使用

 

  2.ref :響應式數據(基本數據類型)

2.1. 什么是 ref?
  ref 和 reactive 一樣,也是用來實現響應式數據的方法

  由於 reactive 必須傳遞一個對象,所以導致在企業開發中,如果我們只想讓某個變量實現響應式的時候會非常麻煩,

  所以 Vue3 就給我們提供了 ref 方法,實現對簡單值的監聽
2.2. ref 本質
  ref 底層的本質其實還是 reactive,系統會自動根據我們給 ref 傳入的值將它轉換成 ref(xx) -> reactive({value: xx})
2.3. ref 注意點
  在 Vue 中使用 ref 的值不用通過 value 獲取

  在 JS 中使用 ref 的值必須通過 value 獲取

 

3.reactive:響應式數據(json/arr)

<template>
  <div>
    <p>{{time}}</p>
    <button @click="myFn">按鈕</button>
  </div>
</template>

<script>
/* reactive的用法與ref的用法相似,也是將數據變成響應式數據,當數據發生變化時UI也會自動更新。 不同的是ref用於基本數據類型,而reactive是用於復雜數據類型,比如對象和數組 */
// toRefs解構
import { reactive,toRefs } from 'vue' export default { name: 'App', setup() { // 賦值
    let state = reactive({ time: new Date(), }) function myFn() { /* reactive中傳遞的參數必須是json對象或者數組,如果傳遞了其他對象(比如new Date()),在默認情況下修改對象, 界面不會自動更新,如果也需要具有響應式,可以通過重新賦值的方式實現 */ const newTime = new Date(state.time.getTime()) newTime.setDate(newTime.getDate() + 1) state.time = newTime // state.time.setDate(state.time.getDate() + 1) ,頁面不更新
        console.log(state)    // reactive將傳遞的對象包裝成了proxy對象
 } return { ...toRefs(state), myFn, } }, } </script>

 

3.1. 什么是 reactive?

    •  reactive 是 Vue3 中提供的實現響應式數據的方法
    •  在 Vue2 中響應式數據是通過 defineProperty 來實現的,而在 Vue3 中響應式數據是通過 ES6 的 Proxy 來實現的

3.2. reactive 注意點

    •  reactive 參數必須是對象 (json/array)
    •  如果給 reactive 傳遞了其他對象
    •  默認情況下修改對象,界面不會自動更新
    •    如果想更新,可以通過重新賦值的方式

 

   4.isRef 和 isReactive :判斷一個數據是 ref 類型還是 reactive 類型

import { ref, reactive, isRef, isReactive } from 'vue' export default { name: 'App', setup() { let age = ref(18) // let age = reactive({
          // value: 18
          // })
        function myFun() { console.log(isReactive(age)) console.log(isRef(age)) age.value += 2 } return { age, myFun } } }

 

  5.只讀:readonly,shallowReadonly,isReadonly

    • readonly:用於創建一個只讀的數據,並且是遞歸只讀
    • shallowReadonly: 用於創建一個只讀數據,但是不是遞歸只讀的
    • isReadonly:對於 readonly 和 shallowReadonly 創建的數據,返回結果均為 true
    • const 和 readonly 的區別:

      const: 賦值保護,不能給變量重新賦值

      readonly:屬性保護,不能給屬性重新賦值

 

import { readonly, isReadonly, shallowReadonly } from 'vue' export default { name: 'App', setup() { // 用於創建一個只讀的數據,並且是遞歸只讀
    let state = readonly({ name: 'lnj', attr: { age: 18, height: 1.88, }, }) function myFn() { state.name = '驚蟄' state.attr.age = 666 state.attr.height = 1.66 console.log(state) console.log(isReadonly(state)) } return { state, myFn, } }, }

 

  6.shallowRef和shallowReactive:非遞歸監聽

遞歸監聽
  默認情況下,無論是通過 ref 還是 reactive 都是遞歸監聽

  每一層都包裝成了一個 proxy 對象

  遞歸監聽存在的問題

  如果數據量比較大,非常消耗性能

非遞歸監聽
  shallowReactive
  非遞歸監聽下,第一層被包裝成了 proxy
  這意味着:只有第一層的數據發生改變,才會觸發 UI界面 的更新


  shallowRef
  如果是通過 shallowRef 創建數據,那么 Vue監聽的是 .value 的變化,並不是第一層的變化
  如果想在修改其內部數據后觸發界面的更新,可以調用 triggerRef 方法


  應用場景
  一般情況下 使用 ref 和 reactive 即可
  只有在需要監聽的數據量比較大的時候,我們才使用 shallowRef / shallowReactive

<template>
  <div>
    <p>{{ state.a }}</p>
    <p>{{ state.gf.b }}</p>
    <p>{{ state.gf.f.c }}</p>
    <p>{{ state.gf.f.s.d }}</p>
    <button @click="myFun">按鈕</button>
  </div>
</template>

<script> import { ref, shallowRef, triggerRef } from 'vue' export default { name: 'App', setup() { // shallowRef 本質上還是 shallowReative
      // shallowRef(10) -> shallowReactive({ value: 10 })
      // 所以如果是通過 shallowRef 創建的數據,它監聽的是 .value 的變化
      let state = shallowRef({ a: 'a', gf: { b: 'b', f: { c: 'c', s: { d: 'd' } } } }) function myFun() { /** * triggerRef * 注意點: * + Vue3 只提供了 triggerRef 方法,沒有提供 triggerReactive 方法 * + 所以如果是 reactive 類型的數據,那么是無法主動觸發界面更新的 */
        // state.value.a = 1
        // state.value.gf.b = 2
        state.value.gf.f.c = 3 state.value.gf.f.s.d = 4 // 如果想在修改該數據時,觸發界面的更新,可以調用 triggerRef 方法主動觸發
 triggerRef(state) /** * shallowRef * 注意點: * + 如果是通過 shallowRef 創建數據,那么 Vue監聽的是 .value 的變化,因為底層本質上.value才是第一層 */
        // state.value = {
        // a: '1',
        // gf: {
        // b: '2',
        // f: {
        // c: '3',
        // s: {
        // d: '4'
        // }
        // }
        // }
        // }
 console.log(state) console.log(state.value.gf) console.log(state.value.gf.f) console.log(state.value.gf.f.s) } return { state, myFun } } } </script>

 

  7.toRef & toRefs、toRaw & markRaw

    • ref->復制,將原始數據轉化為響應式,修改響應式數據不會影響原始數據(將原始數據深拷貝);數據發生改變,界面就會自動更新
    • toRef->引用,將原始數據轉化為響應式,修改響應式數據會影響以前的數據(將原始數據淺拷貝);數據發生改變,界面也不會自動更新
    • toRaw->toRaw(state.value),拿到響應式數據的原始數據,數據發生改變,界面也不會自動更新
    • markRaw->被markRaw標記的原始數據,不會被追蹤變為響應式
    • toRefs->解構 

  8.customRef函數

<template>
  <div>
    <p>{{age}}</p>
    <button @click="myFun">按鈕</button>
  </div>
</template>

<script>
  /** * custemRef返回一個 ref 對象,可以顯式的控制依賴追蹤和觸發響應 */ import { ref, customRef } from 'vue'
  function myRef(value) { return customRef((track, trigger) => { // track -> 追蹤 trigger -> 觸發
    return { get() { track() // 告訴 Vue 這個數據是需要追蹤變化的
        console.log('get', value) return value }, set(newValue) { console.log('set', newValue) value = newValue trigger() // 告訴 Vue 觸發界面更新
 } } }) } export default { name: 'App', setup() { // let age = ref(18) // reactive({value: 18})
      let age = myRef(18) function myFun() { age.value += 1 } return { age, myFun } } } </script>

 


免責聲明!

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



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