<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [vue3] vue3 setup函數

      從語法上看,Composition API 提供了一個 setup 啟動函數作為邏輯組織的入口,提供了響應式 API,提供了生命周期函數以及依賴注入的接口,通過調用函數來聲明一個組件。

      Options API

      • 選項式 API 在 props、data、methods、computed 等選項中定義變量;
      • 在組件初始化階段,Vue.js 內部處理這些 options,把定義的變量添加到組件實例上;
      • 等模板編譯成 render 函數的時候,內部通過 with(this){} 的語法去訪問在組件實例中的變量。

      在 Vue3 中,這兩種 API 能夠同時使用,但執行的優先級不同,建議只使用其中一種。

      • Options API 適合小型簡單的組件;
      • Composition API 適合大型復雜、需要拆分邏輯的組件。

      組件初始化

      在 Vue3 中,render函數可以訪問到 setup 函數返回的數據,這是怎么實現的呢?

      組件的渲染流程是:創建vnode、渲染vnode、生成DOM。

      其中渲染vnode就是在掛載(或更新)組件,通過 patch 函數對不同類型的 vnode 進行掛載或更新。

      setup 函數只在首次掛載的流程中調用,因此這里主要研究掛載的流程。

      通過 patch 函數內部的調用鏈通過 mountComponent 函數進行組件掛載。

      mountComponent

      const mountComponent = (
      	initialVNode,
          container,
          anchor,
          parentComponent,
          parentSuspense,
          namespace: ElementNamespace,
          optimized,
      ) => {
          // 創建組件實例
          const instance: ComponentInternalInstance = 
                (initialVNode.component = createComponentInstance(
                    initialVNode,
                    parentComponent,
                    parentSuspense,
                ))
          // 設置組件實例:props, slots ...
          setupComponent(instance)
          
          // 設置并運行帶副作用的渲染函數
          setupRenderEffect(
              instance,
              initialVNode,
              container,
              anchor,
              parentSuspense,
              namespace,
              optimized,
          )
      }
      

      mountComponent 函數內部主要執行了三個函數:

      • createComponentInstance:【工廠模式】內部通過對象字面量創建一個組件實例對象并返回,對象包含許多屬性,例如:
        • effect,update,job:與副作用和更新邏輯相關;
        • components、directives:局部組件與局部指令;
        • ctx、data、props:state相關;
        • bc、c、bm、m、bu:聲明周期相關,源代碼中用首字母命名,bc 是 beforeCreate;
      • setupComponent:
        1. 判斷組件是否有狀態;
        2. 初始化props
        3. 初始化slots
        4. 如果有狀態,則調用 setupStatefulComponent 進行組件實例設置,內部調用了 setup 函數
      • setupRenderEffect:創建一個與更新相關的副作用,再包裝成 Job 對象。這個副作用內部會調用生命周期 hook 。

      這篇文章主要介紹setup,下面主要內容是執行了setup函數的 setupStatefulComponent 函數。

      setupStatefulComponent

      創建代理

      這個函數創建了渲染上下文代理,創建代理的目的是讓訪問數據更加簡便。

      例如在 Vue2 中 props 的數據實際存儲在 this._props 上,而 data 的數據則存儲在 this._data 上,在組件方法中可以通過 this.msg 訪問到 this._data.msg ,就是因為使用了代理。

      而在 Vue3 中,不同的狀態被存儲在了組件實例的 setupState、ctx、data、props中。通過創建一個代理,渲染函數可以在一個對象上進行讀寫操作,再由代理將讀寫操作分發給不同的狀態對象。

      // 0. create render proxy property access cache
      instance.accessCache = Object.create(null)
      // 1. create public instance / render proxy
      instance.proxy = new Proxy(instance.ctx, PublicInstanceProxyHandlers)
      

      函數內部還創建了一個 accessCache 對象,它是一個 key 到 state類型 的映射,避免每次讀取一個 key 都要去判斷這個 key 屬于哪一種狀態。

      PublicInstanceProxyHandlers 內部關于 accessCache 的快速命中代碼:

      const n = accessCache![key]
      if (n !== undefined) {
          switch (n) {
              case AccessTypes.SETUP:
                  return setupState[key]
              case AccessTypes.DATA:
                  return data[key]
              case AccessTypes.CONTEXT:
                  return ctx[key]
              case AccessTypes.PROPS:
                  return props![key]
                  // default: just fallthrough
          }
      }
      

      如果沒能命中緩存,內部只能通過 hasOwn 方法一個一個去判斷狀態對象上是否存在查詢的 key。hasOwn 是這一過程中的開銷大頭。

      判斷的順序很重要,當不同的狀態對象有著相同名稱的屬性,那么優先應用那個先判斷的類型。

      get攔截(在沒有命中緩存的情況下)的判斷順序是 setup、data、props、context。

      這意味著當我們混用 setup函數 和 選項式 API 時,同名響應式變量會命中 setup 中聲明的變量。

      下面的代碼會在界面上顯示“from setup”。

      <template>
        <p>{{ msg }}</p>
      </template>
      
      <script>
      import { ref } from 'vue';
      export default{
        data() {
          return {
            msg: 'from data'
          }
        },
        setup(){
          const msg = ref('from setup');
          return {
            msg
          }
        }
      }
      </script>
      

      上面說的都是對get的攔截,對于set的攔截簡要介紹如下:

      • key 的判斷順序和 get 一樣;
      • 在開發環境中對props的修改操作進行警告。
      調用setup

      setupStatefulComponent 函數在創建了這個上下文代理之后,就調用了 setup 函數

      大致流程如下:

      1. 判斷是否有 setup 函數;

      2. 如果setup函數參數列表長度大于1,則調用 createSetupContext 函數創建 setup 上下文對象;

        setup函數的參數如下,第二個參數是一個上下文對象。如果用戶(前端程序員)編寫setup的時候使用了第二個參數,那么Vue在執行setup函數之前就要把這個上下文對象準備好。

        setup(props, { attrs, slots, emit, expose }) {
            ...
        }
        
      3. 執行 setup 函數獲取返回的結果;

        執行 setup 函數是通過 callWithErrorHandling 間接調用的。其實內部不復雜,有參數則攜帶參數執行,用 try/catch 捕獲錯誤。

        export function callWithErrorHandling(
          fn: Function,
          instance: ComponentInternalInstance | null | undefined,
          type: ErrorTypes,
          args?: unknown[],
        ): any {
          try {
            return args ? fn(...args) : fn()
          } catch (err) {
            handleError(err, instance, type)
          }
        }
        
      4. 處理 setup 返回的結果。

        setup 函數的返回值有兩種類型:數據對象 和 渲染函數。

        • 如果是渲染函數,則綁定到 instance.render 上;

          instance.render = setupResult as InternalRenderFunction
          
        • 如果是數據對象,則先進行響應式包裝,再綁定到 instance.setupState 上。

          instance.setupState = proxyRefs(setupResult)
          

      至此,setup函數執行完成了,相關的數據也都綁定到了組件實例上。

      posted @ 2024-08-25 16:56  feixianxing  閱讀(375)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲熟妇自偷自拍另欧美| 国产第一页浮力影院入口| 亚洲国产欧美日韩另类| 日韩有码中文在线观看| 久久99日韩国产精品久久99| 国产va免费精品观看| 久9视频这里只有精品| 精品国产成人国产在线观看| 精品日本免费一区二区三区| 麻豆精品久久久久久久99蜜桃| 国产在线午夜不卡精品影院| 色呦呦九九七七国产精品| 国产精品人妻熟女男人的天堂| 蜜臀av一区二区三区日韩| 男女性高爱潮免费网站| 久久精品国产亚洲av麻| 丰满少妇被猛烈进出69影院| 东方四虎av在线观看| 116美女极品a级毛片| 欧洲精品码一区二区三区| 国产18禁黄网站禁片免费视频 | 国产精品538一区二区在线| 亚洲国产美女精品久久久| 亚洲精品有码在线观看| 九九成人免费视频| 在线精品视频一区二区三四 | 亚洲国产成人AⅤ毛片奶水| 亚洲综合网国产精品一区| 久久亚洲人成网站| 农村老熟女一区二区三区| 中文字幕在线精品国产| 久热综合在线亚洲精品| 亚洲av成人网在线观看| 国产区成人精品视频| 强奷乱码中文字幕| 周至县| 亚洲综合色网一区二区三区| 国产精品区一区第一页| 婷婷六月综合缴情在线| 亚洲人成绝网站色www| 成人乱人伦精品小说|