您好,登錄后才能下訂單哦!
本篇內容介紹了“Ref操作Dom在Vue2.x和Vue3.x的不同點有哪些”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
在開發一個項目之前,我們往往都是先做下需求分析,針對前端而言,就是可以調研或者選擇一個基礎組件庫,來提高我們的工作效率。畢竟,對比較計較時間成本的公司來說,不會給你拿看電視劇玩游戲的時間去專門開發一個類似日歷的組件。但在市面上的組件庫,并不能都能滿足我們的需求。這個時候,我們就需要自己手寫組件,來應用到項目中。
而這就是我想說的: 如何設計組件,讓其既能易于應用(或者說減少代碼量),又能提高擴展性,方便需求變更和后續維護?
可以有很多種方式,而利用Ref操作Dom的特性隨是其中之一,但這個方式卻讓我們在維護和操作Modal、Popup以及頻繁操作Dom顯示和隱藏交互的組件的時候,卻發揮得很大優勢。
就對Ref操作Dom的相關知識點以及應用實例分幾個方面來做下剖析
Ref獲取Dom的本質
Ref操作Dom在Vue2.x和Vue3.x的不同
Ref操作組件Dom和父子組件單向傳遞對比
Ref獲取Dom的本質
Vue2.x中Vue的對象屬性$refs,其實就是所有注冊過的ref的一個集合,而ref對應著template模版中,不同組件或普通Dom元素上關聯的ref="xx"; 源碼中ref的實際獲取方式也是通過原生方式getElementById而得到的Dom節點;可以說ref是document.getElementById
的語法糖。vue3的ref延續了vue2的用法,還增加了一個作用就是創建響應式數據
也許有人會問了,既然ref和getElementById都能獲取到Dom,那么在項目開發中,我選擇哪種方式都沒什么區別呢?
關于這個問題,經過數據表明,$refs相對document.getElementById的方法,會減少獲取dom節點的消耗;而具體原因,等下一篇文章再詳細探討。
Ref操作Dom在Vue2.x和Vue3.x的不同
我們只需要在相應的Dom元素或者組件加上ref="xx"屬性,然后在Vue對象中使用this.$refs.xx,就可以直接獲取到該Dom并操作其方法屬性,
<user-and-dep-tree-select-modal
ref="avaUserTreeSelect"
title="選擇可見範圍"
:project-id="currentProjectId"
:visible.sync="avaUserModalVisible"
@ok="editAvailableUser"
/>
或者
<div class="user" ref="user">dd</div>
// $refs
showManagerModal () {
this.$refs.avaUserTreeSelect.showModal(this.form.managers)
console.log(this.$refs.user.text)
},
在Vue3.2版本使用的方式
//普通Dom
<div class="user" ref="user"></div>
//組件
<batch-adjust-department-modal ref="batchAdjustDepartmentRef" />
<script setup>
import { ref } from 'vue';
// modal調整部門彈層Dom
const batchAdjustDepartmentRef = ref(null);
const user = ref(null);
</script>
也許這里有人疑問,為什么聲明了一個和template的ref中同名的常量變量就綁定了對應的dom? 在這里再補充說明一下:
Vue3 在早期版本( 3.0.0-beta.21 之前)中對 composition api 的支持,只能在組件選項 setup
函數中使用。而相應式的變量都是通過在setup()方法中return {寫入需要在模版中使用的變量或方法}
<script>
import { defineComponent, ref } from 'vue'
export default defineComponent({
name: 'HelloWorld',
setup(props, ctx) {
const count = ref(0)
function add() {
count.value++
}
// 使用return {} 把變量、方法暴露給模板
return {
count,
add,
}
},
})
</script>
在 3.0.0-beta.21 版本中增加了 <script setup>
的實驗特性。如果使用了,會提示 <script setup>
還處在實驗特性階段。
在 3.2.0 版本中移除 <script setup>
的實驗狀態,從此,宣告 <script setup>
正式轉正使用,成為框架穩定的特性之一
與組件選項 setup
函數對比, <script setup>
我們只需要寫更少、更簡潔的代碼,不需要使用 return {}
暴露變量和方法了,使用組件時不需要主動注冊了,會自動幫你綁定
所以在<script setup>
中聲明的變量會自動被加到該Vue對象的本身this中,如
<script setup> | <script> |
---|---|
const user = ref(null); | this.$ref.user |
Ref操作組件Dom和父子組件單向傳遞
props父傳子,子通過emits傳父,這樣單方向傳遞,在控制彈層組件的顯示和隱藏方面也可以實現,但是如此一來,我們就會像下面一樣 父組件
<template>
<exchange-valid-modal-vue v-model:visible="visibleExchange" />
</template>
<script setup>
// 轉讓管理員組件
import ExchangeValidModalVue from './modal/ExchangeValidModal.vue';
// modal彈層
const visibleExchange = ref(false); // 轉讓管理員可視化
const onExchangeAdmin = () => {
visibleExchange.value = true;
};
</script>
子組件ExchangeValidModalVue.vue
<template>
<t-dialog
v-model:visible="visibleExchange"
header="轉讓主管理員"
attach="body"
width="384px"
:confirm-on-enter="true"
:on-close="onCloseExchange"
/>
</template>
<script setup>
const visibleExchange = ref(false);
const props = defineProps({
data: {
type: Object,
default: () => {},
},
visible: {
type: Boolean,
default: false,
},
});
watch(
() => props.visible,
(cur, pre) => {
visibleExchange.value = cur;
if (cur) {
firstTag.value = 1;
}
},
);
watch(
() => visibleExchange.value,
(cur, pre) => {
emits('update:visible', cur);
},
);
</script>
從代碼里面我們就可以發現通過用父子組件單向傳遞的方式去實現一個組件的顯示和隱藏功能,我們需要如此費勁地聲明多個變量,還要做兩次監聽,萬一后面不止一個這樣的參數進行傳遞,那么代碼量可想而知,而且也不易維護。
其實顯示和隱藏的功能可以直接在內部中進行值的響應即可,并不需要在父級別中操作,如下將上面代碼改變一下:
子組件ExchangeValidModalVue.vue
<template>
<t-dialog
v-model:visible="visible"
header="轉讓主管理員"
attach="body"
width="384px"
:confirm-on-enter="true"
:on-close="onCloseExchange"
/>
</template>
<script setup>
import { ref } from 'vue';
const visible = ref(false);
const emits = defineEmits(['call']);
const onEmitSelectSuperiod = () => { // 省略
emits('call');
};
const onOpen = () => {
visible.value = true;
};
const onClose = () => {
visible.value = false;
};
defineExpose({
onOpen,
onClose,
});
</script>
那么在父組件中,我們只需要通過ref得到該組件Dom,然后操作Dom內部的方法即可;
如:父組件改寫
<template>
<exchange-valid-modal-vue ref="exchangeRef" />
</template>
<script setup>
// 轉讓管理員組件
import ExchangeValidModalVue from './modal/ExchangeValidModal.vue';
// modal彈層
const exchangeRef = ref(null); // 轉讓管理員可視化
const onExchangeOpen = () => {
exchangeRef.onOpen() // 直接操作dom里defineExpose暴露出來的方法
};
</script>
如此,是不是比父子單向數據傳遞的方式更加高效易用?當然上面所說的只是我舉的一個例子,當后續需要在組件內擴展功能也可按類似的方法代替單向數據流的方式擴展
但,請注意;這種操作dom方式,并不是什么場景下都是最佳的選擇;我們可以分情況選擇,比如當一些數據只需要在子組件的范疇中實現,而不需要父組件外加干涉的情況下,選擇ref操作dom更為高效;
補充知識點:
defineExpose
在 Vue3.2 中,默認不會暴露任何在 <script setup>
中聲明的綁定,即不能通過模板 ref
獲取到組件實例聲明的綁定。
Vue3.2 提供了 defineExpose
編譯器宏,可以顯式地暴露需要暴露的組件中聲明的變量和方法。
“Ref操作Dom在Vue2.x和Vue3.x的不同點有哪些”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。