溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Ref操作Dom在Vue2.x和Vue3.x的不同點(diǎn)有哪些

發(fā)布時(shí)間:2023-01-31 11:31:27 來源:億速云 閱讀:132 作者:iii 欄目:編程語言

本篇內(nèi)容介紹了“Ref操作Dom在Vue2.x和Vue3.x的不同點(diǎn)有哪些”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

在開發(fā)一個(gè)項(xiàng)目之前,我們往往都是先做下需求分析,針對(duì)前端而言,就是可以調(diào)研或者選擇一個(gè)基礎(chǔ)組件庫,來提高我們的工作效率。畢竟,對(duì)比較計(jì)較時(shí)間成本的公司來說,不會(huì)給你拿看電視劇玩游戲的時(shí)間去專門開發(fā)一個(gè)類似日歷的組件。但在市面上的組件庫,并不能都能滿足我們的需求。這個(gè)時(shí)候,我們就需要自己手寫組件,來應(yīng)用到項(xiàng)目中。

而這就是我想說的: 如何設(shè)計(jì)組件,讓其既能易于應(yīng)用(或者說減少代碼量),又能提高擴(kuò)展性,方便需求變更和后續(xù)維護(hù)?

可以有很多種方式,而利用Ref操作Dom的特性隨是其中之一,但這個(gè)方式卻讓我們?cè)诰S護(hù)和操作Modal、Popup以及頻繁操作Dom顯示和隱藏交互的組件的時(shí)候,卻發(fā)揮得很大優(yōu)勢。

就對(duì)Ref操作Dom的相關(guān)知識(shí)點(diǎn)以及應(yīng)用實(shí)例分幾個(gè)方面來做下剖析

  • Ref獲取Dom的本質(zhì)

  • Ref操作Dom在Vue2.x和Vue3.x的不同

  • Ref操作組件Dom和父子組件單向傳遞對(duì)比

詳說

Ref獲取Dom的本質(zhì)

Vue2.x中Vue的對(duì)象屬性$refs,其實(shí)就是所有注冊(cè)過的ref的一個(gè)集合,而ref對(duì)應(yīng)著template模版中,不同組件或普通Dom元素上關(guān)聯(lián)的ref="xx"; 源碼中ref的實(shí)際獲取方式也是通過原生方式getElementById而得到的Dom節(jié)點(diǎn);可以說ref是document.getElementById的語法糖。vue3的ref延續(xù)了vue2的用法,還增加了一個(gè)作用就是創(chuàng)建響應(yīng)式數(shù)據(jù)

也許有人會(huì)問了,既然ref和getElementById都能獲取到Dom,那么在項(xiàng)目開發(fā)中,我選擇哪種方式都沒什么區(qū)別呢?

關(guān)于這個(gè)問題,經(jīng)過數(shù)據(jù)表明,$refs相對(duì)document.getElementById的方法,會(huì)減少獲取dom節(jié)點(diǎn)的消耗;而具體原因,等下一篇文章再詳細(xì)探討。

Ref操作Dom在Vue2.x和Vue3.x的不同

Vue2.x

我們只需要在相應(yīng)的Dom元素或者組件加上ref="xx"屬性,然后在Vue對(duì)象中使用this.$refs.xx,就可以直接獲取到該Dom并操作其方法屬性,

<user-and-dep-tree-select-modal
  ref="avaUserTreeSelect"
  title="選擇可見範(fàn)圍"
  :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

在Vue3.2版本使用的方式

//普通Dom
<div class="user" ref="user"></div>
//組件
<batch-adjust-department-modal ref="batchAdjustDepartmentRef" />
<script setup>
import { ref } from 'vue';
// modal調(diào)整部門彈層Dom
const batchAdjustDepartmentRef = ref(null);
const user = ref(null);
</script>

也許這里有人疑問,為什么聲明了一個(gè)和template的ref中同名的常量變量就綁定了對(duì)應(yīng)的dom? 在這里再補(bǔ)充說明一下:

  • Vue3 在早期版本( 3.0.0-beta.21 之前)中對(duì) composition api 的支持,只能在組件選項(xiàng) setup 函數(shù)中使用。而相應(yīng)式的變量都是通過在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> 的實(shí)驗(yàn)特性。如果使用了,會(huì)提示 <script setup> 還處在實(shí)驗(yàn)特性階段。

  • 在 3.2.0 版本中移除 <script setup> 的實(shí)驗(yàn)狀態(tài),從此,宣告 <script setup> 正式轉(zhuǎn)正使用,成為框架穩(wěn)定的特性之一 與組件選項(xiàng) setup 函數(shù)對(duì)比, <script setup> 我們只需要寫更少、更簡潔的代碼,不需要使用 return {} 暴露變量和方法了,使用組件時(shí)不需要主動(dòng)注冊(cè)了,會(huì)自動(dòng)幫你綁定

所以在<script setup>中聲明的變量會(huì)自動(dòng)被加到該Vue對(duì)象的本身this中,如

<script setup><script>
const user = ref(null);this.$ref.user

Ref操作組件Dom和父子組件單向傳遞

props父傳子,子通過emits傳父,這樣單方向傳遞,在控制彈層組件的顯示和隱藏方面也可以實(shí)現(xiàn),但是如此一來,我們就會(huì)像下面一樣 父組件

<template>
  <exchange-valid-modal-vue v-model:visible="visibleExchange" />
</template>
<script setup>
// 轉(zhuǎn)讓管理員組件
import ExchangeValidModalVue from './modal/ExchangeValidModal.vue';
// modal彈層
const visibleExchange = ref(false); // 轉(zhuǎn)讓管理員可視化
const onExchangeAdmin = () => {
  visibleExchange.value = true;
};
</script>

子組件ExchangeValidModalVue.vue

<template>
    <t-dialog
      v-model:visible="visibleExchange"
      header="轉(zhuǎn)讓主管理員"
      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>

從代碼里面我們就可以發(fā)現(xiàn)通過用父子組件單向傳遞的方式去實(shí)現(xiàn)一個(gè)組件的顯示和隱藏功能,我們需要如此費(fèi)勁地聲明多個(gè)變量,還要做兩次監(jiān)聽,萬一后面不止一個(gè)這樣的參數(shù)進(jìn)行傳遞,那么代碼量可想而知,而且也不易維護(hù)。

其實(shí)顯示和隱藏的功能可以直接在內(nèi)部中進(jìn)行值的響應(yīng)即可,并不需要在父級(jí)別中操作,如下將上面代碼改變一下:

子組件ExchangeValidModalVue.vue

<template>
    <t-dialog
      v-model:visible="visible"
      header="轉(zhuǎn)讓主管理員"
      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內(nèi)部的方法即可;

如:父組件改寫

<template>
  <exchange-valid-modal-vue ref="exchangeRef" />
</template>
<script setup>
// 轉(zhuǎn)讓管理員組件
import ExchangeValidModalVue from './modal/ExchangeValidModal.vue';
// modal彈層
const exchangeRef = ref(null); // 轉(zhuǎn)讓管理員可視化
const onExchangeOpen = () => {
   exchangeRef.onOpen() // 直接操作dom里defineExpose暴露出來的方法
};
</script>

如此,是不是比父子單向數(shù)據(jù)傳遞的方式更加高效易用?當(dāng)然上面所說的只是我舉的一個(gè)例子,當(dāng)后續(xù)需要在組件內(nèi)擴(kuò)展功能也可按類似的方法代替單向數(shù)據(jù)流的方式擴(kuò)展

但,請(qǐng)注意;這種操作dom方式,并不是什么場景下都是最佳的選擇;我們可以分情況選擇,比如當(dāng)一些數(shù)據(jù)只需要在子組件的范疇中實(shí)現(xiàn),而不需要父組件外加干涉的情況下,選擇ref操作dom更為高效;

補(bǔ)充知識(shí)點(diǎn):

defineExpose

在 Vue3.2 中,默認(rèn)不會(huì)暴露任何在 <script setup> 中聲明的綁定,即不能通過模板 ref 獲取到組件實(shí)例聲明的綁定。

Vue3.2 提供了 defineExpose 編譯器宏,可以顯式地暴露需要暴露的組件中聲明的變量和方法。

“Ref操作Dom在Vue2.x和Vue3.x的不同點(diǎn)有哪些”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI