去年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>