去年vue還沒有升級為2.0點時候,建立了這個庫,並且寫了幾篇簡單的入門教程。發現也有一些朋友都拿這個collection來入門vue,在去年10月份vue升級2.0版本後,我一直沒時間來升級這個collection。現在終於有一整塊時間來做升級。藉助這幾個demo來感受如何從vue1.x升級vue2.x。我新建了vue2.x分支,所有的升級改動都將提交到這個分支中。
package版本升級
-
vue:
^1.0.0
to^2.2.1
-
vue-resource:
^0.7.4
to^1.3.1
-
vue-router:
^0.7.13
to2.5.2
-
vuex:
^0.6.3
to2.3.1
-
webpack:
^1.12.2
to2.2.0
看完版本升級對比,感覺我都是拿著“古董”寫的vue1.x版本的demo。vue全家桶+webpack全部有了重要的更新。前端生態就是這樣子,半年不去更新,世界都換了個樣子。
工程升級
本次升級全部基於vue-demo-collection
下的demo進行升級。一定還有升級中沒有接觸到的點,這裡不去深入。
webpack1.x升級2.x
webpack1.x和2.x最大的變化是module.loaders
變成了module.rules
以下是vue-cli
工具建立的vue1.x模版與vue2.x模版webpack配置檔案module
程式碼塊對比。
不妨自己嘗試一下,通過執行下面命令。找到工程目錄中的webpack.conf.js對比一下。
vue init webpack-simple@1.0 vue1.x
vue init webpack-simple vue2.x
對比發現:
-
modules.loaders
變為modules.rules
-
vue
loaders變為vue-loader
-
babel
loaders變為babel-loader
module: {
- loaders: [
+ rules: [
{
test: /.vue$/,
- loader: `vue`
+ loader: `vue-loader`,
+ options: {
+ loaders: {
+ }
+ // other vue-loader options go here
+ }
},
{
test: /.js$/,
- loader: `babel`,
+ loader: `babel-loader`,
exclude: /node_modules/
},
{
test: /.(png|jpg|gif|svg)$/,
loader: `url`,
query: {
limit: 10000,
loader: `file-loader`,
options: {
name: `[name].[ext]?[hash]`
}
}
]
},
vue1.x升級2.x
vue2.x
入口檔案
從升級入口檔案main.js
開始,Vue2.x的入口檔案和Vue1.x相比,Vue例項帶有router和store選項。
-
router
配置引數注入路由,從而整個應用都有路由功能; -
store
配置引數注入store到根例項,從而根元件下所有子元件都可以訪問store。
// 簡單的main.js
import Vue from `vue`
import VueResource from `vue-resource`
import App from `./App.vue`
Vue.use(VueResource)
new Vue({
el: `#app`,
render: h => h(App)
})
// 帶有vue-router和vuex的main.js
import Vue from `vue`
import VueRouter from `vue-router`
import routes from `./routes`
import App from `./App.vue`
import store from `./vuex/store`
// Vue.config.devtools = true
Vue.use(VueRouter)
const router = new VueRouter({
scrollBehavior: () => ({ y: 0 }),
routes
})
// Start up our app
const app = new Vue({
router,
store,
...App
})
app.$mount("#root")
$Index
和$key
在vue2.x中已經被棄用,代替寫法為:
<li v-for="(value, key, index) in objs" ></li>
vue2.2.0+
版本在元件使用v-for
指令到時候需要指定key
,這點和react
類似。
vuex2.x
首先看兩張圖:
vuex1.0資料流閉環
vuex2.0資料流閉環
-
vuex中的store選項,從
App
元件,移動到入口檔案main.js
,在建立Vue例項的時候通過store物件提供給store
選項。
const app = new Vue({
store,
...App
})
app.$mount("#root")
-
vue2.x中去掉了
$remove
方法,使用splice
方法代替。
state.cart.splice(state.cart.indexOf(cartInfo), 1)
-
action中
dispatch
變為commit
,實踐中會用到ES6解構來簡化程式碼。
actions: {
increment ({ commit }) {
commit(`increment`)
}
}
我對action中commit方法做了統一優化,用統一的函式處理commit。
import * as types from `./mutation-types`
const makeAction = (type) => {
return ({ commit }, ...args) => commit(type, ...args)
}
export const changePrice = makeAction(types.CHANGE_PRICE)
export const changeStyle = makeAction(types.CHANGE_STYLE)
export const addItem = makeAction(types.ADD_ITEM)
export const removeItem = makeAction(types.REMOVE_ITEM)
-
善用元件繫結的輔助函式
vuex2.x給開發者帶來另一個福利,多了map*系列的輔助函式:
mapState - 建立元件的計算屬性返回 Vuex store 中的狀態
mapGetters - 建立元件的計算屬性返回 getter 的返回值。
mapActions - 建立元件方法分發 action。
mapMutations - 建立元件方法提交 mutation。
vue-router2.x
vue-router2.x中,路由初始化時,在建立Vue例項的時候需要傳入router配置向整個應用注入路由功能。
const app = new Vue({
router,
...App
})
app.$mount("#root")
vue-router2.x中,router.map
替換為router
例項裡的一個routes選項陣列。
import Index from `./components/Index.vue`
import Cart from `./components/Cart.vue`
// Route config
export default [
{
path: `/`,
name: `Home`,
component: Index
},
{
path: `/index`,
name: `Index`,
component: Index
},
{
path: `/cart`,
name: `Cart`,
component: Cart
},
{
path: `*`,
redirect: `/`
}
]
v-link
指令已經被一個新的<router-link>
元件指令替代。
<router-link class="navbar-brand" :to="{ path: `/` }">Shopping Cart</router-link>