vue,vuex,vue-router放在一起能做什么?不用webpack之類的打包工具使用他們是否可行?各位道友在初學vue時是否有這樣的困惑。因為現代構建前端項目的一般模式是:
- 安裝webapck,某種是glup,grunt,或者是fis等構建工具
- 然后安裝一個包管理器,npm,bower,或者說是新一代:yarn
- 再然后用 包管理器 安裝各種各樣的包,如:vue,bootstrap,vuex等。
- 其后用es6的import或者是node的require引入包
- 最后通過 構建工具 打包或發布項目
在這個過程中你是否發現開發者越來越依賴構建工具,你是否想過構建工具幫助我們解決了很多問題,但他也讓你不能快速的感知和了解庫或者框架的本質。這次就簡單點,用vue,vuex,vue-router,但不用webpack做一個示例,主要目的皆在了解這些庫的本質,或者說是是基礎應用。
你能看到的知識點
- vue-router的簡單應用,包含:基礎配置路由配置,子路由。
- vuex的應用,包含:多組件共享同一份數據。
- vue組件生命周期的理解。
代碼結構圖

- form,comp,life通過路由導航到組件
- comp中compA和compB是通過子路由導航到組件
- inputComp + comboComp實現一個輸入數據動態反映到其他組件的示例
- lifeUpdate:主要測試組件生命周期中的beforeUpdate勾子
- compB:展示了inputComp輸入的數據,皆在展示vuex的能力
- lifeList:測試組件完全生命周期,但不包含beforeUpdate和updatedg兩個勾子
示例展示

本示例利用vue-router做為導航,其中結合了vue和vuex相關知識,如果你想單獨了解其中的某一個庫,可訪問vue原來可以這樣上手和vuex原來可以這樣上手這兩個鏈接。如果你還想和我們一起討論前端技術,可以加入本人創建的QQ群,群號在左側。單擊下載示例源碼
重點介紹
以下截取的都是代碼片斷,或者是減少后的代碼,只表其意。如需要看完整的還是下載示例源碼看吧。
vue-router介紹
js代碼:
var routeropt = [ { path: '', component: form }, { path: '/form', component: form}, { path: '/comp', component: comp, children:[ { path: '', component: compA }, { path: 'compA', component: compA }, { path: 'compB', component: compB } ]}, { path: '/life', component: compLife } ]; var router = new VueRouter({ routes: routeropt });
html代碼:
<div id="app"> <ul class="nav nav-tabs"> <li><router-link to="/form">選擇下拉列表</router-link></li> <li><router-link to="/comp">子組件路由</router-link></li> <li><router-link to="/life">生命周期</router-link></li> </ul> <router-view></router-view> </div>
說明:
- 注冊路由和子路由很簡單,注冊子路由只需在路由中增加children數組即可,如/comp下就注冊了兩個子路由。
- router-view是顯示路由導航的組件內容,他可以用name屬性指定具體要顯示的某個組件。
vuex的多組件引用
- vuex的store中的state定義了list集合,以及對list集合的相關getter,actions,muations等。
var state = { list: [{"id":1, "name": "001"}] }; var mutations = { ADDITEM: function(argState, item){ argState.list.push(item); } }; var getters = { getList:function(argState){ return argState.list; } } var actions = { addItem:function(dis,item){ dis.commit('ADDITEM',item); } }
- 在inputComp中通過$store.dispatch來觸發actions中addItem方法,用於向list添加一條數據
createElement('button',{
on:{
"click": function(event){
self.$store.dispatch('addItem',{"id":2,"name": self.value});
}
},
- ComboComp和compB組件中通過訪問getters獲取list的數據
comboComp組件中的代碼:
createElement("ul",
{
class:{
"dropdown-menu":true
},
attrs:{
"aria-labelledby":"dr02"
}
}, self.$store.getters["getList"].map(function(item){
return createElement("li",item.name);
}))
compB組件中的代碼:
computed: { list: function(){ return this.$store.getters.getList; } }
vue組件的生命周期介紹
- compLife實現生命周期的勾子,lifeList顯示生命周期的執行過程。
- beforeRouteEnter和beforeCreate在執行時,組件實例還沒有創建完成,所以用next和nextTick來執行日志輸出
- beforeRouteEneter,beforeRouteUpdate,beforeRouteLeave等是vue-router增加的勾子
- 沒有展示beforeUpdate和updated勾子
beforeCreate: function(){ var self = this, obj = {eventId: index++, eventName: 'beforeCreate--nextTick'}; this.$nextTick(function(){ self.addItem(obj); }); }, created: function(){ this.addItem({eventId: index++, eventName: 'created-----------------------'}); this.title = '生命周期'; }, beforeMount: function(){ this.addItem({eventId: index++, eventName: 'beforeMount'}); }, mounted: function(){ this.addItem({eventId: index++, eventName: 'mounted'}); }, activated: function(){ //keep-alive激活時 this.addItem({eventId: index++, eventName: 'activated'}); }, deactivated: function(){ this.addItem({eventId: index++, eventName: 'deactivated'}); }, beforeDestroy: function(){ this.addItem({eventId: index++, eventName: 'beforeDestroy'}); }, destroyed: function(){ this.addItem({eventId: index++, eventName: 'destroyed'}); }, beforeRouteEnter: function(to, from, next){ var obj = {eventId: index++, eventName: 'router: beforeRouteEnter--nextTick'}; next(function(vm){ vm.addItem(obj); }) }, beforeRouteUpdate: function(to, from, next){// 路由修改時 V2.2 this.addItem({eventId: index++, eventName: 'router: beforeRouteUpdate'}); next(true); }, beforeRouteLeave: function(to, from, next){ //路由離開當前組件時 this.addItem({eventId: index++, eventName: 'router: beforeRouteLeave'}); next(true); }
- beforeUpdate和updated的展示
- beforeUpdate是最一次更新數據的機會,且不會導致重復渲染,但在beforeUpdate中修改 $store,或者是通過$emit改變非本組件的內容,並導致了VNODE的改變,都會引起重復渲染(死循環)。
- updated中數據時不能影響VNODE的改變,否則會導致重復渲染(死循環)
- 示例代碼在lifeUpdate組件中,代碼如下:
beforeUpdate: function(){ //最后一次修改渲染到DOM上數據的機會,不會導致重復執行渲染,而updated中修改狀態會導致重復渲染 //但在beforeUpdate中修改 $store,或者是$emit 來通知改變非本組件的VNODE,都會導致重復渲染 this.msg = '我不導致重復渲染'; }
