vue3中$attrs的變化與inheritAttrs的使用詳解
在vue3中的$attrs的變化
$listeners已被刪除合并到$attrs中。 $attrs現(xiàn)在包括class和style屬性。 也就是說在vue3中$listeners不存在了。vue2中$listeners是單獨存在的。 在vue3 $attrs包括class和style屬性, vue2中 $attrs 不包含class和style屬性。
在vue2中的$attrs
在Vue 2中,attrs里面包含著上層組件傳遞的所有數(shù)據(jù)(除style和class) 當(dāng)一個組件聲明了prop時候,attrs里面包含除去prop里面的數(shù)據(jù)剩下的數(shù)據(jù)。 結(jié)合inheritAttrs:false,可以將傳遞下來的數(shù)據(jù)應(yīng)用于其他元素,而不是根元素:
父組件的屬性直接渲染在根節(jié)點上
父頁面.vue
<template> <div> <TestCom title="父組件給的標(biāo)題" aa="我是aa" bb="我是bb"></TestCom> </div> </template> <script setup lang="ts"> import TestCom from "../../components/TestCom.vue" </script>
子組件.vue
<template> <div class="root-son"> <p>我是p標(biāo)簽</p> <span>我是span</span> </div> </template>
我們發(fā)現(xiàn)父組件中的屬性直接是渲染在了 <div class="root-son"></div>這個節(jié)點上。 變?yōu)榱?<div class="root-son" title="父組件給的標(biāo)題" aa="我是aa" bb="我是bb"></div>。 因為在默認情況下,父組件的屬性會直接渲染在子組件的根節(jié)點上?!局攸c】 然后有些情況我們希望是渲染在指定的節(jié)點上。那怎么處理這問題呢? 我們的 $attrs 和 inheritAttrs: false 這一對 ”好基友“ 閃亮登場
如何讓父組件的屬性渲染在指定的節(jié)點上
我們可以使用 $attrs 配合 inheritAttrs: false 可以將屬性渲染在指定的節(jié)點上 子組件的代碼中新增 inheritAttrs: false //子組件 <template> <div class="root-son"> <!--所有的屬性都將被這個元素p接收 --> <p v-bind="$attrs">我是p標(biāo)簽</p> <span>我是span</span> </div> </template> <script lang="ts" setup> // 不讓子組件的根節(jié)點渲染屬性 inheritAttrs: false </script>
發(fā)現(xiàn)問題-根節(jié)點和指定節(jié)點都別渲染了屬性
好家伙,你不是說 $attrs 配合 inheritAttrs: false可以將屬性渲染在指定的節(jié)點上。 現(xiàn)在雖然渲染在指定節(jié)點上。但是根節(jié)點也有。這樣不好吧。切。走了。走了。菜雞。 這,這,這, 你別走呀。 等一會。趕緊偷偷人偷偷去官網(wǎng)看一下出怎么說的。 原來是這樣的: <script setup> 可以和普通的 <script> 一起使用。 普通的 <script> 在有這些情況下或許會被使用到。 比如:無法在 <script setup> 中的聲明選項中去使用 inheritAttrs 或插件的自定義選項。
我們需要將代碼變?yōu)槿缦拢?/p>
<template> <div class="root-son"> <!--所有的屬性都將被這個元素p接收 --> <p v-bind="$attrs">我是p標(biāo)簽</p> <span>我是span</span> </div> </template> <script> //無法在 <script setup> 中的聲明選項中去使用 inheritAttrs。 //所有只有在整一個<script> export default { inheritAttrs: false, customOptions: {} } </script> <script lang="ts" setup> 你的代碼 </script>
TM又又發(fā)現(xiàn)問題了
在瀏覽器中提示:[plugin:vite:vue] [@vue/compiler-sfc] <script> and <script setup> must have the same language type. TM又又發(fā)現(xiàn)問題了。穩(wěn)住,我可以的。在心里一直告訴自己,冷靜點,我可以解決這個問題的。 先看看它提示 must have the same language type. 必須具有相同的語言類型 小問題就是說必須要有一個類型。我將 script 上添加一個 lang="ts"就解決了。 我感覺自己又行了。 <template> <div class="root-son"> <p v-bind="$attrs">我是p標(biāo)簽</p> <span>我是span</span> </div> </template> <script lang="ts"> export default { inheritAttrs: false, customOptions: {} } </script> <script lang="ts" setup> </script>
簡單的介紹 $listeners
$listeners包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監(jiān)聽器。 它可以通過 v-on="$listeners" 傳入內(nèi)部組件——在創(chuàng)建更高層次的組件時非常有用。 我的理解:因為$listeners 可以接收父級組件中(不含.native修飾器的) v-on 事件監(jiān)聽器. 所以在進行組件事件傳遞的時候非常有用。 很多時候我們對組件進行二次封裝的時候不可能將組件中的內(nèi)置事件都拋出來。 這個時候 $listeners 就派上用場了。 在vue2中有 vue2中$listeners是單獨存在的。vue3 被合并到$attrs中了。
vue2中 v-bind="$attrs" 和 $listeners
//子組件.vue <template> <div> <el-button type="primary" @click="dialogVisible = true">點擊打開 </el-button> <el-dialog v-bind="$attrs" v-on="$listeners" :visible.sync="dialogVisible" width="30%" :before-close="handleClose"> <span>這是一段信息</span> <span slot="footer" class="dialog-footer"> <el-button @click="dialogVisible = false">取 消</el-button> <el-button type="primary" @click="dialogVisible = false">確 定</el-button> </span> </el-dialog> </div> </template> <script> export default { inheritAttrs: false, //不讓屬性直接渲染在根節(jié)點上 data() { return { dialogVisible: false }; }, methods: { handleClose(done) { this.$confirm('確認關(guān)閉?').then(() => { done(); }).catch(() => { }); } } }; </script>
//父組件.vue <template> <div> <LianCom title="父組件給的標(biāo)題" @open="openHandler"></LianCom> </div> </template> <script> import LianCom from "../components/LianCom.vue" export default { components: { LianCom }, methods: { openHandler() { console.log('可以直接注冊事件,因為 v-on="$listeners"會接收除了.native的原生事件') } } } </script>
vue3 v-bind="$attrs" 會接收屬性和事件
//子組件 <template> <el-button text @click="dialogTableVisible = true"> 打開 </el-button> <el-dialog width="600px" v-bind="$attrs" v-model="dialogTableVisible" title="我是標(biāo)題"> <div>我值彈窗中的內(nèi)容</div> </el-dialog> </template> <script lang="ts"> export default { inheritAttrs: false, } </script> <script lang="ts" setup> import { ref } from 'vue' const dialogTableVisible = ref(false) </script> ps:我們沒有向上拋出任何事件。 但是父組件可以調(diào)用 Element Plus 中對話框中的內(nèi)置方法。 但是父頁面中可以 注冊 Element Plus 中對話框中的內(nèi)置方法。
// 父組件 <template> <div class="father"> <TestCom @close="closeHandler" :before-close="beforeclose" title="父組件給的標(biāo)題" aa="我是aa" bb="我是bb"></TestCom> </div> </template> <script setup lang="ts"> import { ElMessageBox } from 'element-plus' import TestCom from "../../components/TestCom.vue" // Dialog 關(guān)閉的回調(diào) const closeHandler = () => { console.log('Dialog 關(guān)閉的回調(diào)') } /* before - close 只會在用戶點擊關(guān)閉按鈕或者對話框的遮罩區(qū)域時被調(diào)用。 如果你在 footer 具名插槽里添加了用于關(guān)閉 Dialog 的按鈕,那么可以在按鈕的點擊回調(diào)函數(shù)里加入 before - close 的相關(guān)邏輯。 關(guān)閉前的回調(diào),會暫停 Dialog 的關(guān)閉. 回調(diào)函數(shù)內(nèi)執(zhí)行 done 參數(shù)方法的時候才是真正關(guān)閉對話框的時候. */ const beforeclose = (done: () => void) => { ElMessageBox.confirm('Are you sure to close this dialog?') .then(() => { console.log('用戶點擊了確定') done() }) .catch(() => { console.log('用戶點擊了取消') }) } </script>
到此這篇關(guān)于vue3中$attrs的變化與inheritAttrs的使用 的文章就介紹到這了,更多相關(guān)vue3 $attrs與inheritAttrs的使用 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue-resource + json-server模擬數(shù)據(jù)的方法
本篇文章主要介紹了vue-resource + json-server模擬數(shù)據(jù)的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11vue設(shè)計與實現(xiàn)合理的觸發(fā)響應(yīng)
這篇文章主要為大家介紹了vue設(shè)計與實現(xiàn)合理的觸發(fā)響應(yīng)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08