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

Vue 技巧之控制父類的 slot

 更新時間:2020年02月24日 08:52:39   作者:前端小智  
插槽(Slot)是Vue提出來的一個概念,正如名字一樣,插槽用于決定將所攜帶的內(nèi)容,插入到指定的某個位置,從而使模板分塊,具有模塊化的特質(zhì)和更大的重用性。

首先來思考一個問題:是否有一種方法可以從子組件填充父組件的插槽?

最近一位同事問我這個問題,答案很簡單:可以的。但我的解決方案可能和你想的完全不一樣,這是涉及一個棘手的Vue架構(gòu)問題,但也是一個非常有趣的問題。

為什么會有這個問題

在我們的應用程序中,我們有一個頂部欄,其中包含不同的按鈕、搜索欄和其他一些控件。根據(jù)每個人所在的頁面,它可能略有不同,因此我們需要一種基于每個頁面配置它的方法。

為此,我們希望每個頁面都能夠配置操作欄。看起來很簡單,但這里有個問題

這個頂部欄(我們稱之為ActionBar)實際上是我們的主布局的一部分,結(jié)構(gòu)如下:

<template>
 <div>
  <FullPageError />
  <ActionBar />
  <App />
 </div>
</template>

根據(jù)你所在的頁面/路線動態(tài)注入App的位置。

我們可以使用ActionBar上的一些插槽來配置它。 但是,我們?nèi)绾螐?code>App組件中控制這些插槽?

定義問題

首先,最好是盡可能清楚地知道我們要解決的問題。

我們來看一個具有一個子組件和一個插槽的組件:

// Parent.vue
<template>
 <div>
  <Child />
  <slot />
 </div>
</template>

我們可以這樣填充Parent的插槽:

// App.vue
<template>
 <Parent>
  <p>This content goes into the slot</p>
 </Parent>
</template>

這里沒什么特別的。。。

填充子組件的插槽很容易,這也是使用插槽的最常見方式。

但是,有沒有一種方法可以控制從Child組件內(nèi)部進入Parent組件slot的內(nèi)容呢?

換種說法:我們可以讓子組件填充父組件的插槽嗎?來看看我想到的第一個解決方案。

向下使用 props,向上使用 event

數(shù)據(jù)流經(jīng)組件樹的唯一途徑是使用props。 而向上通信的方法是使用事件。這意味著,如果要讓子組件與父組件進行通信,我們需要使用事件來實現(xiàn)。

因此,我們將使用事件來將內(nèi)容傳遞到ActionBars槽中

import SlotContent from './SlotContent';

export default {
 name: 'Application',
 created() {
  // As soon as this component is created we'll emit our events
  this.$emit('slot-content', SlotContent);
 }
};

我們將要放入插槽中的所有內(nèi)容打包到SlotContent組件中。 一旦創(chuàng)建了應用程序組件,我們就會發(fā)出slot-content事件,并傳遞我們要使用的組件。

我們的組件結(jié)構(gòu)如下:

<template>
 <div>
  <FullPageError />
  <ActionBar>
   <Component :is="slotContent" />
  </ActionBar>
  <App @slot-content="component => slotContent = component" />
 </div>
</template>

監(jiān)聽該事件,并將slotContent設置為我們的App組件發(fā)送給我們的任何內(nèi)容。 然后,使用內(nèi)置的Component,就可以動態(tài)地渲染該組件。

但是,通過事件傳遞組件感覺很奇怪,并非是主流的做法。幸運的是,還有一種方法可以完全避免使用事件。

使用 $options

由于Vue組件只是 JS 對象,因此我們可以向它們添加所需的任何屬性。無需使用事件傳遞插槽內(nèi)容,我們只需將其作為字段添加到組件中即可:

 // App.vue
import SlotContent from './SlotContent';

export default {
 name: 'Application',
 slotContent: SlotContent,
 props: { /***/ },
 computed: { /***/ },
};

在主頁中通過 App.slotContent 獲取對應的組件

<template>
 <div>
  <FullPageError />
  <ActionBar>
   <Component :is="slotContent" />
  </ActionBar>
  <App />
 </div>
</template>

import App from './App';
import FullPageError from './FullPageError';
import ActionBar from './ActionBar';

export default {
 name: 'Scaffold',
 components: {
  App,
  FullPageError,
  ActionBar,
 }
 data() {
  return {
   slotContent: App.slotContent,
  }
 },
};

這更像是靜態(tài)配置,更美觀、更簡潔,但這仍然是不對的。

理想情況下,我們不會在代碼中混合使用范式,所有操作應該都是以聲明方式完成。

但是在這里,我們沒有將我們的組件組合在一起,而是將它們作為 JS 對象傳遞。如果我們能以正常的Vue方式把我們想要的寫在插槽里就好了。

考慮 Portal(傳送門)

Vue 中的 Portal 技術(shù) 在 Vue 項目中,我們使用模板來聲明 dom

嵌套關系,然而有時候一些組件需要脫離固定的層級關系,不再受制與層疊上下文,比如說 Modal 和 Dialog
這種組件就希望能夠脫離當前模板所在的層疊上下文。

在 Vue 中有兩種方式來實現(xiàn)這種效果,一種是使用指令,操作真實 dom,使用熟知的 dom 操作方法將指令所在的元素 append
到另外一個 dom 節(jié)點上去。另一種方式就是定義一套組件,將組件內(nèi)的 vnode 轉(zhuǎn)移到另外一個組件中去,然后各自渲染。

它們的工作方式和你想象的完全一樣。你可以把任何東西從一個地方傳送到另一個地方。在我們的例子中,我們將元素從DOM中的一個位置“傳送”到另一個位置。

無論組件樹如何顯示,我們都可以控制組件在DOM中的顯示位置。

例如,假設我們想要填充一個modal。但是我們的modal必須在根頁面處渲染,這樣我們才能正確地覆蓋它。首先,我們要在modal中指定我們想要的:

<template>
 <div>
  <!-- Other components -->
  <Portal to="modal">
   Rendered in the modal.
  </Portal>
 </div>
</template>

然后,在我們的modal組件中,我們將擁有另一個將內(nèi)容渲染出來的 portal:

<template>
 <div>
  <h1>Modal</h1>
  <Portal from="modal" />
 </div>
</template>

這是一項改進,因為現(xiàn)在我們實際上是在編寫HTML,而不僅僅是傳遞對象。 它更具聲明性,更容易查看應用程序中發(fā)生的事情。

由于 portal 在背后執(zhí)行一些操作以在不同位置渲染元素,因此它完全打破了DOM渲染在Vue中工作方式的模型。 看起來您正在正常渲染元素,但根本無法正常工作,這可能會引起很多混亂和沮喪。

還有一個很大的問題,稍后我們會講到。

提升狀態(tài)

“提升狀態(tài)”是指將狀態(tài)從子組件移動到父組件或祖父組件,將它向上移動到組件樹中。

這可能對應用程序的體系結(jié)構(gòu)產(chǎn)生較大的影響。對于我們的目的,這會是更簡單的解決方案。

這里的“狀態(tài)”是我們試圖傳遞到ActionBar組件插槽中的內(nèi)容。但是該狀態(tài)包含在Page組件中,我們不能真正將 page 特定的邏輯移到layout組件中。 我們的狀態(tài)必須保留在我們正在動態(tài)渲染的Page組件內(nèi)。

因此,我們必須提升整個Page組件才能提升狀態(tài)。當前,我們的Page組件是Layout組件的子組件:

<template>
 <div>
  <FullPageError />
  <ActionBar />
  <Page />
 </div>
</template>

解除它需要我們將其翻轉(zhuǎn),并使Layout組件成為Page組件的子組件。 我們的Page組件看起來像這樣:

<template>
 <Layout>
  <!-- Page-specific content -->
 </Layout>
</template>

現(xiàn)在,我們的Layout組件將看起來像這樣,我們可以在其中使用插槽插入頁面內(nèi)容:

<template>
 <div>
  <FullPageError />
  <ActionBar />
  <slot />
 </div>
</template>

但這還不能讓我們自定義任何內(nèi)容。 我們必須在Layout組件中添加一些命名的插槽,以便我們可以傳遞應放置在ActionBar中的內(nèi)容。

最簡單的方法是使用一個插槽來完全替代ActionBar組件:

<template>
 <div>
  <FullPageError />
  <slot name="actionbar">
   <ActionBar />
  </slot>
  <slot />
 </div>
</template>

這樣,如果你不指定“actionbar”插槽,默認使用ActionBar組件。 但我們可以使用自己的自定義ActionBar配置覆蓋此插槽:

<template>
 <Layout>
  <template #actionbar>
   <ActionBar>
    <!-- Custom content that goes into the action bar -->
   </ActionBar>
  </template>
  <!-- Page-specific content -->
 </Layout>
</template>

對我來說,這是一種理想的處理方式,但是它確實需要我們重構(gòu)頁面的布局方式。 對于界面復雜點的,這可能是一項艱巨的任務。

簡化一下

當我們第一次定義問題時:

我們可以讓子組件填充父組件的插槽嗎?

但實際上,這個問題與props沒有任何關系。 更簡單地說,它是關于使子組件控制在其自己的子樹之外渲染的內(nèi)容。

我們可以這樣表述問題

組件控制在其子組件之外渲染的內(nèi)容的最佳方法是什么?

通過這個鏡頭檢查我們提出的每個解決方案,都會為我們提供一個有趣的新視角。

向父組件發(fā)出事件

數(shù)據(jù)流經(jīng)組件樹的唯一途徑是使用 props。 而向上通信的方法是使用事件。這意味著,如果要讓子組件與父組件進行通信,我們需要使用事件來實現(xiàn)。

靜態(tài)配置

只是將必要的信息提供給其他組件,而不是主動地要求另一個組件做事情。

傳送門

組件無法控制其子樹之外的內(nèi)容。這里的每個方法都是讓另一個組件執(zhí)行我們的命令并控制我們真正感興趣的元素不同的方式。

在這方面,使用 portal 更好的原因是它們允許我們將所有這些通信邏輯封裝到單獨的組件中。

提升狀態(tài)

提升狀態(tài)是一種比我們前面看到的3種更簡單、更強大的技術(shù),這里我們的主要限制是我們想要控制的內(nèi)容在子組件之外。

最簡單的解決方法是:

提升狀態(tài)以及操縱該狀態(tài)的邏輯,使我們可以擁有更大范圍的組件,并將目標元素包含在該組件中。如果可以這樣做,這是解決此特定問題以及所有相關問題的最簡單方法。

請記住,這并不一定意味著要提升整個組件。 你也可以重構(gòu)你的應用程序,以將邏輯移到組件樹中更高的組件中。

依賴注入

如果熟悉軟件工程設計模式的人可能已經(jīng)注意到,我們在這里所做的是依賴注入,這是我們在軟件工程中已經(jīng)使用了幾十年的技術(shù)。

它的用途之一是編寫易于配置的代碼。在我們的例子中,,我們在使用的每個Page中以不同的方式配置Layout組件。

當調(diào)換PageLayout組件時,我們正在執(zhí)行所謂的控件反轉(zhuǎn)。

在基于組件的框架中,父組件控制子組件的操作,因此我們選擇讓Page來控制Layout組件,而不是由Layout組件控制Page。

為了做到這一點,我們使用插槽為Layout組件提供完成任務所需的內(nèi)容。

正如我們所看到的,使用依賴注入可以使我們的代碼更加模塊化和易于配置。

總結(jié)

我們討論了解決這個問題的4種不同方法,展示了每種方法的優(yōu)缺點。然后我們更進一步,將問題轉(zhuǎn)化為一個更一般的問題,即控制組件子樹之外的內(nèi)容。

、提升狀態(tài)和依賴項注入是兩個非常有用的模式。它們是我們武器庫中最好的工具,因為它們可以應用于無數(shù)的軟件開發(fā)問題。

但最重要的是,希望你還能學會:

通過使用一些常見的軟件模式,將一個丑陋解決方案的問題轉(zhuǎn)變成一個非常優(yōu)雅的問題。許多其他的問題都可以用這種方法解決,即把一個丑陋的、復雜的問題轉(zhuǎn)化成一個更簡單、更容易解決的問題。

代碼部署后可能存在的BUG沒法實時知道,事后為了解決這些BUG,花了大量的時間進行l(wèi)og 調(diào)試,這邊順便給大家推薦一個好用的BUG監(jiān)控工具 Fundebug。

原文:https://dev.to/michaelthiesse...

以上就是Vue 技巧之控制父類的 slot的詳細內(nèi)容,更多關于Vue控制父類的 slot的資料請關注腳本之家其它相關文章!

相關文章

  • 詳解Vue底部導航欄組件

    詳解Vue底部導航欄組件

    這篇文章主要介紹了Vue底部導航欄的詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-05-05
  • Vue高級用法實例教程之動態(tài)組件

    Vue高級用法實例教程之動態(tài)組件

    讓多個組件使用同一個掛載點,并動態(tài)切換,這就是動態(tài)組件,下面這篇文章主要給大家介紹了關于Vue高級用法實例教程之動態(tài)組件的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2021-11-11
  • 基于vue的fullpage.js單頁滾動插件

    基于vue的fullpage.js單頁滾動插件

    這篇文章主要為大家詳細介紹了基于vue的fullpage.js單頁滾動插件,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • Vue出現(xiàn)彈出層時禁止底部頁面跟隨滑動

    Vue出現(xiàn)彈出層時禁止底部頁面跟隨滑動

    本文主要介紹了Vue出現(xiàn)彈出層時禁止底部頁面跟隨滑動,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07
  • Vue深入講解數(shù)據(jù)響應式原理

    Vue深入講解數(shù)據(jù)響應式原理

    應用會對用戶的操作進行反饋,就叫響應式,數(shù)據(jù)變化會實時改變UI,就叫數(shù)據(jù)響應式,修改Vue實例中的數(shù)據(jù)時,視圖會重新渲染,就是Vue的數(shù)據(jù)響應式
    2022-05-05
  • 解決vue同一slot在組件中渲染多次的問題

    解決vue同一slot在組件中渲染多次的問題

    今天小編就為大家分享一篇解決vue同一slot在組件中渲染多次的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • 一篇文章總結(jié)Vue3.2語法糖使用

    一篇文章總結(jié)Vue3.2語法糖使用

    Vue3.2(21年8月10日)相比于Vue3新增了語法糖,減少了代碼冗余,下面這篇文章主要給大家介紹了關于Vue3.2語法糖使用的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-11-11
  • 快速解決Error: error:0308010C:digital envelope routines::unsupported的三種解決方案

    快速解決Error: error:0308010C:digital envelope ro

    因為 node.js V17版本中最近發(fā)布的OpenSSL3.0, 而OpenSSL3.0對允許算法和密鑰大小增加了嚴格的限制,下面通過本文給大家分享快速解決Error: error:0308010C:digital envelope routines::unsupported的三種解決方案,感興趣的朋友一起看看吧
    2024-02-02
  • element--Diaolog彈窗打開之后渲染組件方式

    element--Diaolog彈窗打開之后渲染組件方式

    這篇文章主要介紹了element--Diaolog彈窗打開之后渲染組件方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • vue中使用gantt-elastic實現(xiàn)可拖拽甘特圖的示例代碼

    vue中使用gantt-elastic實現(xiàn)可拖拽甘特圖的示例代碼

    這篇文章主要介紹了vue中使用gantt-elastic實現(xiàn)可拖拽甘特圖,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07

最新評論

彩票| 澄迈县| 惠州市| 黎城县| 丰台区| 城步| 论坛| 仪陇县| 仪陇县| 嘉荫县| 定州市| 湖南省| 彰武县| 鹿邑县| 鹿邑县| 大英县| 咸宁市| 拉孜县| 巴林右旗| 额济纳旗| 黄梅县| 天津市| 报价| 阳江市| 清原| 清原| 岐山县| 和政县| 拉萨市| 桐梓县| 宜兴市| SHOW| 武定县| 枣阳市| 加查县| 南川市| 舞阳县| 武安市| 汶上县| 台南市| 驻马店市|