摘要:前言這節(jié)凈是些嘮叨,只想看升級(jí)的可直接跳過(guò)。在不久之前,如約發(fā)布了版本。正如計(jì)劃之初,博客的版本也將升級(jí)到。升級(jí)之旅首先,升級(jí)依賴。那該怎么做哪再一次谷哥和查閱文檔,然而一無(wú)所獲。返回的是整個(gè)項(xiàng)目路由的實(shí)例,它是只讀的。
Troubleshooting of upgrading Vue from 1.0 to 2.0
前言系列文章:
Vue 2.0 升(cai)級(jí)(keng)之旅 (本文)
Vuex — The core of Vue application
從單頁(yè)應(yīng)用(SPA)到服務(wù)器渲染(SSR)
本文不包含 Vue 2.0 所有新特性,如 SSR 等,本文并沒(méi)有涉及,本文只包含 個(gè)人博客項(xiàng)目 升級(jí)中所遇到的經(jīng)驗(yàn)分享,如有興趣,可以查看 Vue 2.0 changes log。
這節(jié)凈是些嘮叨,只想看升(tian)級(jí)(keng)的可直接跳過(guò)。
從去年年底開(kāi)始寫博客,那時(shí)對(duì)怎么搞個(gè)博客網(wǎng)站一竅不通,看別人用 Github Pages 寫博客挺贊的,就也想搞個(gè)玩玩。技術(shù)選型時(shí),在 jekyll 和 hexo 中選擇了前者,或許你會(huì)問(wèn)為什么?估計(jì)當(dāng)時(shí)大腦的供氧量不足了吧...
于是,我的博客就這么誕生了。(jekyll 版的博客已經(jīng)廢棄了,如果你有興趣,可以查看之前的提交)
可是,用久了就發(fā)現(xiàn)并不怎么好用,雖然支持 markdown,可代碼塊要轉(zhuǎn)換成 highlighter 標(biāo)簽;其次,主題模板是挺好看,可換成中文字雜就那么別扭哪;還有,對(duì) jekyll 的模板又不熟,自定義也不方便。
年初有一天,突然想到自己也是搞技術(shù)的,為啥不自己搭一個(gè)博客網(wǎng)站哪?對(duì),順帶還能學(xué)學(xué)新技術(shù),何樂(lè)而不為。又到了技術(shù)選型的時(shí)候了,這次擺在我面前又有 2 個(gè)選擇,React 和 Vue,這次我選擇了后者。
Why?因?yàn)椋笳吒p量級(jí),也更貼近我熟悉的 Angular 的語(yǔ)法,還有,那時(shí)網(wǎng)上就有說(shuō)今年 4 月 Vue 會(huì)升級(jí)到 2.0 和 Vue 兼具 React 和 Angular 的優(yōu)點(diǎn)等等。(好吧,老實(shí)說(shuō),不選 React 只是因?yàn)椴幌矚g JSX 而已。-_-||)
So,我就用 Vue 1.10+ 搭建了自己的新博客——Disciple.Ding Blog(點(diǎn)這里看源碼),并漸漸地往里添加一些新學(xué)到的東西,ES6, webpack, docker 等,并在 DAOcloud 上發(fā)布了。(免費(fèi)用了人家那么久的服務(wù),在這里做個(gè)硬廣也是應(yīng)該的,DAOcloud 的確很好用,特別和 Github 綁定之后能自動(dòng)構(gòu)建,應(yīng)用更新也及其簡(jiǎn)單,只是有個(gè)缺點(diǎn)就是有帶寬限制。)
在不久之前,Vue 如約發(fā)布了 2.0 版本。正如計(jì)劃之初,博客 Vue 的版本也將升級(jí)到 2.0。
說(shuō)了那么多,再不進(jìn)入正題就要變成標(biāo)題黨了。好,那就開(kāi)始我們的升(cai)級(jí)(keng)之旅。
升(tian)級(jí)(keng)之旅首先,升級(jí)依賴。
npm install vue@next vue-router@next --saveimport vue
順利安裝完成并按 changelog 做了修改之后,啟動(dòng)項(xiàng)目也正常,當(dāng)我興致勃勃地打開(kāi) Browser,駕輕就熟地輸入 localhost,并自然而然地按下 Enter,一切水到渠成。
然而,迎接我的竟是一片白板,控制臺(tái)里赫然映著一串紅字。
[Vue warn] : You are using the runtime-only build of Vue where the template option is not available. Either pre-compile the templates into render functions, or use the compiler-included build. (found in root instance)
What? template 選項(xiàng)不能用了,changelog 沒(méi)提到???但 vue-router 的例子中都在用啊,什么鬼?甚至我將代碼全部替換成例子中的代碼依舊無(wú)法運(yùn)行,但在 vue-router 項(xiàng)目里就能跑,什么鬼??!
但是,我并不妥協(xié),分別打斷點(diǎn)運(yùn)行,發(fā)現(xiàn)兩者竟然跑的不是同一段代碼,納尼!
import vue from "vue"
同樣的 import 語(yǔ)句,卻有不一樣的結(jié)果,vue-router 中引的是 vue.js,而在我的項(xiàng)目中引的竟然是 vue.common.js...common...mon...n...
為什么會(huì)引 vue.common.js,from "vue" 不該引的是 vue.js 么?這就要引入另一個(gè)知識(shí)點(diǎn):package.json。
package.json 中的 main 屬性決定了,當(dāng)項(xiàng)目被引入時(shí),輸出的是哪個(gè)文件,而 vue 的 package.json 中的 main 指向的是 dist/vue.common.js。
福利時(shí)間:推薦一個(gè)網(wǎng)站 json.is,它對(duì) package.json 里的每條屬性都有詳細(xì)的解釋。
找到了問(wèn)題產(chǎn)生的原因,那么解決也就輕而易舉了。
import vue from "vue/dist/vue.js"
每次引用 vue 的時(shí)候都要寫那么長(zhǎng),一點(diǎn)都不優(yōu)雅,而且為什么 vue-router 的例子可以用???
我要一探究竟。確認(rèn)了 vue-router 中依賴的 vue 的 package.json 文件中的 main 字段指向的也是 dist/vue.common.js。那就只有一個(gè)可能了,webpack 對(duì)引入做了處理,查看 webpack.config.js
module.exports = { // 省略... resolve: { alias: { "vue": "vue/dist/vue.js" } }, ...
果然啊~他用 webpack 的別名功能把 vue/dist/vue.js 命名成了 vue,防不勝防。
在自己項(xiàng)目的 wepack.config.js 里同樣給 vue 起別名,這樣就又能愉快地使用 import vue from "vue" 了。
你是不是以為這樣就結(jié)束了?不,對(duì)待一個(gè)問(wèn)題要刨根問(wèn)底,不能不求甚解。
為什么 vue 默認(rèn)導(dǎo)出的是 vue.common.js,它和 vue.js 的區(qū)別在哪里,又有什么關(guān)系?
這個(gè)問(wèn)題在囧克斯的博客中有提到。
Vue 最早會(huì)打包生成三個(gè)文件,一個(gè)是 runtime only 的文件 vue.common.js,一個(gè)是 compiler only 的文件 compiler.js,一個(gè)是 runtime + compiler 的文件 vue.js。
也就是說(shuō),vue.js = vue.common.js + compiler.js,而如果要使用 template 這個(gè)屬性的話就一定要用 compiler.js,那么,引入 vue.js 是最恰當(dāng)?shù)摹?/p> 路由升級(jí)
vue-router 的升級(jí)并不困難,參照 Releases Note 上的注釋修改應(yīng)該沒(méi)有什么大問(wèn)題,主要的變化有兩點(diǎn):
路由配置從一系列的方法調(diào)用,變成了傳遞一個(gè)配置對(duì)象
原先的 v-link 指令,變成了 router-link Component,路徑指向用 to 屬性
正當(dāng)你以為會(huì)一路順風(fēng)順?biāo)?,輕松升級(jí)路由完成的時(shí)候,現(xiàn)實(shí)總會(huì)給你當(dāng)頭一棒。
之前博客的 vue-router 中使用了 beforeEach 和 afterEach 方法,根據(jù) Release Note
router.beforeEach (replaced by the beforeEach option)
router.afterEach (replaced by the afterEach option)
行,那我把它改到配置里
const ROUTER_SETTING = { routes: [ // 省略... ], beforeEach: () => { /* some function */ }, afterEach: () => { /* some function */ } }
But, not work. What"s wrong?
難道我哪里寫錯(cuò)了?又經(jīng)過(guò)我一番谷哥和查閱文檔之后,發(fā)現(xiàn)在下一個(gè)版本的 Release Note 中有這么一段
beforeEach and afterEach are reverted as router instance methods (options removed). This makes it more convenient for plugins/modules to add hooks after the router instance has been created.
好吧,它又被恢復(fù)回路由實(shí)例的方法了。那么,改回去
const router = new VueRouter(ROUTER_SETTING); router .beforeEach(() => { /* some function */ }) .afterEach(() => { /* some function */ });
OK,這樣總好了吧。然而,并沒(méi)有...console 中報(bào)出無(wú)法從 undefined 中讀取 afterEach,好吧,我猜這應(yīng)該是 beforeEach 中沒(méi)有像之前一樣返回路由對(duì)象,所以不能鏈?zhǔn)秸{(diào)用。
class VueRouter { // 省略... beforeEach (fn: Function) { this.beforeHooks.push(fn) } afterEach (fn: Function) { this.afterHooks.push(fn) } // 省略... }
看一眼源碼,果然如此。
那再將之前的代碼稍作修改就可以了。
const router = new VueRouter(ROUTER_SETTING); router.beforeEach(() => { /* some function */ }); router.afterEach(() => { /* some function */ });
不過(guò),不能鏈?zhǔn)秸{(diào)用似乎沒(méi)之前的優(yōu)雅了哪~
最后,提一下 vue-router 2.0 里所有的 hook(就像之前的 beforeEach, afterEach,以及每個(gè)路由狀態(tài)中的 beforeEnter, beforeRouteLeave等)都具有相同的參數(shù)簽名,這在 Release Note 中也有提到。
fn (toRoute, redirect, next) { // toRoute: {Object} 當(dāng)前路由對(duì)象 // redirect: {Function} 調(diào)用跳轉(zhuǎn)至另一路由 // next: {Function} 調(diào)用繼續(xù)當(dāng)前路由跳轉(zhuǎn) // 什么都不做,則取消當(dāng)前跳轉(zhuǎn) }
路由升級(jí)完成后,如果控制臺(tái)沒(méi)有什么報(bào)錯(cuò),那么,路由可以相互切換了,那些不依賴數(shù)據(jù)讀取的組件已經(jīng)可以正常顯示了。
那些依賴數(shù)據(jù)讀取的組件哪?
這就要提到組件的生命周期鉤子(即 lifecycle hooks)。
Lifecycle hooks生命周期鉤子應(yīng)該算 vue 這次升級(jí)中 broken changes 最多的一部分了,對(duì)照 1.0 的文檔和 release note,作了下面這張表
vue 1.0+ | vue 2.0 | Description |
---|---|---|
init | beforeCreate | 組件實(shí)例剛被創(chuàng)建,組件屬性計(jì)算之前,如 data 屬性等 |
created | created | 組件實(shí)例創(chuàng)建完成,屬性已綁定,但 DOM 還未生成,$el 屬性還不存在 |
beforeCompile | beforeMount | 模板編譯/掛載之前 |
compiled | mounted | 模板編譯/掛載之后 |
ready | mounted | 模板編譯/掛載之后(不保證組件已在 document 中) |
- | beforeUpdate | 組件更新之前 |
- | updated | 組件更新之后 |
- | activated | for keep-alive,組件被激活時(shí)調(diào)用 |
- | deactivated | for keep-alive,組件被移除時(shí)調(diào)用 |
attached | - | 不用了還說(shuō)啥哪... |
detached | - | 那就不說(shuō)了吧... |
beforeDestory | beforeDestory | 組件銷毀前調(diào)用 |
destoryed | destoryed | 組件銷毀后調(diào)用 |
知道了 hooks 升級(jí)前后的對(duì)應(yīng)關(guān)系,那么升級(jí)起來(lái)就輕而易舉了,改改組件的屬性名就可以了。
那么,改完屬性名是不是就完成了?然而并沒(méi)有。
因?yàn)椋?vue 1.0+ 中,如果一個(gè)組件和路由相關(guān),那么,它就可能不單單有自己組件的 lifecycle hooks,它還會(huì)有基于 vue-router 的 lifecycle hooks。
而在 vue 2.0 中,router lifecycle hooks 全部被移除了,因?yàn)?,這些 hooks 可以通過(guò)其他的方式來(lái)代替,這樣不但簡(jiǎn)化了配置,還不用在組件中去處理路由相關(guān)的業(yè)務(wù),降低了耦合。那這些 hooks 該如何替換,我們接下來(lái)就來(lái)看一下。
activate & deactivate:使用組件自身的 lifecycle hook 替代
data:通過(guò)組件 watch 屬性來(lái)監(jiān)聽(tīng)當(dāng)前路由 $route 的變化
canActivate:由路由屬性 beforeEnter 來(lái)代替
canDeactivate:由路由屬性 beforeRouteLeave 來(lái)代替
canReuse:去除
那個(gè)這個(gè)是不是也直接改改屬性名就好了哪?
恩,差不多。不過(guò)需要注意的是,如果原先 hooks 中使用了有關(guān)路由信息的 transition 參數(shù)是肯定不能用了。比如,根據(jù)路由參數(shù)來(lái)進(jìn)行查詢,原先通過(guò) transition.to.params 獲取路由參數(shù),現(xiàn)在就要通過(guò)剛剛提到的當(dāng)前路由對(duì)象 this.$route.params 來(lái)獲取。
在升級(jí)這里的過(guò)程中,還遇到一個(gè)問(wèn)題:當(dāng)用戶輸入的 URL 滿足路由匹配,但根據(jù)路由參數(shù)無(wú)法獲得正確的文章時(shí),我想讓路由直接跳轉(zhuǎn)到首頁(yè)。
在 1.0 版本中,我通過(guò) transition.redirect("/"); 就輕松的回到了首頁(yè),由于 2.0 中沒(méi)有 transition 參數(shù),而 $route 只包含當(dāng)前路由的信息,并不包換路由切換的操作。那該怎么做哪?再一次谷哥和查閱文檔,然而一無(wú)所獲。
最后在 vue-router 的例子中找到了解決問(wèn)題的鑰匙——$router。
$router 返回的是整個(gè)項(xiàng)目路由的實(shí)例,它是只讀的。于是,剛剛那個(gè)問(wèn)題就可以通過(guò) this.$router.replace("/"); 來(lái)解決。
這里還有一點(diǎn),在 1.0 版本中組件配置 route 屬性時(shí)還可以設(shè)置一個(gè)叫 waitForData 的屬性。這個(gè)在 2.0 中,我還沒(méi)有找到直接的替換方式,不過(guò),我在整個(gè)組件上添加 v-if 來(lái)處理。從理論和效果的角度上講,v-if 是可以替代原先的 waitForData 屬性,就似乎不那么優(yōu)雅。
剩余其他小點(diǎn),看控制臺(tái)報(bào)錯(cuò)信息,然后查查 Release Note 都能輕松處理啦~
寫在最后至此,我的整個(gè) Blog 也升級(jí)完成了,歡迎來(lái)訪。(查看源碼戳這里)
如果現(xiàn)在再讓我選一個(gè)技術(shù)來(lái)搭博客的話,我會(huì)選 React。為啥?
因?yàn)?vue 我已經(jīng)玩過(guò)啦,哈哈哈~
最后,借用外國(guó)網(wǎng)友的一句話:
I"m constantly rewriting / refactoring this silly little blog using the latest and buzziest tech, so that I can stay up to date on these libraries and frameworks.
這也是我自己搭博客,而不是直接使用博客系統(tǒng)的主要原因。
最后的最后,安利下自己的 Blog,以及 Source Code。
歡迎交流,噴子繞道。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/87845.html
摘要:個(gè)人看來(lái),一個(gè)狀態(tài)管理的應(yīng)用,無(wú)論是使用,還是,最困難的部分是在的設(shè)計(jì)。中,并沒(méi)有移除,而是改為用于觸發(fā)。也是一個(gè)對(duì)象,用于注冊(cè),每個(gè)都是一個(gè)用于返回一部分的。接受一個(gè)數(shù)組或?qū)ο?,根?jù)相應(yīng)的值將對(duì)應(yīng)的綁定到組件上。 系列文章: Vue 2.0 升(cai)級(jí)(keng)之旅 Vuex — The core of Vue application (本文) 從單頁(yè)應(yīng)用(SPA)到服務(wù)器...
摘要:最近在用寫一個(gè)命令行游戲升級(jí)版植物大戰(zhàn)僵尸,順便鞏固一下編程技巧。目前版已經(jīng)在上發(fā)布,這是鏈接。我想在一開(kāi)始盡量簡(jiǎn)化游戲,所以用了一個(gè)一維數(shù)組我想先不管陽(yáng)光的問(wèn)題,用一個(gè)類實(shí)現(xiàn)基礎(chǔ)的植物大戰(zhàn)僵尸角色的功能。 最近在用python寫一個(gè)命令行游戲:升(jian)級(jí)(hua)版植物大戰(zhàn)僵尸,順便鞏固一下python編程技巧。在這個(gè)過(guò)程中,也收獲(cai)了不少樂(lè)趣(keng)。目前1.0版...
摘要:本來(lái)寫這個(gè)項(xiàng)目時(shí)就沒(méi)打算來(lái)自己實(shí)現(xiàn)富文本編輯器,本著能用開(kāi)源就用開(kāi)源的原則,在項(xiàng)目里測(cè)試了一些開(kāi)源的編輯器,發(fā)現(xiàn)或多或少都有些問(wèn)題,后來(lái)一琢磨,反正這個(gè)項(xiàng)目的富文本編輯器需求不復(fù)雜,就自己實(shí)現(xiàn)一個(gè)好了。 斷斷續(xù)續(xù)寫了個(gè)把月,終于在昨天完成了第一版… 筆落寫作 一款幫助網(wǎng)絡(luò)寫手更方便地進(jìn)行小說(shuō)創(chuàng)作的PC軟件,目前支持 OSX/Windows 名字靈感來(lái)自于杜甫的一首詩(shī),前兩句是: 《寄...
摘要:認(rèn)識(shí)組件組件是強(qiáng)大的功能之一。注意,所有的組件同時(shí)也都是的實(shí)例,可接受相同的選項(xiàng)對(duì)象。組件全局注冊(cè)時(shí)通過(guò)方式注冊(cè)??紤]到會(huì)出現(xiàn)禁止使用的場(chǎng)景,需要禁止和啟用組件的功能,所以需要。同樣也是先在子組件的選項(xiàng)中定義好傳遞過(guò)來(lái)的數(shù)據(jù)。 前言 Vue.js是一套構(gòu)建用戶界面的漸進(jìn)式框架(官方說(shuō)明)。通俗點(diǎn)來(lái)說(shuō),Vue.js是一個(gè)輕量級(jí)的,易上手易使用的,便捷,靈活性強(qiáng)的前端MVVM框架。簡(jiǎn)潔的A...
閱讀 2775·2023-04-25 14:15
閱讀 2712·2021-11-04 16:11
閱讀 3402·2021-10-14 09:42
閱讀 452·2019-08-30 15:52
閱讀 2833·2019-08-30 14:03
閱讀 3554·2019-08-30 13:00
閱讀 2119·2019-08-26 11:40
閱讀 3317·2019-08-26 10:25