最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Vue3 Teleport 的實踐及原理

 更新時間:2020年12月02日 10:46:35   作者:Shenfq  
這篇文章主要介紹了Vue3 Teleport 組件的實踐及原理,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

Vue3 的組合式 API 以及基于 Proxy 響應(yīng)式原理已經(jīng)有很多文章介紹過了,除了這些比較亮眼的更新,Vue3 還新增了一個內(nèi)置組件: Teleport 。這個組件的作用主要用來將模板內(nèi)的 DOM 元素移動到其他位置。

使用場景

業(yè)務(wù)開發(fā)的過程中,我們經(jīng)常會封裝一些常用的組件,例如 Modal 組件。相信大家在使用 Modal 組件的過程中,經(jīng)常會遇到一個問題,那就是 Modal 的定位問題。

話不多說,我們先寫一個簡單的 Modal 組件。

<!-- Modal.vue -->
<style lang="scss">
.modal {
 &__mask {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0, 0, 0, 0.5);
 }
 &__main {
  margin: 0 auto;
  margin-bottom: 5%;
  margin-top: 20%;
  width: 500px;
  background: #fff;
  border-radius: 8px;
 }
 /* 省略部分樣式 */
}
</style>
<template>
 <div class="modal__mask">
  <div class="modal__main">
   <div class="modal__header">
    <h3 class="modal__title">彈窗標題</h3>
    <span class="modal__close">x</span>
   </div>
   <div class="modal__content">
    彈窗文本內(nèi)容
   </div>
   <div class="modal__footer">
    <button>取消</button>
    <button>確認</button>
   </div>
  </div>
 </div>
</template>

<script>
export default {
 setup() {
  return {};
 },
};
</script>

然后我們在頁面中引入 Modal 組件。

<!-- App.vue -->
<style lang="scss">
.container {
 height: 80vh;
 margin: 50px;
 overflow: hidden;
}
</style>
<template>
 <div class="container">
  <Modal />
 </div>
</template>

<script>
export default {
 components: {
  Modal,
 },
 setup() {
  return {};
 }
};
</script>

如上圖所示, div.container 下彈窗組件正常展示。使用 fixed 進行布局的元素,在一般情況下會相對于屏幕視窗來進行定位,但是如果父元素的 transform , perspectivefilter 屬性不為 none 時, fixed 元素就會相對于父元素來進行定位。

我們只需要把 .container 類的 transform 稍作修改,彈窗組件的定位就會錯亂。

<style lang="scss">
.container {
 height: 80vh;
 margin: 50px;
 overflow: hidden;
 transform: translateZ(0);
}
</style>

這個時候,使用 Teleport 組件就能解決這個問題了。

Teleport 提供了一種干凈的方法,允許我們控制在 DOM 中哪個父節(jié)點下呈現(xiàn) HTML,而不必求助于全局狀態(tài)或?qū)⑵洳鸱譃閮蓚€組件。 -- Vue 官方文檔

我們只需要將彈窗內(nèi)容放入 Teleport 內(nèi),并設(shè)置 to 屬性為 body ,表示彈窗組件每次渲染都會做為 body 的子級,這樣之前的問題就能得到解決。

<template>
 <teleport to="body">
  <div class="modal__mask">
   <div class="modal__main">
    ...
   </div>
  </div>
 </teleport>
</template>

可以在 https://codesandbox.io/embed/vue-modal-h5g8y 查看代碼。

源碼解析

我們可以先寫一個簡單的模板,然后看看 Teleport 組件經(jīng)過模板編譯后,生成的代碼。

Vue.createApp({
 template: `
  <Teleport to="body">
   <div> teleport to body </div> 
  </Teleport>
 `
})

簡化后代碼:

function render(_ctx, _cache) {
 with (_ctx) {
  const { createVNode, openBlock, createBlock, Teleport } = Vue
  return (openBlock(), createBlock(Teleport, { to: "body" }, [
   createVNode("div", null, " teleport to body ", -1 /* HOISTED */)
  ]))
 }
}

可以看到 Teleport 組件通過 createBlock 進行創(chuàng)建。

// packages/runtime-core/src/renderer.ts
export function createBlock(
  type, props, children, patchFlag
) {
 const vnode = createVNode(
  type,
  props,
  children,
  patchFlag
 )
 // ... 省略部分邏輯
 return vnode
}

export function createVNode(
 type, props, children, patchFlag
) {
 // class & style normalization.
 if (props) {
  // ...
 }

 // encode the vnode type information into a bitmap
 const shapeFlag = isString(type)
  ? ShapeFlags.ELEMENT
  : __FEATURE_SUSPENSE__ && isSuspense(type)
   ? ShapeFlags.SUSPENSE
   : isTeleport(type)
    ? ShapeFlags.TELEPORT
    : isObject(type)
     ? ShapeFlags.STATEFUL_COMPONENT
     : isFunction(type)
      ? ShapeFlags.FUNCTIONAL_COMPONENT
      : 0

 const vnode: VNode = {
  type,
  props,
  shapeFlag,
  patchFlag,
  key: props && normalizeKey(props),
  ref: props && normalizeRef(props),
 }

 return vnode
}

// packages/runtime-core/src/components/Teleport.ts
export const isTeleport = type => type.__isTeleport
export const Teleport = {
 __isTeleport: true,
 process() {}
}

傳入 createBlock 的第一個參數(shù)為 Teleport ,最后得到的 vnode 中會有一個 shapeFlag 屬性,該屬性用來表示 vnode 的類型。 isTeleport(type) 得到的結(jié)果為 true ,所以 shapeFlag 屬性最后的值為 ShapeFlags.TELEPORT1 << 6 )。

// packages/shared/src/shapeFlags.ts
export const enum ShapeFlags {
 ELEMENT = 1,
 FUNCTIONAL_COMPONENT = 1 << 1,
 STATEFUL_COMPONENT = 1 << 2,
 TEXT_CHILDREN = 1 << 3,
 ARRAY_CHILDREN = 1 << 4,
 SLOTS_CHILDREN = 1 << 5,
 TELEPORT = 1 << 6,
 SUSPENSE = 1 << 7,
 COMPONENT_SHOULD_KEEP_ALIVE = 1 << 8,
 COMPONENT_KEPT_ALIVE = 1 << 9
}

在組件的 render 節(jié)點,會依據(jù) typeshapeFlag 走不同的邏輯。

// packages/runtime-core/src/renderer.ts
const render = (vnode, container) => {
 if (vnode == null) {
  // 當前組件為空,則將組件銷毀
  if (container._vnode) {
   unmount(container._vnode, null, null, true)
  }
 } else {
  // 新建或者更新組件
  // container._vnode 是之前已創(chuàng)建組件的緩存
  patch(container._vnode || null, vnode, container)
 }
 container._vnode = vnode
}

// patch 是表示補丁,用于 vnode 的創(chuàng)建、更新、銷毀
const patch = (n1, n2, container) => {
 // 如果新舊節(jié)點的類型不一致,則將舊節(jié)點銷毀
 if (n1 && !isSameVNodeType(n1, n2)) {
  unmount(n1)
 }
 const { type, ref, shapeFlag } = n2
 switch (type) {
  case Text:
   // 處理文本
   break
  case Comment:
   // 處理注釋
   break
  // case ...
  default:
   if (shapeFlag & ShapeFlags.ELEMENT) {
    // 處理 DOM 元素
   } else if (shapeFlag & ShapeFlags.COMPONENT) {
    // 處理自定義組件
   } else if (shapeFlag & ShapeFlags.TELEPORT) {
    // 處理 Teleport 組件
    // 調(diào)用 Teleport.process 方法
    type.process(n1, n2, container...);
   } // else if ...
 }
}

可以看到,在處理 Teleport 時,最后會調(diào)用 Teleport.process 方法,Vue3 中很多地方都是通過 process 的方式來處理 vnode 相關(guān)邏輯的,下面我們重點看看 Teleport.process 方法做了些什么。

// packages/runtime-core/src/components/Teleport.ts
const isTeleportDisabled = props => props.disabled
export const Teleport = {
 __isTeleport: true,
 process(n1, n2, container) {
  const disabled = isTeleportDisabled(n2.props)
  const { shapeFlag, children } = n2
  if (n1 == null) {
   const target = (n2.target = querySelector(n2.prop.to))   
   const mount = (container) => {
    // compiler and vnode children normalization.
    if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
     mountChildren(children, container)
    }
   }
   if (disabled) {
    // 開關(guān)關(guān)閉,掛載到原來的位置
    mount(container)
   } else if (target) {
    // 將子節(jié)點,掛載到屬性 `to` 對應(yīng)的節(jié)點上
    mount(target)
   }
  }
  else {
   // n1不存在,更新節(jié)點即可
  }
 }
}

其實原理很簡單,就是將 Teleportchildren 掛載到屬性 to 對應(yīng)的 DOM 元素中。為了方便理解,這里只是展示了源碼的九牛一毛,省略了很多其他的操作。

總結(jié)

希望在閱讀文章的過程中,大家能夠掌握 Teleport 組件的用法,并使用到業(yè)務(wù)場景中。盡管原理十分簡單,但是我們有了 Teleport 組件,就能輕松解決彈窗元素定位不準確的問題。

到此這篇關(guān)于詳解Vue3 Teleport 的實踐及原理的文章就介紹到這了,更多相關(guān)Vue3 Teleport組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue.js管理后臺table組件封裝的方法

    vue.js管理后臺table組件封裝的方法

    table作為數(shù)據(jù)展示組件,在日常開發(fā)中經(jīng)常被用到,這篇文章主要給大家介紹了關(guān)于vue.js管理后臺table組件封裝的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2021-08-08
  • vue或react項目生產(chǎn)環(huán)境去掉console.log的操作

    vue或react項目生產(chǎn)環(huán)境去掉console.log的操作

    這篇文章主要介紹了vue或react項目生產(chǎn)環(huán)境去掉console.log的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • vue項目預覽excel表格功能(file-viewer插件)

    vue項目預覽excel表格功能(file-viewer插件)

    這篇文章主要介紹了vue項目預覽excel表格功能(file-viewer插件),本文分步驟結(jié)合實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-10-10
  • 在vue中使用echarts實現(xiàn)飛機航線水滴圖詞云圖效果

    在vue中使用echarts實現(xiàn)飛機航線水滴圖詞云圖效果

    這篇文章主要介紹了在vue中使用echarts實現(xiàn)飛機航線?水滴圖?詞云圖,通過引入中國地圖JS文件,會自動注冊地圖,文中結(jié)合示例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-08-08
  • Vue使用JSEncrypt實現(xiàn)rsa加密及掛載方法

    Vue使用JSEncrypt實現(xiàn)rsa加密及掛載方法

    這篇文章主要介紹了Vue使用JSEncrypt實現(xiàn)rsa加密及掛載方法,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-02-02
  • Vue實現(xiàn)英文字母大小寫在線轉(zhuǎn)換功能

    Vue實現(xiàn)英文字母大小寫在線轉(zhuǎn)換功能

    在Web開發(fā)中,字符串處理是常見的需求之一,特別是在國際化應(yīng)用中,對于文本的格式化處理尤為重要,本文將介紹如何使用Vue.js來構(gòu)建一個簡單的在線英文字母大小寫轉(zhuǎn)換工具,需要的朋友可以參考下
    2024-09-09
  • 基于vue2.x的電商圖片放大鏡插件的使用

    基于vue2.x的電商圖片放大鏡插件的使用

    本篇文章主要介紹了基于vue2.x的電商圖片放大鏡插件的使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • 如何使用Vue3的onMounted鉤子函數(shù)及vue3中onMounted的用法詳解

    如何使用Vue3的onMounted鉤子函數(shù)及vue3中onMounted的用法詳解

    本文詳細介紹了Vue3中的`onMounted`鉤子函數(shù)的前世今生,包括其在Vue2中的前身`mounted`鉤子,以及Vue3中使用Composition?API的`onMounted`鉤子的用法,文章涵蓋了`onMounted`的多種用法,感興趣的朋友跟隨小編一起看看吧
    2024-11-11
  • Vue+penlayers實現(xiàn)多邊形繪制及展示

    Vue+penlayers實現(xiàn)多邊形繪制及展示

    這篇文章主要為大家詳細介紹了Vue+penlayers實現(xiàn)多邊形繪制及展示,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • 簡單實現(xiàn)vue中的依賴收集與響應(yīng)的方法

    簡單實現(xiàn)vue中的依賴收集與響應(yīng)的方法

    這篇文章主要介紹了簡單實現(xiàn)vue中的依賴收集與響應(yīng)的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-02-02

最新評論

鄂伦春自治旗| 灵台县| 康乐县| 筠连县| 永和县| 皋兰县| 慈利县| 海南省| 体育| 固安县| 大埔县| 苍山县| 中卫市| 平江县| 苍梧县| 闽侯县| 阿克苏市| 和平县| 珲春市| 奉节县| 朝阳县| 崇州市| 云南省| 宣威市| 两当县| 广平县| 襄垣县| 常熟市| 渭源县| 南投市| 舟曲县| 日照市| 比如县| 承德县| 明溪县| 拉孜县| 苍南县| 报价| 衡东县| 庆云县| 南岸区|