在Vue項目里管理彈窗組件是用ref還是用props詳解
在 Vue 項目里管理彈窗組件:用 ref 還是用 props?
在做業(yè)務后臺時,頁面上常常會有很多彈窗:新增、編輯、詳情、排班表……這些彈窗如果直接寫在頁面里,很快就會把父組件擠爆,于是我們會想到“抽成子組件”。但這時往往會遇到一個問題:父組件到底該用 ref 調子組件方法,還是用 props + 事件 來控制子組件?這篇文章就圍繞這個問題,把我們剛才討論過的內容系統(tǒng)梳理一下。
兩種常見的控制方式
1. 用 props + 事件 控制子組件(推薦)
思路:
- 父組件通過 props 把“狀態(tài)”傳給子組件(例如:是否可見、當前模式、需要編輯的行數(shù)據(jù)等)。
- 子組件通過 事件 告訴父組件“我保存好了”“我關閉了”,父組件再決定要不要刷新列表等。
父組件負責的狀態(tài)(示例):
- 列表 & 查詢相關
- 當前頁、每頁條數(shù)、篩選條件等。
- 和彈窗有關的最小狀態(tài)
- 某個編輯彈窗當前是否顯示(例如:編輯彈窗的 visible 布爾值)。
- 編輯模式(新增 / 編輯)。
- 當前被編輯的這一行數(shù)據(jù)(或它的 id)。
子組件負責的狀態(tài):
- 表單字段對象。
- 校驗規(guī)則。
- 彈窗里的 loading 狀態(tài)。
- 內部下拉列表、內部接口請求等。
優(yōu)點:
- 單向數(shù)據(jù)流清晰:父組件的數(shù)據(jù)流向子組件,子組件通過事件“回報”結果。
- 職責邊界清楚:父管“業(yè)務流程”,子管“彈窗內部細節(jié)”。
- 高度可復用:這個彈窗子組件以后可以在很多父組件里復用,只要把必要的數(shù)據(jù)通過 props 給它。
- 遷移到 Vue 3 更順暢:這種模式正是 Vue 3 推薦的,遷移時只需要把語法細節(jié)稍微調整一下(比如變成 v-model:visible、用 defineEmits 等)。
可以把這種模式理解為:> 父組件不“命令”子組件做事,而是“給它數(shù)據(jù) + 監(jiān)聽它發(fā)出的事件”。
2. 用 $refs.xxx.xxx() 直接調用子組件方法
思路:
- 父組件給子組件一個 ref 名,比如 groupEdit。
- 父組件在需要時,通過 this.$refs.groupEdit.open('edit', row) 之類的方式,直接調用子組件的方法,來打開彈窗、注入數(shù)據(jù)。
父組件負責的內容:
- 仍然要記住子組件對外暴露的 API,例如:open(mode, row)。
- 需要維護正確的 ref 名稱,并保證子組件提供了對應方法。
子組件負責的內容:
- 定義若干供父組件調用的方法,比如 open、close、reset 等。
- 在這些方法里再去設置自身的 visible、表單數(shù)據(jù)等內部狀態(tài)。
優(yōu)點:
- 用起來直觀:一眼就知道“調用這個函數(shù)就會打開彈窗”,讀起來像是“調用組件的 API”,容易理解。
- 當這個彈窗 只在一個地方用 時,這種方式在短期內也能“夠用”。
缺點:
- 耦合度高:
- 父組件必須知道子組件的 ref 名字。
- 父組件必須知道子組件有哪些公共方法,以及這些方法的參數(shù)簽名。
- 不便于復用:
- 在別的頁面復用這個彈窗時,也不得不按同樣的辦法注冊 ref,調用同名方法。
- 不夠 Vue 化:
- Vue 更鼓勵“數(shù)據(jù) + 事件”的聲明式方式,而不是處處用 ref 去命令式調用。
Vue 3 遷移視角下的比較
如果你將來準備把項目慢慢升級到 Vue 3,或者用 Composition API /
props + 事件 在 Vue 3 的表現(xiàn)
- Vue 3 官方依然推薦:
- 父傳子:通過 props / v-model。
- 子傳父:通過 emit 事件。
- 遷移時,只需要:
- 把 .sync 寫法變成 v-model:xxx。
- 在子組件里用 defineProps、defineEmits 等新語法替代老的 props / this.$emit 寫法。
核心思想不變,只是“換一層語法皮”。這意味著:今天用 props + 事件 管子組件,將來改 Vue 3 時,不用推翻設計,只是重寫語法。
$refs 調子組件方法在 Vue 3 的表現(xiàn)
- 傳統(tǒng) Options API 下 $refs 依然可以用。
- 但如果你改用
- 這樣一來:
- 子組件要加“暴露 API”的聲明;
- 父組件仍要通過 ref 調用這些方法;
- 一旦你多次重構組件結構,容易出“小坑”。
也就是說:這種以 $refs 為中心的方式,在 Vue 3 里不能說用不了,但和新的組合式風格有點“別扭”,遷移時需要額外適配。
當頁面上有“很多彈窗”時該怎么設計
現(xiàn)實業(yè)務中,一個頁面上可能有:
- 新增班組彈窗
- 編輯班組彈窗
- 排班表彈窗
- 詳情彈窗
- 審核意見彈窗
- …
如果所有彈窗的表單、校驗、loading、內部狀態(tài),統(tǒng)統(tǒng)塞到父組件的 data 里,父組件會非常臃腫,而且很多狀態(tài)和“列表主流程”并沒有直接關系。一個比較健康的拆分策略是:
父組件只維護“與業(yè)務流程相關的最小狀態(tài)”
例如:
- 當前激活的是哪個彈窗:
- 某個 bool:例如編輯彈窗的 visible。
- 彈窗模式:新增 / 編輯。
- 當前作用的業(yè)務對象:
- 比如當前選中的一行數(shù)據(jù),或當前的業(yè)務 id。
所有這些數(shù)據(jù)都直接體現(xiàn)“頁面業(yè)務流程”:比如“我要新增一個班組”,“我要編輯這行班組”,“我要查看這個班組的排班表”。
子組件維護“彈窗內部的一切細節(jié)”
例如:
- 表單字段。
- 校驗規(guī)則。
- 內部 loading。
- 內部下拉選項、接口請求邏輯。
- 內部的 UI 結構。
這樣,即使頁面上有很多彈窗:
- 父組件只是多了一些簡單的“狀態(tài)標志 + 當前對象”。
- 復雜的邏輯都被封裝在一個個相對獨立的子組件里。
無論你最終選擇 props + 事件 還是 $refs,這個拆分邊界是更重要的設計點。
什么時候更適合用 props + 事件
可以優(yōu)先選用這一套的場景:
- 你希望:
- 組件可復用。
- 以后升級 Vue 3、改 Composition API 時成本低。
- 團隊代碼風格更偏聲明式、數(shù)據(jù)驅動。
- 一個彈窗可能會在多個頁面被復用,例如:
- 公共的“選擇用戶”彈窗。
- 多處使用的“編輯班組”彈窗等。
- 你想要更清晰的邊界:父組件描述“業(yè)務流程”,子組件只管“具體表現(xiàn)和交互”。
總結成一句話:> 只要不是非常臨時的一次性組件,props + 事件 一般都是更穩(wěn)妥的首選方案。
什么時候 $refs 也可以接受
盡管不推薦作為默認選擇,但在一些情況下,$refs 也是可以使用的:
- 這個彈窗 只會在當前頁面里使用,沒有復用需求。
- 你很希望有一個“像函數(shù)一樣”的入口,比如:
- 在某個復雜流程中,需要多次、不同參數(shù)地調用子組件的能力。
- 調用鏈比較長時,用 $refs.xxx.open(param) 比一層層傳 props 來得更好讀。
- 團隊內部對 $refs 的用法有統(tǒng)一約定:
- 比如統(tǒng)一所有側滑彈窗子組件都對外提供 open(row) 方法。
- 這樣即使用 $refs,也還算規(guī)范。
哪怕如此,也建議:
- 不要在一個組件里到處用 $refs 驅動邏輯。
- 盡量將 $refs 使用場景局限在“少數(shù)真正需要命令式行為”的地方。
總結:實際項目里的推薦組合
綜合上面所有點,可以給出一個比較落地的建議組合:
- 通用彈窗 / 表單組件:
- 用 props + 事件 管理;
- 父組件保持最小狀態(tài),子組件封裝內部邏輯;
- 為未來遷移 Vue 3 做好準備。
- 特殊場景、強命令式的東西(少數(shù)):
- 可以用 $refs + 子組件暴露少量方法;
- 但要克制使用,并在團隊內達成共識。
如果你現(xiàn)在正在重構一個老頁面、抽離一堆彈窗組件,一個實用的操作順序是:
- 先盡量用 props + 事件 把復雜表單彈窗都抽出去。
- 只有在確實“很不方便”時,再為某個子組件補一個 open() 形式的 API,配合 $refs 使用。
這樣既能兼顧當前開發(fā)效率,也不會把未來的維護成本提前埋雷。
總結
到此這篇關于在Vue項目里管理彈窗組件是用ref還是用props的文章就介紹到這了,更多相關Vue用ref還是props內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
詳解Vue3.0中ElementPlus<input輸入框自動獲取焦點>
這篇文章主要給大家介紹了關于Vue3.0中ElementPlus<input輸入框自動獲取焦點>的相關資料,文中通過實例代碼介紹的非常詳細,對大家學習或者使用vue3.0具有一定的參考學習價值,需要的朋友可以參考下2023-04-04
npm安裝vue腳手架報錯警告npm WARN deprecated
安裝vue腳手架報錯可能具體原因比較多,可以根據(jù)報錯信息進行排查,本文主要介紹了npm安裝vue腳手架報錯警告npm WARN deprecated,感興趣的可以了解一下2023-11-11
vue中v-cloak解決刷新或者加載出現(xiàn)閃爍問題(顯示變量)
這篇文章主要介紹了vue中v-cloak解決刷新或者加載出現(xiàn)閃爍問題(顯示變量) ,需要的朋友可以參考下2018-04-04
vue動態(tài)綁定多個類名方法詳解(:class動態(tài)綁定多個類名)
vue中可以通過:class=""這樣來根據(jù)一定的條件來動態(tài)添加class,但是有時候需要判斷的條件比較多,需要動態(tài)添加的class也比較多,下面這篇文章主要給大家介紹了關于vue動態(tài)綁定多個類名(:class動態(tài)綁定多個類名)的相關資料,需要的朋友可以參考下2022-11-11

