從Vue2升級Vue3過程中遇到作用域插槽語法變更問題的解決方法
更新時間:2026年02月12日 09:53:32 作者:愛看星星的豬_
在將項目從 Vue 2 升級到 Vue 3 的過程中,遇到了兩處典型的兼容性問題,主要涉及 作用域插槽語法變更 和 響應(yīng)式數(shù)據(jù)類型處理差異,本文通過具體代碼示例,說明問題原因、Vue 版本機制差異,并給出推薦改法,需要的朋友可以參考下
一、問題代碼片段及功能說明
場景 1:表格中動態(tài)字段的樣式與標(biāo)題控制(輸入框)
<!-- Vue 2 原始寫法 -->
<template slot-scope="scope">
<el-input-number
:class="{ 'text-red': originTableDataCopy[scope.$index]['EXT_FIELD' + (firstChidIndex + 1)]?.split('?')[1] !== 'null' }"
:title="originTableDataCopy[scope.$index]['EXT_FIELD' + (firstChidIndex + 1)]?.split('?')[1] || ''"
v-model="scope.row['EXT_FIELD' + (firstChidIndex + 1)]"
/>
</template>功能說明:
- 根據(jù)字段值是否包含
?error形式的后綴(如"100?超限"),決定是否顯示紅色樣式; title顯示錯誤信息(即?后的內(nèi)容);- 使用
v-model雙向綁定當(dāng)前行的擴展字段。
場景 2:更復(fù)雜的動態(tài)字段名與條件渲染
<!-- Vue 2 原始寫法 -->
<template slot-scope="scope">
<el-input-number
:class="{ 'text-red':
loanAccounttype === 'issued' &&
originTableDataCopy[scope.$index]['EXT_FIELD.' + firstChid.functFldEnNm + (index + 1)]?.split('?')[1] &&
originTableDataCopy[scope.$index]['EXT_FIELD.' + firstChid.functFldEnNm + (index + 1)]?.split('?')[1] !== 'null'
}"
v-model="scope.row['EXT_FIELD.' + firstChid.functFldEnNm + (index + 1)]"
v-if="!secondChid.name?.includes('參考值')"
/>
<span v-else>{{ scope.row['REF_VALUE_0'] }}...</span>
</template>功能說明:
- 字段名由多個變量拼接生成(如
EXT_FIELD.income1); - 僅當(dāng)
loanAccounttype === 'issued'且字段包含非'null'錯誤信息時,標(biāo)紅; - 若字段為“參考值”,則不顯示輸入框,改用文本展示。
二、Vue 2 與 Vue 3 的機制差異
| 維度 | Vue 2 | Vue 3 |
|---|---|---|
| 作用域插槽語法 | <template slot-scope="scope"> | <template #default="{ row, $index }"> |
| 插槽參數(shù) | scope 是對象,含 row, $index 等屬性 | 直接解構(gòu) { row, $index },$index 仍可用但非必須 |
$index 是否存在 | ? 存在 | ? 存在(作為默認(rèn)屬性),但不再通過 scope.$index 訪問 |
| 響應(yīng)式代理方式 | Object.defineProperty + __ob__ | Proxy 包裝,控制臺顯示為 Proxy(Array) |
| 數(shù)據(jù)訪問建議 | 可通過 data[index] 或 scope.row | 強烈推薦直接使用 row,避免依賴外部數(shù)組索引 |
關(guān)鍵變化:
Vue 3 中 slot-scope 已廢棄,且雖然 $index 仍可解構(gòu)使用,但只要用不到索引,就不應(yīng)引入。更重要的是,row 就是當(dāng)前行的真實引用,等價于 originTableDataCopy[$index],且更安全。
三、遷移后的正確寫法(Vue 3 兼容)
改造原則:
- 使用
#default="{ row }"替代slot-scope="scope" - 用
row['xxx']替代originTableDataCopy[scope.$index]['xxx'] - 添加
typeof ... === 'string'防御性判斷,避免.split()報錯
示例:場景 2 的 Vue 3 安全寫法
<template #default="{ row }">
<el-input-number
type="number"
:controls="false"
:class="{
'text-red':
loanAccounttype === 'issued' &&
typeof row['EXT_FIELD.' + firstChid.functFldEnNm + (index + 1)] === 'string' &&
row['EXT_FIELD.' + firstChid.functFldEnNm + (index + 1)].split('?')[1] &&
row['EXT_FIELD.' + firstChid.functFldEnNm + (index + 1)].split('?')[1] !== 'null'
}"
:title="
loanAccounttype === 'issued' &&
typeof row['EXT_FIELD.' + firstChid.functFldEnNm + (index + 1)] === 'string' &&
row['EXT_FIELD.' + firstChid.functFldEnNm + (index + 1)].split('?')[1]
? row['EXT_FIELD.' + firstChid.functFldEnNm + (index + 1)].split('?')[1]
: ''
"
v-model="row['EXT_FIELD.' + firstChid.functFldEnNm + (index + 1)]"
v-if="originTableDataCopy.length > 0 && editable && !secondChid.name?.includes('參考值')"
/>
<el-input-number
v-else-if="!secondChid.name?.includes('參考值')"
type="number"
:controls="false"
v-model="row['EXT_FIELD.' + firstChid.functFldEnNm + (index + 1)]"
/>
<span class="text-red" v-else>
{{
row['REF_VALUE_0'] +
(secondChid.twolvlClsf?.includes('輕度') ? '1' :
secondChid.twolvlClsf?.includes('中度') ? '2' : '3')
}}
</span>
</template>關(guān)鍵改進:
- 移除 scope.$index,使用 row 直接訪問;
- 添加 typeof ... === 'string' 防止 .split() 在非字符串上調(diào)用;
- 保留業(yè)務(wù)邏輯不變,提升健壯性。
四、總結(jié)與最佳實踐
| 問題類型 | Vue 2 寫法 | Vue 3 推薦寫法 | 原因 |
|---|---|---|---|
| 作用域插槽 | slot-scope="scope" | #default="{ row }" | 語法標(biāo)準(zhǔn)化,更簡潔 |
| 行數(shù)據(jù)訪問 | originTableDataCopy[scope.$index] | row | 更安全,避免索引錯位 |
| 類型安全 | 無防御 | typeof val === 'string' | 防止 .split() 在 number/null 上調(diào)用 |
| 布爾表達式 | cond ? true : false | 直接用 cond | 冗余,JS 表達式本身即布爾值 |
最佳實踐建議:
- 永遠優(yōu)先使用
row而非data[index]:它更可靠,不受數(shù)組變更影響; - 對
.split(),.replace()等字符串方法做類型檢查; - 避免
JSON.parse(JSON.stringify())深拷貝,改用structuredClone或{...}+map; - 按需解構(gòu)插槽參數(shù):不用
$index就不要寫它。
以上就是從Vue2升級Vue3過程中遇到作用域插槽語法變更問題的解決方法的詳細內(nèi)容,更多關(guān)于Vue2升級Vue3作用域插槽語法變更的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
iview實現(xiàn)動態(tài)表單和自定義驗證時間段重疊
這篇文章主要介紹了iview實現(xiàn)動態(tài)表單和自定義驗證時間段重疊,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
vue實現(xiàn)拖拽的簡單案例 不超出可視區(qū)域
這篇文章主要為大家詳細介紹了vue實現(xiàn)拖拽的簡單案例,不超出可視區(qū)域,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-07-07

