拒絕gogocode亩进,vue2升級(jí)vue3症虑,看這里

聲明

請(qǐng)注意,筆者在寫本文時(shí)归薛,已經(jīng)完成了升級(jí)改造工作谍憔,故部分錯(cuò)誤可能無法通過截圖呈現(xiàn)匪蝙,不過筆者會(huì)盡可能用語(yǔ)言描述清楚

一次失敗的嘗試

由于所要改造項(xiàng)目是公司運(yùn)行六七年的老項(xiàng)目了,內(nèi)容之大之重可以想象习贫,純靠人力的話逛球,光是想想就頭大

所謂遇事不決先百度,像這類遷移工具必定是有人已經(jīng)做過了的沈条,于是發(fā)現(xiàn)了gogocode

首先需忿,使用npm安裝該工具

npm install gogocode-cli -g

接著進(jìn)行語(yǔ)法轉(zhuǎn)換

在項(xiàng)目根目錄執(zhí)行如下命令

// src是要轉(zhuǎn)換的源
gogocode -s ./src -t gogocode-plugin-vue -o ./src-out

然后靜靜等待它轉(zhuǎn)換完成

image.png

下一步诅炉,對(duì)相關(guān)依賴做升級(jí)蜡歹,gogocode也提供了相關(guān)指令

gogocode -s package.json -t gogocode-plugin-vue -o package.json

這一步執(zhí)行之后,使用yarn重新安裝依賴

yarn

這樣工具幫我們處理的工作就完成了涕烧,我們先來跑一下lint看看月而,如下有3k+

image.png

此時(shí),我已經(jīng)有點(diǎn)打退堂鼓了

先不急议纯,咱們先來看看它轉(zhuǎn)出來的效果

首先父款,它對(duì)package.json轉(zhuǎn)換后,vue的版本是3.0.0瞻凤。我為什么要特意強(qiáng)調(diào)這個(gè)呢憨攒?

因?yàn)檫@說明了兩個(gè)問題:

1.現(xiàn)在vue3.3了,它卻還在用3.0阀参,這說明大概率它已經(jīng)鮮有維護(hù)更新了

2.3.3的語(yǔ)法與3.0大概率會(huì)存在出入肝集,也就是說,它的轉(zhuǎn)換結(jié)果未必可信

現(xiàn)在蛛壳,我們?cè)賮砜淳唧w的sfc文件的轉(zhuǎn)換

  • props

我們知道杏瞻,vue3.3props已經(jīng)被扁平化了,是不需要通過特定的props屬性進(jìn)行傳遞的衙荐,但gogocode對(duì)這一部分并未處理

image.png
  • attrs

attrs也有類似的問題

image.png
  • style樣式

工具對(duì)源碼轉(zhuǎn)換后捞挥,會(huì)導(dǎo)致style標(biāo)簽內(nèi)的樣式錯(cuò)亂,具體來說應(yīng)該是它無法識(shí)別css代碼中的注釋導(dǎo)致的

  • 格式

除了上述的語(yǔ)法轉(zhuǎn)換問題外忧吟,還有其他的砌函,此處不再一一闡述。其實(shí)真正讓我決定放棄的是溜族,它轉(zhuǎn)換出來感覺有點(diǎn)亂讹俊,且對(duì)源碼的侵入性太大

比如eventBus,修改后斩祭,無法和原來一樣調(diào)用劣像,需要先導(dǎo)入,再使用摧玫,且必須手動(dòng)傳入組件實(shí)例耳奕,偽代碼如下

import {$on,$emit,$off} from '../xx/utils'

$on(instance,key,callback)

這成功給筆者造成了將近一千個(gè)error绑青,因?yàn)轫?xiàng)目里用到了400多次

image.png

具體來說,每一個(gè)文件都會(huì)觸發(fā)相對(duì)路徑必須在絕對(duì)路徑之后引入變量未被使用這兩個(gè)error

半自動(dòng)化

現(xiàn)在屋群,筆者打算自己手動(dòng)修正闸婴。不過在開始前,先說原則芍躏,原則就是邪乍,能不修改原來代碼的就盡量不修改,能保證原有調(diào)用格式的就盡量保證原來的使用方式

loaders

一些通用的調(diào)整对竣,可以通過webpackloader來自動(dòng)化

  • filters

vue3中已經(jīng)剔除了filters選項(xiàng)庇楞,需要將其移動(dòng)到methods

image.png

不過,代碼有點(diǎn)多否纬,咱這文章畢竟也不是賣錢的小冊(cè)吕晌,所以就只講一下思路,這也是最重要的:

首先临燃,通過正則提取出script標(biāo)簽的內(nèi)容部分睛驳,然后將其ast化,在通過節(jié)點(diǎn)樹找到export default部分并將其提取出來轉(zhuǎn)換成對(duì)象

轉(zhuǎn)對(duì)象的時(shí)候膜廊,由于部分代碼可能是export default外部的乏沸,比如

const yyy = 'spp'
export default {
    data(){
        return xxx:yyy
    }
}

這部分直接去解析會(huì)報(bào)錯(cuò),因此需要進(jìn)行try...catch并在捕獲到錯(cuò)誤時(shí)遞歸

function parse(){
    try{
        ...
    }catch(err){
        if(err){
            parse()
        }
    }
}

接著判斷對(duì)象中是否存在filters屬性爪瓜,如果有蹬跃,就對(duì)該屬性做遍歷,將其key提取到methods中钥勋,形式大概是這樣

export default {
    methods:{
        filtersKey:filtersValue
    }
}

這個(gè)filtersValue對(duì)應(yīng)的就是原來的過濾函數(shù)炬转,要把它生成到script標(biāo)簽中,具體來說算灸,是import語(yǔ)句和export之間

function filtersValue(){
    ...
}

下一步扼劈,就是去template模板中查找使用過濾函數(shù)的地方進(jìn)行替換。這利用正則可以很輕松的完成

image.png
  • props

vue2中可以這樣聲明props

export default {
    props:{
        xxx:'some value'
    }
}

vue3中會(huì)報(bào)錯(cuò)菲驴。因此需要對(duì)此進(jìn)行轉(zhuǎn)換荐吵。具體來說,就是找到props對(duì)象赊瞬,分別對(duì)它的key對(duì)應(yīng)的值進(jìn)行識(shí)別先煎。如果是對(duì)象或函數(shù)則不處理,如果是基本數(shù)據(jù)類型巧涧,則轉(zhuǎn)換成如下形式

{
    type:'原值所對(duì)應(yīng)的數(shù)據(jù)類型',
    default:'some value'
}

這里比較容易出錯(cuò)的點(diǎn)是關(guān)于字符串類型的獲取薯蝎,需要手動(dòng)拼接上引號(hào)

image.png

完整代碼如下

image.png
  • bus通信

眾所周知,vue3中已經(jīng)剔除了eventBus谤绳,無法再通過new實(shí)例的方式來實(shí)現(xiàn)跨級(jí)通信

但第三方插件又無法保證this指向占锯,一般需要手動(dòng)傳入

但前文我們說過袒哥,要盡可能保證原調(diào)用方式不變

因此,需要在loader中提取并添加

image.png

這里的注意點(diǎn)在于loader的執(zhí)行時(shí)機(jī)消略,必須要保證它在源代碼被轉(zhuǎn)換之前堡称。否則添加的this與回調(diào)函數(shù)內(nèi)的this大概率不是一個(gè)。如下艺演,是經(jīng)過轉(zhuǎn)換后的代碼却紧,在回調(diào)中使用的this其實(shí)并不是實(shí)際傳入的this

var this1 = this
this.$bus.$on(key,this,()=>{
    this1.xxx = 'spp'
})

fixed

還有一些是可以在全局去做兼容的,它們的目的是與改造前的代碼行為盡可能保持一致

  • bus通信

在前文loader中雖然解決了eventBus的this指向問題胎撤,但還沒有找到可替代的包

幸運(yùn)的是晓殊,筆者在之前實(shí)現(xiàn)的web-localstorage-plus中實(shí)現(xiàn)了該功能

首先,使用web-localstorage-plus提供的接口來代替bus功能

image.png

接著將其掛載到app.config.globalProperties上哩照,這是vue3中提供的類似Vue.prototype掛載方式

image.png

又不幸的是挺物,web-localstorage-plus目前其實(shí)并不支持接收this參數(shù),且回調(diào)函數(shù)也不支持傳遞多個(gè)參數(shù)

因此飘弧,還需要對(duì)這兩個(gè)接口進(jìn)行重寫。如下砚著,接受參數(shù)二并將其掛載到第三個(gè)函數(shù)參數(shù)上次伶,然后在觸發(fā)on注冊(cè)的監(jiān)聽函數(shù)時(shí)手動(dòng)使用call修改其this指向,并將參數(shù)使用展開運(yùn)算符傳遞以支持多個(gè)參數(shù)傳遞

image.png
  • vue-router

在筆者的業(yè)務(wù)中稽穆,對(duì)單點(diǎn)登錄進(jìn)行了校驗(yàn)冠王,并在無權(quán)限時(shí)跳轉(zhuǎn)到指定的頁(yè)面,偽代碼如下

// 獲取權(quán)限
this.$router.onReady(...)
// 校驗(yàn)權(quán)限
this.$router.beforeEach(...)

這兩行代碼有兩個(gè)問題

一個(gè)是vue-router4.x中已經(jīng)廢棄了onReady舌镶,需要改成isReady代替

image.png

另一個(gè)問題是柱彻,當(dāng)頁(yè)面刷新或執(zhí)行window.open時(shí),其表現(xiàn)與vue-router3.x不一致

vue-router3.x中刷新并不會(huì)觸發(fā)beforeEach鉤子餐胀,但vue-router4.x中會(huì)觸發(fā)

這就導(dǎo)致哟楷,會(huì)觸發(fā)權(quán)限的重新獲取,而此時(shí)beforeEach鉤子執(zhí)行時(shí)還拿不到權(quán)限數(shù)據(jù)導(dǎo)致跳轉(zhuǎn)到noAuth頁(yè)面

因此否灾,需要對(duì)beforeEach鉤子進(jìn)行重寫卖擅。如下,我們?cè)陧?yè)面刷新或window.open被執(zhí)行時(shí)向本地設(shè)置緩存墨技,并在beforeEach鉤子中判斷是否存在緩存標(biāo)記惩阶,存在則什么都不做,否則正常跳轉(zhuǎn)路由

image.png
  • $children

vue3中已經(jīng)剔除了$children接口扣汪,需要自己手動(dòng)實(shí)現(xiàn)一份查找邏輯断楷。如下,只需要按指定的格式進(jìn)行遞歸即可

image.png
  • $filters

對(duì)于注冊(cè)的全局過濾器崭别,現(xiàn)在統(tǒng)一調(diào)整到app.config.globalProperties

image.png
  • view-ui-plus

之前默認(rèn)注冊(cè)到全局的loading現(xiàn)在已經(jīng)沒有了冬筒,需要根據(jù)業(yè)務(wù)需求做調(diào)整

image.png

其他

剩下的统刮,就是需要手動(dòng)調(diào)整的其他語(yǔ)法了

  • vue-router

1-h函數(shù)

vue4.x版本中應(yīng)該已經(jīng)不支持render函數(shù)了,由于筆者公司項(xiàng)目有且僅有這一處對(duì)組件的使用账千,故修改成了默認(rèn)方式

image.png

實(shí)際上侥蒙,更準(zhǔn)確的寫法應(yīng)該是這樣

image.png

2-注冊(cè)方式

4.x中已經(jīng)不需要使用new關(guān)鍵字了,取而代之的是createRouter接口匀奏。另外鞭衩,mode屬性也被history替代了

import { createRouter, createWebHashHistory } from 'vue-router';
export default createRouter({
  history: createWebHashHistory(),
  routes:[...]
})
  • vuex

1-注冊(cè)方式

vue-router類似,通過createStore替換娃善。

import { createStore } from 'vuex';
export default createStore({...})

2-日志引入

它的日志插件的導(dǎo)入方式要改成下邊這樣

import { createLogger } from 'vuex';
  • view-ui-plus

對(duì)于js模塊中使用的消息提示需要手動(dòng)按需導(dǎo)入

import { Message } from 'view-ui-plus'

Message.error('...')
  • h函數(shù)

h函數(shù)的變動(dòng)大致有四個(gè)

1-props與attrs

現(xiàn)在不需要在顯示的指定這兩個(gè)屬性了论衍,可以直接平鋪傳遞

h('div',{
  //props:{
  //  xxx:'spp'
  //}
  xxx:'spp'
})

2-事件綁定

現(xiàn)在也已經(jīng)剔除了on屬性,而需要改成onEventType的形式

h('div',{
  //on:{
  //  click:()=>{}
  //}
  onClick(){}
})

3-slots

插槽需要改成函數(shù)形式

h('div',{
    //slot:'slotName'
    slotName(){}
})

4-組件渲染

現(xiàn)在使用h函數(shù)渲染組件有兩種方式聚磺,筆者采用的方式如下

首先將要導(dǎo)入的組件掛載到全局

import { LoadingBar } from 'view-ui-plus';

app.component('LoadingBar', LoadingBar);

然后借助vue3提供的resolveComponent來執(zhí)行導(dǎo)入

import { resolveComponent } from 'vue';
h(resolveComponent('LoadingBar'))
  • $set

基于proxyv3已經(jīng)不需要$set或$delete了坯台,現(xiàn)在直接進(jìn)行修改即可

  • slot

v3中的插件必須使用template,且寫法有變更瘫寝,如下蜒蕾,現(xiàn)在可以合寫成一個(gè)了

<template 
  //slot="createTime" 
  //slot-scope="scope"
  v-slot="scope"
>
  ...
</template>
  • 三方組件庫(kù)

這種每個(gè)人的不一樣,筆者就不貼了焕阿,只說下筆者的處理方式

1-找vue3版本

有些組件庫(kù)是支持vue3版本的咪啡,這部分直接yarn即可

2-修改源碼

如果沒有v3版本,就利用patch-pkg自己修改源碼做兼容

3-copy源碼

對(duì)于比較復(fù)雜的庫(kù)暮屡,筆者是找到其源代碼copy了一份撤摸,然后在項(xiàng)目中引入并修改

  • vue-loader

項(xiàng)目啟動(dòng)后,頁(yè)面元素之間的間隙會(huì)失效褒纲,配置如下

image.png

測(cè)試問題修復(fù)

  • vue-router傳參

4.x已經(jīng)不支持傳遞對(duì)象形式了

image.png

因?yàn)槟玫降氖亲址家模⑶疫@個(gè)字符串還沒法通過JSON.parse進(jìn)行解析

image.png

但是又沒法一個(gè)一個(gè)調(diào)整莺掠,畢竟有一百多處都在使用

image.png

所以還是老規(guī)矩衫嵌,從源碼修改汁蝶。這只需要分兩步

第一步,重寫push

image.png

第二步,重寫query屬性

image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市慰枕,隨后出現(xiàn)的幾起案子具则,更是在濱河造成了極大的恐慌,老刑警劉巖具帮,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件博肋,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蜂厅,警方通過查閱死者的電腦和手機(jī)匪凡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掘猿,“玉大人病游,你說我怎么就攤上這事〕硗ǎ” “怎么了衬衬?”我有些...
    開封第一講書人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)采记。 經(jīng)常有香客問我佣耐,道長(zhǎng),這世上最難降的妖魔是什么唧龄? 我笑而不...
    開封第一講書人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮奸远,結(jié)果婚禮上既棺,老公的妹妹穿的比我還像新娘。我一直安慰自己懒叛,他們只是感情好丸冕,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著薛窥,像睡著了一般胖烛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上诅迷,一...
    開封第一講書人閱讀 51,190評(píng)論 1 299
  • 那天佩番,我揣著相機(jī)與錄音,去河邊找鬼罢杉。 笑死趟畏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的滩租。 我是一名探鬼主播赋秀,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼利朵,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了猎莲?” 一聲冷哼從身側(cè)響起绍弟,我...
    開封第一講書人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎著洼,沒想到半個(gè)月后樟遣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡郭脂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年年碘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片展鸡。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡屿衅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出莹弊,到底是詐尸還是另有隱情涤久,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布忍弛,位于F島的核電站响迂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏细疚。R本人自食惡果不足惜蔗彤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望疯兼。 院中可真熱鬧然遏,春花似錦、人聲如沸吧彪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)姨裸。三九已至秧倾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間傀缩,已是汗流浹背那先。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留扑毡,地道東北人胃榕。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親勋又。 傳聞我的和親對(duì)象是個(gè)殘疾皇子苦掘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容