首頁 > 軟體

vue3中的透傳attributes教學範例詳解

2022-08-29 14:01:23

引言

最近兩年都是在使用 react 進行專案開發,看技術部落格都是針對 react 和 javaScript 高階方面的,對 vue 的知識基本上遺忘的差不多了。最近開始慢慢回顧 vue 的知識以及對新的語法進行學習,為後面的計劃做準備(哈哈哈,懂得都懂)。

先從最簡單的樣式開始吧。

繫結樣式

vue 的樣式繫結要人性化很多,react 實現 vue 的這種寫法,還需要專門下載一個第三方庫: classnames。

vue 的樣式繫結有兩種形式:物件陣列

相對而言,個人還是比較的偏向物件的寫法,可能 react 寫習慣了吧。原因有兩點:

  • 陣列能實現的,物件也能使用(反之亦然)。
  • 在 DOM 結構中,使用陣列的[]形式,感覺看起來比較的怪異,複雜。

物件

我把物件的形式分為三種場景,分別如下:

場景一:迴圈列表,根據列表項的某屬性的不同而展示不同

 <script setup lang="ts">
 const list = [
   {
     id: "1",
     name: "name1",
     isActive: true,
   },
   {
     id: "2",
     name: "name2",
     isActive: false,
   },
   {
     id: "3",
     name: "name3",
     isActive: false,
   },
 ];
 </script>
 <template>
   <div
     v-for="item in list"
     :key="item.id"
     class="common"
     :class="{ isActive: item.isActive }" 
   >
     {{ item.name }}
   </div>
 </template>
 <style>
 .isActive {
   color: red;
 }
 </style>

根據列表項的isActive的屬性值不同,來判斷是否顯示isActive類名。

場景二:通過觸發事件,來展示不同的樣式。

這種情況一般針對於使用者操作,比如點選按鈕觸發事件,來修改某一內容的樣式。

 <script setup lang="ts">
 import { ref } from "vue";
 const isActive = ref<boolean>(false);
 // 事件改變 data 屬性值  
 const btn = () => {
   isActive.value = !isActive.value;
 };
 </script>
 <template>
   <div class="common" :class="{ isActive: isActive }">文字說明</div>
   <button @click="btn">改變樣式</button>
 </template>
 <style>
 .common {
   font-size: 20px;
 }
 .isActive {
   color: red;
 }

通過點選事件,修改 data 中的值,從而影響到 div 標籤的類名展示。

情況三:當關聯多個動態樣式,直接繫結一個物件

上面的情況,當存在少量的動態樣式(1~2個)的時候,可以直接寫在DOM結構中,閱讀性可觀。當存在多個的時候,還這樣寫的話,可能 DOM 就顯的混亂了,閱讀性極低,這時藉助一個物件就很好的解決了這個問題。

 <script setup lang="ts">
 import { reactive } from "vue";
 const classObj = reactive({
   isActive: true,
   hasError: false,
   textRed: true,
 });
 </script>
 <template>
   <div class="common" :class="classObj">文字說明</div>
 </template>

陣列

陣列的寫法,對於個人來說,就大致的瞭解下就行了。

形式一:繫結多個class

 <script setup lang="ts">
 import { ref } from "vue";
 const activeClass = ref("active");
 const errorClass = ref("text-danger");
 </script>
 <template>
   <div :class="[activeClass, errorClass]"></div>
 </template>

最後渲染出來的結果:

 <div class="active text-danger"></div>

形式二:陣列中的判斷

 <!--三目運運算元的判斷-->
 <div :class="[isActive ? activeClass : '', errorClass]"></div>
 <!--陣列中巢狀物件的判斷-->
 <div :class="[{activeClass: isActive}, errorClass]"></div>

vue 中的動態 style 跟 class 的用法基本相似的,就不用多說了。

透傳的attributes

在上面的樣式繫結中,都是把 class 寫在了原生標籤上,那麼如果把 class 寫在元件上,效果是什麼呢?

在此之前,先來彌補兩個小知識點。

知識點一:vue3 支援多個根節點

 <!--vue2: 錯誤的寫法-->
 <template>
   <div></div>
   <div></div>
 </template>
 <!--vue3: 正確-->
 <template>
   <div></div>
   <div></div>
 </template>

知識點二:什麼是透傳的attributes?

“透傳 attribute”指的是傳遞給一個元件,卻沒有被該元件宣告為 propsemits 的 attribute 或者 v-on 事件監聽器。常見的有 class style id.

簡單的理解就是:傳遞給子元件的屬性,但是被沒有在子元件宣告,就是透傳 attributes

準備工作完成,可以開始正題了。

透傳 attributes 之樣式繫結

分為兩種情況,只有一個根節點或者多個根節點。

情況一:子元件只有一個根節點

 <!--son子元件-->
 <template>
   <div class="own">son元件</div>
 </template>

存在自身的類名 own

 <!--父元件使用Son-->
 <Son class='abc' />

class 並沒有在 props 中申明,那麼它就是透傳 attributes。

那麼最後渲染的結果:

 <div class='abc own'>son元件</div>

就會主動的繫結到根節點上去,與原來的 class 進行組合。

情況二:子元件有多個根節點

存在多個根節點的時候,並且還傳遞了透傳 attributes,如果沒有手動處理的話,是會存在警告的。

 <!--son子元件-->
 <template>
   <div class="own">son元件1</div>
   <div class="own">son元件2</div>
 </template>
 <!--父元件使用Son-->
 <Son class='abc' />

沒有處理,丟擲警告:

那麼處理警告的方式兩種:

  • 禁用透傳 attributes,設定 inheritAttrs 為 false(後面再說)。
  • 手動處理,具體系結在哪一個根節點。
 <!--son子元件-->
 <template>
   <div class="own" :class="$attrs['class']">son元件1</div>
   <div class="own">son元件2</div>
 </template>

這樣警告也會消失,並且把透傳 attributes 繫結在了第一個根節點上。這裡的$attrs是一個物件,需要具體指明某個屬性。

最後渲染的結果:

 <div class="own abc">son元件1</div>
 <div class="own">son元件2</div>

透傳 attributes 之事件繫結

上面只是針對樣式進行了透傳,那麼事件的話,又會是怎麼樣的呢?

先說結論吧,表現形式跟樣式繫結是基本一樣的。

 <!--子元件Son-->
 <script setup lang="ts">
 const btn1 = () => {
   console.log("子元件的點選事件");
 };
 </script>
 <template>
   <button @click="btn1">點選</button>
 </template>

現在子元件的根節點是一個 button 標籤,並且上面繫結了一個點選事件。

 <!--父元件使用-->
 <script setup lang="ts">
 import Son from "./Son.vue";
 const btn = () => {
   console.log("父元件的點選事件");
 };
 </script>
 <template>
   <Son @click="btn" />
 </template>

父元件呼叫,也傳遞了一個透傳的事件過來。當點選按鈕:

發現,子元件的事件被觸發了,父元件傳遞過來的事件也被觸發了,順序為先子後父

透傳的 attributes 基本說完了,接下來就看看幾個特殊部分吧。

特殊1:元件巢狀

有些情況下一個元件會在根節點上渲染另一個元件。那麼透傳 attributes 也會繼續傳遞下去。

 <!--baseChild-->
 <template>
   <div></div>
 </template>
 <!--child-->
 <template>
   <base-child />
 </template>
 <!--father-->
 <Child class='abc'/>

那麼最後渲染的結果:

 <div class='abc'></div>

特殊2:禁用透傳attributes

設定 inheritAttrs:false,就禁止使用了自動繫結,可以消除前面所說的警告;然後就可以自由的繫結 $attrs, 該物件就包含了傳遞過來的透傳 attributes。

 <!--如果是setup寫法,就需要單獨新增一個script標籤,暴露一個設定物件-->
 <script lang="ts">
 export default {
   inheritAttrs: false, // 禁用
 };
 </script>
 <script setup lang="ts">
 const btn1 = () => {
   console.log("子元件的點選事件");
 };
 </script>
 <template>
   <button @click="btn1">點選</button>
 </template>

需要注意的是:

  • 和 props 有所不同,透傳 attributes 在 JavaScript 中保留了它們原始的大小寫,所以像 foo-bar 這樣的一個 attribute 需要通過 $attrs['foo-bar'] 來存取。
  • 像 @click 這樣的一個 v-on 事件監聽器將在此物件下被暴露為一個函數 $attrs.onClick

特殊3:在 javascript 中存取透傳的attributes

在元件範例中獲取,通過 this 的形式

 export default {
   created() {
     console.log(this.$attrs)
   }
 }

總結

回顧了vue中動態繫結樣式,還是比較簡單;又新學習了一點 vue3 的新知識:透傳attributes,收穫滿滿。

參考檔案

cn.vuejs.org/guide/essen…

cn.vuejs.org/guide/compo…

以上就是vue3中的透傳attributes教學範例詳解的詳細內容,更多關於vue3透傳attributes的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com