欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺聊一下Vue3中的component組件

 更新時間:2023年08月31日 10:28:41   作者:BennuCTech  
開發(fā)過程中我們會經(jīng)常遇到一些復(fù)雜的頁面,而這些頁面大部分由一個個小部分組合起來的,而且不同頁面中可能有些部分是一樣的,所以我們通常會將這些部分封裝成組件,在Vue中,我們可以使用components組件(模板)來實現(xiàn),本文就來詳細(xì)的說一說Vue3中的component組件

實現(xiàn)一個組件

一個組件其實就是一個vue文件,簡單示例(header.vue)如下:

<script setup></script>
<template>
  <div class="header"></div>
</template>
<style scoped lang="less">
.header {
  position: absolute;
  width: 100%;
  height: 80px;
  background: linear-gradient(
    180deg,
    rgba(0, 0, 0, 0.6) 0%,
    rgba(0, 0, 0, 0) 100%
  );
}
</style>

注冊使用

基于script setup可以自動注冊組件,只需要import即可使用,如下:

<script setup>
import Header from "./Header.vue";
</script>
<template>
  <div class="container">
    <Header></Header>
  </div>
</template>
<style scoped lang="less">
.container {
  width: 100%;
  height: 100%;
}
</style>

數(shù)據(jù)

可以通過Prop向組件傳遞數(shù)據(jù),先在組件中定義,如下:

<script setup>
const props = defineProps({
  title: String,
  userInfo: Object
});
function doSomething(){
  if(props.userInfo.isVip){
    ...
  }
}
</script>
<template>
  <div class="header">{{props.title}}</div>
</template>
<style scoped lang="less">
...
</style>

這里定義了一個title屬性,是一個字符串;一個userInfo屬性,是一個對象,然后在組件中就可以通過props.xxx來使用這些屬性。

那么如何將數(shù)據(jù)傳遞給這些屬性呢,直接通過v-bind綁定數(shù)據(jù)即可,如下:

<script setup>
import Header from "./Header.vue";
let userInfo;
let title;
</script>
<template>
  <div class="container">
    <Header :title="title" :userInfo="userInfo"></Header>
  </div>
</template>
<style scoped lang="less">
...
</style>

這里使用的是v-bind的縮寫。v-bind綁定后面雙引號中是表達(dá)式,所以如果類型是:

  • 數(shù)值::count="3"
  • 布爾值::isVip="true"
  • 數(shù)組::array="[1,2,3]"
  • 對象::info="{name:'名字',isVip:true}" 其他就不一一列舉了。

Props是支持類型如下:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol。

Props支持類型檢查,同時支持默認(rèn)值,如下:

  props: {
    // 基礎(chǔ)的類型檢查 (`null` 和 `undefined` 值會通過任何類型驗證)
    propA: Number,
    // 多個可能的類型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 帶有默認(rèn)值的數(shù)字
    propD: {
      type: Number,
      default: 100
    },
    // 帶有默認(rèn)值的對象
    propE: {
      type: Object,
      // 對象或數(shù)組的默認(rèn)值必須從一個工廠函數(shù)返回
      default() {
        return { message: 'hello' }
      }
    },
    // 具有默認(rèn)值的函數(shù)
    propG: {
      type: Function,
      // 與對象或數(shù)組的默認(rèn)值不同,這不是一個工廠函數(shù)——這是一個用作默認(rèn)值的函數(shù)
      default() {
        return 'Default function'
      }
    }
  }

Props是單向數(shù)據(jù)流,這樣可以防止子組件意外變更父組件的狀態(tài),每當(dāng)父組件發(fā)生變更,子組件所有Props都會刷新到最新值。所以子組件中不能更改Props的屬性,否則會在控制臺警告。

非 Prop 的 Attribute

比如class、style 和 id等attribute,默認(rèn)是添加到組件的根節(jié)點上,如:

<script setup>
...
</script>
<template>
  <div class="header" >
    <input ...>
  </div>
</template>
<style scoped lang="less">
...
</style>

當(dāng)我們使用這個組件時,為其添加attribute,如:

<Header id="my-header"></Header>

實際的渲染結(jié)果是:

<div class="header" id="my-header">
  <input ...>
</div>

禁用 Attribute 繼承

如果不希望添加到根節(jié)點上,則可以設(shè)置inheritAttrs: false

<script setup>無法聲明inheritAttrs,所以我們需要在添加普通的<script>,同時使用v-bind="$attrs"來綁定繼承Attribute的節(jié)點,如

<script>
export default {
  inheritAttrs: false
};
</script>
<script setup>
...
</script>
<template>
  <div class="header" >
    <input ... v-bind="$attrs">
  </div>
</template>
<style scoped lang="less">
...
</style>

這樣添加給組件的Attribute就會直接添加到input元素上,實際的渲染結(jié)果是:

<div class="header">
  <input ...  id="my-header">
</div>

多根節(jié)點

如果組件有多根節(jié)點,那么必須顯式設(shè)置v-bind="$attrs",否則警告。

事件

數(shù)據(jù)傳遞清楚了,那么如何響應(yīng)組件的一些自定義事件呢?通過emits來定義事件,如下:

<script setup>
const emit = defineEmits(["onSelected"]);
function selectItem(item){
  emit("onSelected", item);
}
</script>
<template>
  <div class="header" >
    ...
  </div>
</template>
<style scoped lang="less">
...
</style>

這里定義了一個onSelected事件,當(dāng)組件中觸發(fā)selectItem函數(shù)的時候就會執(zhí)行這個事件。

注意:如果沒有參數(shù),則直接emit("onSelected")即可;如果有多個參數(shù),則emit("onSelected", param1, param2, ...)

在父組件中則通過v-on來綁定事件,如下:

<script setup>
import Header from "./Header.vue";
function headerSelected(item){
}
</script>
<template>
  <div class="container">
    <Header @onSelected="headerSelected"></Header>
  </div>
</template>
<style scoped lang="less">
...
</style>

這里同樣是v-on的縮寫形式,這樣就綁定了事件。事件同樣可以驗證,這里就不細(xì)說了。

v-model

v-model是雙向數(shù)據(jù)綁定,默認(rèn)情況下,組件上的 v-model 使用 modelValue 作為 prop 和 update:modelValue 作為事件。比如有一個title屬性:

<my-component v-model:title="bookTitle"></my-component>

那么在子組件中就可以這樣做:

<script setup>
const props = defineProps({
  title: String
});
const emit = defineEmits(["update:title"]);
const setTitle = (newTitle) => {
  emit("update:title", newTitle);
}
</script>
<template>
  <div class="header" >
    ...
  </div>
</template>
<style scoped lang="less">
...
</style>

這樣子組件中可以通過update:title來同步title數(shù)據(jù)。

插槽

如果子組件中部分區(qū)域是不定的,需要父組件來實現(xiàn),那么怎么辦?這就需要用到插槽slot,插槽使用很簡單,如下:

<script setup>
...
</script>
<template>
  <div class="header" >
    <slot>default</slot>
  </div>
</template>
<style scoped lang="less">
...
</style>

這里定義了一個插槽,并且指定了一個默認(rèn)內(nèi)容,在父組件中:

<script setup>
import Header from "./Header.vue";
</script>
<template>
  <div class="container">
    <Header>newtitle</Header>
  </div>
</template>
<style scoped lang="less">
...
</style>

這樣插槽就被“newtitle”這個字符串替代,如果這里沒有任何內(nèi)容<Header></Header>則顯示默認(rèn)內(nèi)容,即"default"。

插槽中不僅是字符串,可以是html或其他組件,比如:

<Header>
 <button>submit</botton>
</Header>

當(dāng)然默認(rèn)內(nèi)容也可以是html。

具名插槽

一個組件里可以有多個插槽,比如左邊欄右邊欄等,這樣就需要具名插槽來區(qū)分,如下:

<script setup>
...
</script>
<template>
  <div class="header" >
    <div name="leftbar" >
      <slot>left</slot>
    </div>
    <div name="rightbar" >
      <slot>right</slot>
    </div>
  </div>
</template>
<style scoped lang="less">
...
</style>

使用的時候需要用v-slot指令,并且一定是<template>元素,因為v-slot只能添加在<template>上,如下:

<script setup>
import Header from "./Header.vue";
</script>
<template>
  <div class="container">
    <Header>
      <template v-slot:leftbar >
        <button>left</button>
      </template>
      <template v-slot:rightbar >
        <button>right</button>
      </template>
    </Header>
  </div>
</template>
<style scoped lang="less">
...
</style>

插槽名也可以是動態(tài)的<template v-slot:[dynamicSlotName] >。v-slot也可以縮寫成“#”,如<template #leftbar >。

作用域

如下代碼:

<div v-for="item in list" >
  <slot></slot>
</div>

這時候當(dāng)我們使用組件的時候,插槽中則無法item,如下

<my-component >
  <img :src="item.img"></img>
</my-component>

像上面這種代碼就會報錯,因為只能在組件中訪問item,而插槽是在父組件上提供的,作用域不同。

當(dāng)然我們可以為插槽添加一個attribute綁定,即插槽 prop,如下:

<div v-for="item in list" >
  <slot :item="item"></slot>
</div>

插槽可以添加多個attribute。

然后在父級中使用帶值的v-slot來定義我們提供的插槽 prop 的名字,如:

<my-component >
  <template v-slot:default="slotProps">
    <img :src="slotProps.item.img"></img>
  </template>   
</my-component>

這樣就不會報錯了。如果只有一個插槽,那么v-slot可以直接添加組件上,如:

<my-component v-slot="slotProps">
  <img :src="slotProps.item.img"></img> 
</my-component>

就不需要template元素了;但是如果有多個插槽(具名)則必須添加在template元素上。

Provide / Inject

上面知道父組件向子組件傳遞數(shù)據(jù)用Props,但是如果組件層級很深,需要向一個底層的子組件傳遞數(shù)據(jù),如果用Props就需要一層層的去傳遞。這時候就可以使用Provide / Inject。如: 父組件中通過provide(key, value)來設(shè)置數(shù)據(jù)

<script setup>
const userid = "123";
provide("userid", userid);
</script>
...

那么在子組件中通過inject(key, defaultValue)來獲取數(shù)據(jù)

<script setup>
const userid = inject("userid", defaultId);
</script>
...

當(dāng)然上面是一次性的數(shù)據(jù),如果需要響應(yīng),則在父組件中使用ref或reactive,如:

<script setup>
const userid = ref("123");
provide("userid", userid);
</script>
...

獲取DOM對象

在組件中,我們可以給元素設(shè)置id,并通過id的方式來獲取它的DOM對象。但是在頁面上有多個該組件的情況下,這樣獲取DOM對象就會有問題,因為id不唯一。

我們還可以使用 ref attribute 為子組件或 HTML 元素指定引用 ID。如:

<script setup>
import Header from "./Header.vue";
const headerRef = ref();
</script>
<template>
  <div class="container">
    <Header ref="headerRef">
      ...
    </Header>
  </div>
</template>
<style scoped lang="less">
...
</style>

上面Header的ref屬性是“headerRef”,所以變量名也保持一致,即const headerRef = ref();,這樣headerRef.value就是它的DOM對象,可以執(zhí)行getElementsByTagName等方法。

這樣即是頁面上存在多個組件,但是因為作用域的存在,每個headerRef互不干擾。

列表

如果是一個列表中呢?比如:

<template>
  <div class="container">
    <item ref="itemRef" v-for="item in list">
      ...
    </item>
  </div>
</template>

這樣通過const itemRef = ref();得到的是哪個?其實這樣itemRef.value就變成了一個列表,itemRef.value[0]就是第一個item組件的對象。

元素位置受限

有些 HTML 元素如 <ul>、<ol>、<table> 和 <select>,對于其內(nèi)部是有嚴(yán)格限制的。而有些元素如 <li>、<tr> 和 <option>,只能出現(xiàn)在某些特定的元素內(nèi)部。

這會導(dǎo)致我們使用這些有約束條件的元素時遇到一些問題。例如:

<table>
  <my-component></my-component>
</table>

自定義組件 <my-component> 會被作為無效的內(nèi)容提升到外部,導(dǎo)致渲染出錯。這時候需要使用 is attribute,如:

<table>
  <tr is="vue:my-component"></tr>
</table>

注意:is 的值必須以 vue: 開頭,才可以被解釋為 Vue 組件。這是避免和原生自定義元素混淆。

調(diào)用子組件方法

上面事件章節(jié)說的是父組件響應(yīng)子組件的事件,也就是說是子組件調(diào)用父組件的方法。那么父組件如何調(diào)用子組件的方法?

Expose

首先子組件的方法需要暴露出去,如下:

<script setup>
defineExpose({
  onEvent
});
function onEvent(event) {
  console.log(`header: ${event}`);
}
</script>
<template>
  <div class="header" >
    ...
  </div>
</template>
<style scoped lang="less">
...
</style>

然后在父組件中為子組件添加ref屬性,然后通過ref()函數(shù)獲取對象執(zhí)行方法即可,如下:

<script setup>
import Header from "./Header.vue";
const headerRef = ref();
function headerEvent(event){
  headerRef.value.onEvent(event);
}
</script>
<template>
  <div class="container">
    <Header ref="headerRef">
      ...
    </Header>
  </div>
</template>
<style scoped lang="less">
...
</style>

這樣就可以通過headerRef.value執(zhí)行暴露出來的方法了。

如果有多個子組件,都設(shè)置了ref屬性,則定義多個變量即可,如下:

const headerRef = ref();
const footerRef = ref();

EventBus

更簡單的方法是使用EventBus即可完成組件間通信,使用也非常簡單,參考官方文檔即可https://www.npmjs.com/package/events

我們可以簡單封裝一下以便使用,如下:

import EventEmitter from "events";
const eventEmitter = new EventEmitter();
export const WsEvent = {
  emit: data => {
    eventEmitter.emit("wsevent", data);
  },
  on: callback => {
    eventEmitter.on("wsevent", callback);
  }
};

以上就是詳細(xì)說一說Vue3中的component組件的詳細(xì)內(nèi)容,更多關(guān)于Vue3 component組件的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 關(guān)于electron打包的坑

    關(guān)于electron打包的坑

    本文主要介紹了關(guān)于electron打包的坑,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • Vue常用的幾個指令附完整案例

    Vue常用的幾個指令附完整案例

    越來越多的人在用Vue,剛開始接觸vue的話常接觸的指令就幾個,統(tǒng)一歸納一下。感興趣的朋友跟隨小編一起看看吧
    2018-11-11
  • vue實現(xiàn)井字棋游戲

    vue實現(xiàn)井字棋游戲

    這篇文章主要為大家詳細(xì)介紹了vue實現(xiàn)井字棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-09-09
  • Vue如何實現(xiàn)監(jiān)聽組件原生事件

    Vue如何實現(xiàn)監(jiān)聽組件原生事件

    這篇文章主要介紹了Vue如何實現(xiàn)監(jiān)聽組件原生事件,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • Vue路由傳參及props解耦深入分析

    Vue路由傳參及props解耦深入分析

    vue路由傳參的使用場景一般都是應(yīng)用在父路由跳轉(zhuǎn)到子路由時,攜帶參數(shù)跳轉(zhuǎn),下面這篇文章主要給大家介紹了關(guān)于vue路由傳參方式的方式總結(jié)及獲取參數(shù)的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • 詳解VUE項目中安裝和使用vant組件

    詳解VUE項目中安裝和使用vant組件

    這篇文章主要介紹了VUE安裝和使用vant組件,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • vue2項目使用element-ui的el-tabs組件導(dǎo)致瀏覽器崩潰卡死問題

    vue2項目使用element-ui的el-tabs組件導(dǎo)致瀏覽器崩潰卡死問題

    這篇文章主要介紹了vue2項目使用element-ui的el-tabs組件導(dǎo)致瀏覽器崩潰卡死問題及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • vue的列表交錯過渡實現(xiàn)代碼示例

    vue的列表交錯過渡實現(xiàn)代碼示例

    這篇文章主要介紹了vue的列表交錯過渡實現(xiàn)代碼示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Vue修改Dom不生效的解決

    Vue修改Dom不生效的解決

    這篇文章主要介紹了Vue修改Dom不生效的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • vue阻止重復(fù)請求實現(xiàn)示例詳解

    vue阻止重復(fù)請求實現(xiàn)示例詳解

    這篇文章主要為大家介紹了vue阻止重復(fù)請求實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01

最新評論