Vue全家桶 + webpack 构建单页应用初体验
文章指南
主題
? 承接這上一篇Vue + Webpack 構建模塊化開發框架詳解,我們知道了如何使用webpack對vue進行打包,從而開始我們的前端模塊化開發之路,這一篇在上一篇的基礎上講解 Vue全家桶(vue+vuex+vue-router+axios) + webpack 構建一個單頁應用Demo
前提
? 閱讀本篇內容之前,除了需要掌握上一篇內容中的前提部分的知識,還需要了解以下內容?
- Vue全家桶系列,掌握vuex,vue-router以及axios ,不了解請移步官方教程axios-npm,vuex,vue-router
vuex : vuex是一種集中式狀態管理模式,什么意思呢?我們在模塊化開發過程中,我們以組件來作為模塊單位,模塊之間存在于不同的命名空間,作用域互不干預,這樣保證了我們模塊之間變量函數名稱等不會沖突,但是有時候我們我們需要組件之間共享一些數據或者狀態,我們通常的做法是傳參,但是傳參的做法至少有兩個弊端,一是麻煩(尤其是當需要傳遞的參數很多時),二是不好管理且冗余(給多個組件傳參就需要多份參數列表,而且容易出錯)。vuex提供的集中式管理就解決了這個問題,通過把要共享的數據或狀態集中起來管理,別的組件需要時就去訪問變更,大大提高了可維護性和開發效率
vue-router : vue-router是一個前端路由管理器,這個和后端常聽說的路由有些不同(個人覺得),這里的路由管理器更像是一個組件注冊器,vue-router為分散的組件注冊一個路由或者叫地址也未嘗不可,以方便我們控制組件的層級嵌套關系以及隱藏還是顯示,這樣我們可以很方便高效的構建單頁應用
axios : axios 和 jquery.ajax/vue-resource一樣 , 都是HTTP異步請求的工具,axios和vue-resource的API很像,但是個人覺得,axios的API更豐富一些
正文
?本文的小Demo大概功能就是一個登陸的功能,我們這里app.vue封裝了一個登陸組件,success.vue封裝了一個提示面板,通過vuex來集中管理登陸狀態,用vue-router來路由提示面板,用axios來異步提交到一個跨域的服務器(這里后臺服務是nginx+php提供,所以在dev-server中要設置一個反向代理,也就是nginx來代理我們的dev-server的請求從而解決axios跨域問題)
先來看看我們的項目結構 [自定義的]
這里的目錄設置,并不是一成不變的金科玉律,也不一定是最好的,讀者可以根據自己的想法設定文件結構,了解如何配置單入口單出口的webpack.config.js,可以看我的上一篇文章(開頭提到了),或者移步webpack官方網站。本篇內容,不再講解過多webpack配置,和上一篇是基本相同的,下面主要講解 Vue全家桶相關內容
index.js
import Vue from 'vue'; import Router from './routers/index-router'; import Store from './stores/index-store'; import App from './components/App.vue';var app = new Vue({ //創建一個Vue實例router : Router, //加入路由配置store : Store, //加入狀態管理components : {App} //加入App組件 }).$mount('#app'); //掛載節點需要注意的是,路由和狀態都需要加入一個vue實例中去才有意義。這里有一點很有意思,就是在路由router中注冊的組件(success.vue)依然可以訪問到狀態store實例,而官方教程上并沒有特別強調這一點,在下面我們可以看到這個有趣的事情
stores/index-store.js
import Vuex from 'vuex'; import Vue from 'vue'; import axios from 'axios';Vue.use(Vuex); //在vue中加入Vuex插件 const Store = new Vuex.Store({ //實例化一個Storestate : { //這里是我們需要集中管理的登陸狀態account : "ads",password : "123456",islogin : null},mutations : { // 這是唯一可以變更state的途徑,需要通過一個提交updateAccount(state,payload){ //具有載荷的mutationstate.account = payload.account},updatePassword(state,payload){state.password = payload.password},islogin(state,payload){if(payload == 1){state.islogin = true}else if(payload == 0){state.islogin = false}}},actions : { //這是可以支持異步執行提交的actionslogin (context,payload){//這里是去訪問我們的反向代理服務器上的一個php文件axios.get('/index.php',{params : {account : payload.account,password : payload.password}}).then(function(response){if(response.data.code == 'success'){//變更store狀態context.commit('islogin',1) //這里做了在異步邏輯中的狀態提交}else{context.commit('islogin',0)}}).catch(function(error){console.log(error)alert('fail')})}} })export default Store我們這里的Store有三個屬性,state是我們需要集中管理的狀態或者數據, mutations是維護變更我們狀態的一個方式, actions是為了在異步邏輯中提交狀態的一個中轉站,需要注意的是:
在實例化Store之前,必須先 Vue.use(Vuex) ,先在vue中加入Vuex插件這里需要說一下的是,如何開啟dev-server的proxy,讓nginx來代理axios的請求,也就是跨域訪問了(因為dev-server跑的是8080端口,nginx跑的是80端口,不設置代理的話瀏覽器將拒絕跨域訪問),感覺很深奧,其實很簡單,我們需要修改一下webpack.config.js中devServer的配置 :
webpack.config.js
devServer : {contentBase : './dist',watchContentBase : true,compress : true,port : 8080,hot : true,inline : true, //開啟頁面自動刷新open : true,proxy : {'/index.php' : {target : 'http://localhost:80/phpinfo.php',secure : false}}}然后,我們的axios在配置url時使用 /index.php,就可以相當于訪問http://localhost:80/phpinfo.php
routers/index-router.js
import VueRouter from 'vue-router'; import Vue from 'vue'; import success from '../components/success.vue';// 組件注冊路由,這里success組件注冊路由是'/app' var routes = [{path : '/app',component : success} ] Vue.use(VueRouter); //在vue中加入VueRouter插件 var Router = new VueRouter({ //實例化一個routerroutes //這里的寫法相當于 routes:routes })export default Router;這里的路由只注冊了一個組件,vue-router的能力遠不止如此,還可以嵌套定義組件的層級關系,更多到官方文檔了解 ,路由器和狀態管理器一樣都是vue官方核心插件,使用前都需要先 Vue.use(VueRouter) ,我們其實可以看到,這里把路由和狀態分別從vue實例中抽離出來,單獨管理,通過暴露實例Store Router,加入到vue實例中去,這樣可以方便debug和后期維護
components/App.vue 和 components/success.vue
App.vue
<template><div><input type="text" v-model="account"><input type="password" v-model="password"><button type="button" @click="login">show</button></div> </template> <script>export default {data : function(){return {account : "",password : ""}},created : function(){this.account = this.$store.state.accountthis.password = this.$store.state.password},watch : { //偵聽屬性account : function(){ //當accout改變就立即提交狀態this.$store.commit('updateAccount',{account : this.account})},// 當password改變就立即提交狀態password : function(){this.$store.commit('updatePassword',{password : this.password})}},methods : {login : function(){ //通過分發到action,來異步請求登錄服務,并變更狀態this.$store.dispatch('login',{account : this.account,password : this.password})this.$router.push('/app');//同時顯示登陸狀態}}} </script> <style scoped>input {height: 40px;width: 300px;border: 1px solid blue;box-shadow: none;} </style>success.vue
<template><div><p>{{islogin}}</p></div> </template> <script>export default {computed : { //計算屬性//動態響應狀態的變更islogin : function(){var islogin = this.$store.state.isloginif(islogin == null){return 'No option'}else if(islogin == true){return 'Login Success'}else if(islogin == false){return 'Login Fail'}}}} </script> <style scoped>p {height: 40px;text-align: center;} </style>templates/index.html
<!DOCTYPE html> <html> <head><meta charset="utf-8"><title>index</title> </head> <body><div id="app"><!-- App組件渲染出口 --><App></App><!-- 注冊路由的組件渲染出口 --><router-view></router-view></div> </body> </html>總結
好了,到此為止,代碼基本完成,我們來理一理,vue+vuex+vue-router以及組件之間是如何配合工作的?
用戶在App.vue組件中輸入,v-model雙向綁定了App組件中的data,App組件中的偵聽屬性發現data改動,立即向vuex的Store實例提交了狀態變更,當用戶點擊show,App組件中methods.login事件被觸發,它向Store實例發起一個分發,并導航到/app,Store的action收到分發調用axios去異步請求位于localhost:80下的php后臺服務,得到的登陸狀態立即提交,與此同時,Router去渲染/app路由對應的組件到模板中去,于是我們就可以看到一個動態響應式的狀態提示了
總結
以上是生活随笔為你收集整理的Vue全家桶 + webpack 构建单页应用初体验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: django学习(2)----APP
- 下一篇: IC攻城狮求职宝典 01 2018年IC