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

vue3使用h函數(shù)封裝組件和$attrs和props的區(qū)別詳解

 更新時間:2025年10月09日 09:37:33   作者:南風(fēng)晚來晚相識  
這篇文章主要為大家詳細(xì)介紹了vue3使用h函數(shù)封裝組件和$attrs和props的區(qū)別,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

二次封裝組件需要考慮的3個重要的問題

1.props 如何進(jìn)行傳遞

2.插槽如何穿透

3.暴露實例以及實例中的方法

在vue3中的$attrs的變化

  • vue3中$listeners已被刪除合并到$attrs中。
  • vue3的$attrs現(xiàn)在包括class和style屬性。
  • vue2中不包含class和style屬性。

也就是說:當(dāng)子組件寫上 v-bind="$attrs"

父組件就可以使用子組件的內(nèi)置事件和內(nèi)置屬性了。

下面我們會詳細(xì)說一下$attrs

props 如何進(jìn)行傳遞屬性和事件

我們可以在子組件中使用 v-bind="$attrs"

這樣可以把父組件中的屬性傳遞給子組件了

// 子組件
<template>
  <div>
    <!-- v-bind="$attrs"  可以接收到父組件中的屬性設(shè)置 -->
    <el-input v-bind="$attrs"></el-input>
  </div>
</template>
// 父組件
<template>
  <div>
    <MyInput class="set-width" placeholder="請輸入名稱" clearable v-model="name" @blur="clearHandler"></MyInput>
  </div>
</template>

<script setup lang="ts">
import MyInput from '@/components/MyInput.vue'
import { ref } from 'vue';
let name = ref('')


const clearHandler = () => {
  console.log('失去焦點啦')
  name.value += 'copy'
}
</script>

<style lang="scss" scoped>
.set-width {
  margin: 100px;
  width: 300px;
}
</style>

如何解決寫組件時沒有屬性提示的問題

我們發(fā)現(xiàn)一個問題:在父組件中的組件寫相關(guān)屬性時,沒有屬性提示。

// 子組件
<template>
  <div>
    <!-- v-bind="props"  現(xiàn)在我們的屬性肯定是 element-plus 的內(nèi)置屬性了 -->
    <el-input v-bind="props"></el-input>
  </div>
</template>

<script setup lang="ts">
// 引入 input 的所有屬性
import { type InputProps} from 'element-plus'
// 定義 props, Partial將必填屬性變成可選屬性
const props = defineProps<Partial<InputProps>>()
</script>

這樣父組件在使用的時候,就可以看到屬性提示了。

插槽如何封裝1: 通過 template 來封裝插槽

<template>
  <div>
    <el-input v-bind="props">
      <!-- 插槽 -->
      <template v-for="(_, slotName) in $slots" #[slotName]>
        <slot :name="slotName"></slot>
      </template>
    </el-input>
  </div>
</template>

<script setup lang="ts">
// 引入 input 的所有屬性
import { type InputProps} from 'element-plus'
// 定義 props, Partial將必填屬性變成可選屬性
const props = defineProps<Partial<InputProps>>()

插槽如何封裝2: 通過h函數(shù)來處理插槽

我們使用h函數(shù)來進(jìn)行封裝。

h函數(shù)如果第1個參數(shù)如果是組件,那么第三個參數(shù)就是插槽

<template>
  <div>
    <!-- 我們使用h函數(shù)來進(jìn)行封裝,h函數(shù)如果第1個參數(shù)如果是組件,那么第三個參數(shù)就是插槽 -->
    <component :is="h(ElInput, {...$attrs,...props}, $slots)"></component>
  </div>
</template>

<script setup lang="ts">
import { h } from 'vue'
// 引入 input 的所有屬性
import { type InputProps, ElInput} from 'element-plus'
// 定義 props, Partial將必填屬性變成可選屬性
const props = defineProps<Partial<InputProps>>()
</script>
// 父組件
<template>
  <div>
    <MyInput class="set-width"   placeholder="請q輸入內(nèi)容">
      <!-- 在組件中使用插槽 -->
      <template #prepend>
        <el-select v-model="select" placeholder="Select" style="width: 115px">
          <el-option label="Restaurant" value="1" />
          <el-option label="Order No." value="2" />
          <el-option label="Tel" value="3" />
        </el-select>
      </template>
      <template #append>.com</template>
    </MyInput>
  </div>
</template>

<script setup lang="ts">
import MyInput from '@/components/MyInput.vue'
import { ref } from 'vue';
const select = ref('1')
</script>

<style lang="scss" scoped>
.set-width {
  margin: 100px;
  width: 300px;
}
</style>

暴露實例以及實例中的方法

我們可以通過 defineExpose 來暴露實例以及方法【常用的】

也可以通過vm.exposed來進(jìn)行暴露實例以及方法

需要注意組件最初設(shè)置了v-if=false這種情況

// 子組件
<template>
  <div>
    <!-- 我們使用h函數(shù)來進(jìn)行封裝,h函數(shù)如果第1個參數(shù)如果是組件,那么第三個參數(shù)就是插槽 -->
    <component :is="h(ElInput, {...$attrs,...props, ref: nodeRef}, $slots)"></component>
  </div>
</template>

<script setup lang="ts">
import { h, getCurrentInstance } from 'vue'
// 引入 input 的所有屬性
import { type InputProps, ElInput} from 'element-plus'
// 定義 props, Partial將必填屬性變成可選屬性
const props = defineProps<Partial<InputProps>>()
// 獲取當(dāng)前組件實例
const vm = getCurrentInstance()

// ref可以是一個字符串,也可以是一個函數(shù)。這樣父組件就可以通過ref訪問這個組件的實例了
function  nodeRef(inputInstance) {
  // 現(xiàn)在我們把子組件實例給他,當(dāng)組件使用了v-if=false的時候,inputInstance為null
  // 這里我們是把實例(實例中包含方法)暴露出去
  vm.exposed= inputInstance || {}
  // 代理對象也要做同步的更改
  vm.exposeProxy = inputInstance || {}
}
</script>
// 父組件
<template>
  <div>
    <MyInput class="set-width" v-model="msg" ref="NodeInputRef"  placeholder="請輸入內(nèi)容" @blur="clearHandler">
      <!-- 在組件中使用插槽 -->
      <template #prepend>
        <el-select v-model="select" placeholder="Select" style="width: 115px">
          <el-option label="Restaurant" value="1" />
          <el-option label="Order No." value="2" />
          <el-option label="Tel" value="3" />
        </el-select>
      </template>
      <template #append>.com</template>
    </MyInput>

    <el-button @click="getHandler">清空值</el-button>
  </div>
</template>

<script setup lang="ts">
import MyInput from '@/components/MyInput.vue'
import { ref } from 'vue';
const select = ref('1')
const msg = ref('放假快樂')

const NodeInputRef = ref(null)
// 獲取實例中的方法
const getHandler = () => {
  NodeInputRef.value?.clear()
}

const clearHandler = () => {
  console.log('失去焦點啦')
}
</script>

另外一種暴露方式

常見的暴露方式

defineProps({ 
  name:xxx,
  age:xxx,
})

等價與下面這一種

vm.exposed= {
  name:xxx,
  age:xxx,
}

vue3 中的 props

props 是組件的自定義屬性,用于從父組件向子組件傳遞數(shù)據(jù)。

props 不會包含繼承的屬性(如 class 和 style),除非顯式聲明。

vue3 中的 $attrs

vu3中$attrs: 包含了所有[傳遞]給[子組件]的非 props 屬性。如:繼承的屬性(如 class 和 style)以及未在 props 中聲明的屬性。

vue3中的$attrs: 包含 style和class。$attrs包含著數(shù)據(jù)和事件。

vue3 $listeners已被刪除合并到$attrs中。

在vue2中的$attrs

vu2中$attrs: 包含了所有[傳遞]給[子組件]的非 props 屬性和style和class之外的屬性。

vue2中的$attrs: 不包含 style和class

下面是詳細(xì)的講解:

  • 在V ue2 中,attrs里面包含著上層組件傳遞的所有數(shù)據(jù)(除style和class)
  • 當(dāng)一個組件聲明了prop時候,attrs里面包含除去prop里面的數(shù)據(jù)剩下的數(shù)據(jù)。
  • 結(jié)合inheritAttrs:false,可以將傳遞下來的數(shù)據(jù)應(yīng)用于其他元素,而不是根元素。

h函數(shù)封裝上面的組件

有些的小伙伴說:我們是否可以使用h函數(shù)去封裝上面的組件呢?

<script lang="ts">
import { defineComponent, h, getCurrentInstance } from 'vue'
import { type InputProps, ElInput } from 'element-plus'
export default  {
  // 組件名稱
  name: 'MyInput',
  inheritAttrs: false,
  setup(props, { attrs, slots }) {
    console.log('attrs', attrs)
    // attrs:除去props中聲明的屬性。包含屬性和事件
    const vm = getCurrentInstance()
    function nodeRef(inputInstance: any) {
      vm.exposed = inputInstance || {}
      vm.exposeProxy = inputInstance || {}
    }
    return () => h(ElInput, {
      ...attrs,
      ...props,
      ref: nodeRef
    }, slots)
  }
}
<template>
  <div>
    <MyInput class="set-width" placeholder="請輸入名稱" clearable v-model="name" @blur="clearHandler"></MyInput>
  </div>
</template>

<script setup lang="ts">
import MyInput from '@/components/MyInput.vue'
import { ref } from 'vue';
let name = ref('')
const clearHandler = () => {
  console.log('失去焦點啦')
  name.value += 'copy'
}
</script>

<style lang="scss" scoped>
.set-width {
  margin: 100px;
  width: 300px;
}
</style>

到此這篇關(guān)于vue3使用h函數(shù)封裝組件和$attrs和props的區(qū)別詳解的文章就介紹到這了,更多相關(guān)vue3封裝組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于Vue和Firebase實現(xiàn)一個實時聊天應(yīng)用

    基于Vue和Firebase實現(xiàn)一個實時聊天應(yīng)用

    在本文中,我們將學(xué)習(xí)如何使用Vue.js和Firebase來構(gòu)建一個實時聊天應(yīng)用,Vue.js是一種流行的JavaScript前端框架,而Firebase是Google提供的實時數(shù)據(jù)庫和后端服務(wù),結(jié)合這兩者,我們可以快速搭建一個功能強(qiáng)大的實時聊天應(yīng)用,需要的朋友可以參考下
    2023-08-08
  • vue的三種圖片引入方式代碼實例

    vue的三種圖片引入方式代碼實例

    這篇文章主要介紹了vue的三種圖片引入方式代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • 基于Vue3和element-plus實現(xiàn)登錄功能(最終完整版)

    基于Vue3和element-plus實現(xiàn)登錄功能(最終完整版)

    這篇文章主要介紹了基于Vue3和element-plus實現(xiàn)一個完整的登錄功能,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • Vue?+?Android?WebView實現(xiàn)大文件PDF預(yù)覽完整解決方案(附詳細(xì)代碼)

    Vue?+?Android?WebView實現(xiàn)大文件PDF預(yù)覽完整解決方案(附詳細(xì)代碼)

    這篇文章主要介紹了Vue?+?Android?WebView實現(xiàn)大文件PDF預(yù)覽完整解決方案的相關(guān)資料,解決了在AndroidWebView環(huán)境下預(yù)覽大文件PDF的問題,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-12-12
  • vue cli3.0 引入eslint 結(jié)合vscode使用

    vue cli3.0 引入eslint 結(jié)合vscode使用

    這篇文章主要介紹了vue cli3.0 引入eslint 結(jié)合vscode使用,本文分步驟給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-05-05
  • vue--點擊當(dāng)前增加class,其他刪除class的方法

    vue--點擊當(dāng)前增加class,其他刪除class的方法

    今天小編就為大家分享一篇vue--點擊當(dāng)前增加class,其他刪除class的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • Vue EventBus自定義組件事件傳遞

    Vue EventBus自定義組件事件傳遞

    這篇文章主要介紹了Vue EventBus自定義組件事件傳遞,組件化應(yīng)用構(gòu)建是Vue的特點之一,本文主要介紹EventBus進(jìn)行數(shù)據(jù)消息傳遞 ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • vue實現(xiàn)input輸入模糊查詢的三種方式

    vue實現(xiàn)input輸入模糊查詢的三種方式

    本文主要介紹了vue實現(xiàn)input輸入模糊查詢的三種方式嗎,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • vue中v-if?和v-permission?共同使用的坑及解決方案

    vue中v-if?和v-permission?共同使用的坑及解決方案

    這篇文章主要介紹了vue中v-if?和v-permission?共同使用的坑及解決方案的相關(guān)資料,需要的朋友可以參考下
    2023-07-07
  • 前端vue數(shù)組去重的三種方法代碼實例

    前端vue數(shù)組去重的三種方法代碼實例

    數(shù)組去重是我面試時候經(jīng)常會問到應(yīng)聘者的一個問題,所以下面這篇文章主要給大家介紹了關(guān)于前端vue數(shù)組去重的三種方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-06-06

最新評論

广昌县| 渭源县| 宜兴市| 甘南县| 丰城市| 东阿县| 汪清县| 镇坪县| 江达县| 崇信县| 南郑县| 揭西县| 双桥区| 扶沟县| 交城县| 延川县| 天峻县| 徐闻县| 上饶市| 洞口县| 昌平区| 衡阳市| 磐石市| 思南县| 洪泽县| 蕲春县| 民乐县| 平度市| 阳新县| 门源| 平湖市| 洛隆县| 云阳县| 哈巴河县| 商水县| 顺义区| 巴楚县| 景德镇市| 塔河县| 保定市| 永吉县|