vue是現階段很流行的前端框架,不少人經過vue官方文檔的學習,對vue的使用都有了必定的瞭解,但再在項目工程化處理的時候,卻發現不知道改怎麼更好的管理本身的項目,如何去引入一些框架以及vue全家桶其餘框架的使用,如下將詳細地介紹本人在處理工程文件構建的過程;對於剛開始解除vue的新手,建議使用官方腳手架vue-cli,固然,若是你對於webpack很熟悉,你也能夠本身動手搭建本身的腳手架,固然若是你沒把握的話,仍是推薦使用vue-cli,能更好的幫助你搭建項目:css
首先,咱們能夠經過npm安裝vue-clic,前提是咱們須要有node環境,若是電腦還沒安裝node,先安裝,可經過前端
node -v
查詢node的版本號,有版本號則已經安裝成功;vue
接下來,咱們須要確保電腦已經安裝了webpack,webpack是一個包管理工具,也是vue-cli的構建工具,安裝也很簡單,全局安裝只須要執行node
npm install webpack -g
緊接着,開始咱們vue-cli的安裝webpack
npm install --global vue-cli
查看是否安裝成功,咱們能夠經過在cmd中輸入vue -V 查看,以下圖出現版本號則說明安裝已經完成;ios
咱們能夠打開c盤>用戶>用戶名>AppData>Roaming>npm查看咱們全局安裝的vue-cli,以下圖:web
安裝完vue-cli後,咱們能夠經過在cmd中輸入vue-router
vue init webpack projectName
生成webpack腳手架,在咱們按下回車的時候,會出現一些提示問題,對應關係以下:vuex
緊接着,咱們使用cd squareRoot 移動到文件夾squareRoot下,執行chrome
npm install
初始化項目,安裝package.json 文件中描述的依賴,初始化完成後,咱們能夠經過
npm run dev
運行咱們的項目,這個時候,咱們能夠打開瀏覽器,輸入http://localhost:8080/,可看到以下界面,說明咱們的項目腳手架已經初始化完成;
雖然咱們是經過vue-cli生成的項目結構,但仍是但願讀者可以清楚的知道每一個文件的做用,這樣對於咱們學習該腳手架以及搭建本身的腳手架會有很好的幫助,以下圖,是一級目錄下的文件的做用:
構建相關的代碼主要是放在build文件夾和config文件夾下,包括了開發環境和生產環境,即dev和product,能夠打開文件進行閱讀,有接觸過node的小夥伴應該能夠很快讀懂對應文件代碼的做用,這裏就不作詳細的介紹了,須要注意的一點是,咱們須要修改打包後文件的路徑的時候,能夠經過修改config文件夾下的index.js文件,以下圖:
這裏,咱們須要在src目錄下新增一個page文件夾,用於存放頁面相關的組件,而components存在的是公共的組件,這樣作有利於咱們更好的理解項目:
該步驟並非必定要實現的,實際項目操做中,要根據具體需求而引入對應的UI框架或者不引入,鑑於指導的做用,在此處也作個示範,給與參考,可先閱讀iVew官網學習;
首先,咱們應進行iView的安裝,可利用npm包管理工具安裝
npm install iview --save
安裝成功後,咱們要將對應的框架引入到項目中,這個時候,官網上有兩種方法能夠實現,第一種是直接在main.js中作以下配置:
import Vue from 'vue' import App from './App' import router from './router' import iView from 'iview'; import 'iview/dist/styles/iview.css'; Vue.config.productionTip = false Vue.use(iView); /* eslint-disable no-new */ new Vue({ el: '#app', router, components: { App }, template: '<App/>' })
這種方式是一種全局引入的方式,引入後就在具體的頁面或者組件內不須要再進行其餘的引入,但缺點是不管是否須要該組件,都將所有引入,對於性能優化不是很好,這裏推薦第二種用法,按需引入,這裏須要藉助插件babel-plugin-import實現按需加載組件,減少文件體積。首先須要安裝,並在.babelrc中配置:
npm install babel-plugin-import --save-dev
// .babelrc { "plugins": [["import", { "libraryName": "iview", "libraryDirectory": "src/components" }]] }
而後這樣按需引入組件,就能夠減少體積了,這裏須要注意的是,由於咱們修改了.babelrc文件,這將致使咱們第一種引入方法失效了,若是再使用那種方式引入,會致使代碼報錯;
<template> <div class="content"> <div class="title">患者接診</div> <div> <Button type="primary" shape="circle" class="btn-time">臨時保存</Button> <Button type="primary" shape="circle" class="btn-cancel">取消就診</Button> <Button type="primary" shape="circle" class="btn-done">完成就診</Button> </div> </div> </template> <script> import {Button} from 'iview' export default { name: "fHeader", components:{ Button } } </script>
運行結果以下圖
若是沒有閱讀過官方文檔,建議大夥先閱讀,官網上的教程已經足夠詳細,受益不淺;學習的過程當中,須要瞭解路由配置的基本步驟,命名規則,嵌套路由,路由傳參,具名視圖以及路由守衛,滾動行爲和懶加載,這裏咱們就不一一詳細介紹了,官網已有,咱們這裏是作構建是的配置和懶加載處理:
首先,咱們應該是安裝vue-router,這個在咱們生成項目的時候,已經將該依賴加載進來了,下一步要作的是在router文件下index.js進行配置:
import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) export default new Router({ scrollBehavior (to, from, savedPosition) { return { x: 0, y: 0 } }, routes: [ { path:'/', redirect:'/root' }, { path: '/root', name: 'root', components: { Left:() => import('@/page/rootLeft.vue'), Middle: () =>import('@/page/rootMiddle.vue'), Right: ()=>import('@/page/rootRight.vue') } } ] })
上面的代碼中,咱們應用到了幾個知識點,首先是滾動行文,這裏咱們配置了當路由跳轉的時候,默認是滾動到(0,0)位置,即頁面開始位置,其次咱們用到的redirect是一個路由重定向的配置,接下來,在路由"/root"下,配置了具名視圖,加載對應組件到對應視圖,咱們引入組件的方式使用到了箭頭函數,這樣寫的目的是爲了實現路由的懶加載,這樣構建,只有在路由被執行的時候,纔有引入對應的組件,對於頁面性能的優化有很大的幫助;這裏還須要注意的是,咱們在引入的這些組件中,其實默認都是打包到一個文件下的,這樣就會致使一次性引入的文件過大,爲此,咱們能夠利用webapck打包工具,咱們在build>webpack.base.conf.js文件下,增長以下代碼,用於配置輸出文件的模塊名稱,[name]是文件的名稱,[chunkhash]是打包文件的哈希值,加上這個是爲了將其做爲版本號,以解決瀏覽器緩存機制帶來的問題:
而後在路由文件中引入組件的代碼以下:
{ path:"/test", name:"test", component: ()=>import(/*webpackChunkName:"test"*/'@/page/test.vue') }
在引入組件的時候,加上/ webapckChunkName: "文件名" /,就這能夠將對於的組件打包到指定名稱的文件下,這樣能夠減小首次加載的文件的大小,對於一些沒有聯繫的功能,好比不一樣頁面,咱們能夠把對應的組件放在同一個文件,這樣,既能夠減小首次加載文件達大小,同時也能夠將文件實現一個按需加載,提升頁面性能;
經過控制檯,咱們能夠查看當前加載的文件資源,當咱們點擊測試按鈕的時候,頁面發生的跳轉,這時候,咱們會發現,在Network下,會加一條新的資源加載信息,這一條就是咱們的分塊打包後請求的資源;
寫到這裏的時候,可能不少人都會以爲,全局註冊filter和全局組件組件不是很簡單嗎,直接Vue.filter()和Vue.component()不久解決了嗎,其實這麼講也沒錯,可是你可曾想過,註冊全組件是掛載在Vue對象下的,這意味這按照正常思路,咱們要寫在main.js文件下,這樣就會形成,咱們所寫的mian文件過於冗長,你能夠想一下,把全局的過濾器,和組件都寫進去,着實醜陋,很不優雅,下面跟你們說一個優雅的實現方法:
首先,咱們在src>assets目錄下新建一個js文件夾,再該文件夾下再建立一個filters.js的文件,以下圖:
接下來,咱們在filters.js文件下寫咱們的全局過濾器,再將其拋出,寫一個時間過濾器做爲例子:
const fullTime = val => { var dateObj = new Date(Number(val)); var year = dateObj.getFullYear(); var month = dateObj.getMonth() + 1 > 9 ? (dateObj.getMonth() + 1).toString() : "0" + (dateObj.getMonth() + 1).toString(); var date = dateObj.getDate() > 9 ? dateObj.getDate().toString() : "0" + dateObj.getDate().toString(); var hour = dateObj.getHours() > 9 ? dateObj.getHours().toString() : "0" + dateObj.getHours().toString(); var minutes = dateObj.getMinutes() > 9 ? dateObj.getMinutes().toString() : "0" + dateObj.getMinutes().toString(); return year + "/" + month + "/" + date + " " + hour + ":" + minutes; }; module.exports={ fullTime }
作完這一步,其實咱們的過濾器還沒寫完,還須要在main.js中寫一個註冊函數:
import Vue from 'vue' import App from './App' import router from './router' import filters from './assets/js/filters' import 'iview/dist/styles/iview.css'; Object.keys(filters).forEach(key =>{ Vue.filter(key,filters[key]) }) Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', router, components: { App }, template: '<App/>' })
這樣,咱們就把filters文件下的過濾器函數註冊到Vue全局下,一樣道理,咱們能夠按照一樣的思路註冊全局組件,咱們在src>assets>js下新建一個components.js文件,在其中引入咱們想註冊的全局組件,export出一個對象,使用Object.keys獲取後註冊到全局下:
//components.js下 import testInput from '@/components/testInput.vue' export default{ testInput:testInput }
//main.js下 import components from './assets/js/components' Object.keys(components).forEach(key => { Vue.component(key,components[key]) })
優雅的註冊全局組件和全局過濾器已經講完,接下來就是API管理階段了。
這裏咱們使用axios發起異步的請求,安裝很簡單,npm install axios 便可,一開始的時候,我使用的是直接在每一個組件內使用axios,到後面發現,但當我須要修改api接口的時候,須要查找的比較麻煩,只由於沒有集中的對全部的api進行管理,並且每一個請求回來的接口都須要寫對應的報錯處理,着實麻煩,這裏我新建一個fecth文件夾並在其下新建一個api.js用來存放全部的axios處理和封裝,:
//fetch/api.js import axios from 'axios' export function fetch(url, params) { return new Promise((resolve, reject) => { axios.post(url, params).then( response => { resolve(response.data) } ).catch(error => { console.log(error) reject(error) }) }) } getDefaultData=()=>{ return fetch('/api/getBoardList'); } export default { getDefaultData }
這樣作的好處是集中化的管理了全部的api接口,當咱們須要修改接口相關的代碼,只須要在api.js中修改,包括路由修改以及路由攔截等,可讀性更好;在不一樣的組件內,咱們只須要把對應的接口用解構賦值的思想把它引入對應的組件內便可使用。
import {getDefaultData} from '@/fetch/api.js'
這個功能主要是咱們在調試接口的時候使用,由於當咱們運行npm run dev 的時候,實際上咱們的項目已經掛載在一個本地服務端運行了,端口號爲咱們配置的8080,當咱們想在該項目下訪問服務端接口數據的時候,就會產生跨域的問題,這個時候,咱們就須要使用到proxy代理咱們的數據請求,在vue-cli中已有配置相關的代碼,咱們僅須要把對應的代理規則寫進去便可,這裏以一個通用配置例子實現;
首先,咱們在fetch文件夾下新建一個config.js的文件,用於存放咱們的代理路徑配置:
const url = 'http://www.dayilb.com/'; let ROOT; if (process.env.NODE_ENV === 'production') { //生產環境下的地址 ROOT = url; } else { //開發環境下的代理地址,解決本地跨域跨域,配置在config目錄下的index.js dev.proxyTable中 ROOT = "/" } exports.PROXYROOT = url; //代理指向地址 exports.ROOT = ROOT;
接下來,咱們要在config目錄下新建一個proxyConfig.js,存放代理服務器的配置規則:
var config= require("../src/fetch/config"); module.exports = { proxy: { [config.ROOT]: { //須要代理的接口,通常會加前綴來區分,但我我的是沒加,即‘/’都轉發代理 target: config.PROXYROOT, // 接口域名 changeOrigin: true, //是否跨域 pathRewrite: { [`^/`]: '' //須要rewrite的,針對上面的配置,是不須要的 } } } }
最後,咱們在config目錄下的index.js文件中,引入咱們的代理規則,並在,即
var proxyConfig=require('./proxyConfig') ...//省略號表示省略其餘代碼 module.exports = { ... proxyTable: proxyConfig.proxy, ... }
從新啓動項目,咱們就能夠作到代理轉發來實現跨域請求了。
終於,來到了最後一步,那就是咱們的狀態管理vuex,其實這個東西不是說全部項目都須要引入,看項目的具體需求,但須要對同一個數據源進行大量的操做的時候,建議使用,若是每一個組件的數據均可以輕易的在data中管理,那實際上是不必引進去的,該管理工具是更友好的解決了組件間傳值的問題,包括了兄弟組件;
首先,咱們須要安裝vuex,老規矩就是
npm install vuex
安裝完成後,咱們須要對咱們的項目進行一些修改,首先是咱們的目錄,咱們須要src下新增一個store文件夾做爲vuex數據存放位置,在開始搭建前,咱們須要有vuex的相關知識,我就不一一說明,自行百度一下vuex官方文檔;衆所周知,vuex有state,getter,mutation,action等關鍵屬性,state主要是用於存放咱們的原始數據結構,相似與vue的data,不過它是全局的,getter相似於計算屬性computed,mutation主要用於觸發修改state的行爲,actions 也是一種觸發動做,只不過與mutation的區別在於異步的操做咱們只能在action中進行而不能在mutation中進行,目的是爲了瀏覽器更好的跟蹤state中數據的變化。
接下來,咱們來看一下store文件夾中都有什麼:
從上圖可知,我建立了一個index.js入口文件,getters.js,mutation.js和mutationtypes.js,以及actions.js,下面咱們先看看index.js的源碼:
import Vue from 'vue' import Vuex from 'vuex' import actions from '@/store/actions.js' import getters from '@/store/getters.js' import mutations from '@/store/mutations.js' Vue.use(Vuex) const state = { recipeList:[], currRecipe:0 }; if (module.hot) { // 使 action 和 mutation 成爲可熱重載模塊 module.hot.accept(['./mutations'], () => { // 獲取更新後的模塊 // 由於 babel 6 的模塊編譯格式問題,這裏須要加上 `.default` const newMutations = require('./mutations').default; // 加載新模塊 store.hotUpdate({ mutations: newMutations, }) }) } export default new Vuex.Store({ state, mutations, getters, actions })
首先,咱們把Vuex插件引入vue中,並新建了一個Vuex.Store()對象,其中各項屬性值來自咱們前面所建立的文件夾,中間module.hot是配置咱們的action和mutation成爲可熱重載的模塊,對於咱們的調試更方便,當咱們建立爲Vuex.store對象後,咱們還須要把它聲明到main.js的頁面Vue對象中
import store from './store/index' ... new Vue({ el: '#app', router, store, components: {App}, template: '<App/>' })
在使用mutation的時候,咱們是推薦你們把全部的行爲常量保存到一個.js文件中,這樣更有利於管理咱們的項目,由於咱們的mutation每每是須要使用action進一步封裝的,這樣咱們在使用的時候,只須要修改常量對象裏的屬性值,就能夠達到同時修改mutation和action的對應關係,一箭雙鵰,下面舉例給你們參考:
//mutationType.js export default { ADD_NEW_RECIPT:'ADD_NEW_RECIPT', CHANGE_CURR_TAB:'CHANGE_CURR_TAB' }
//mutations.js import mutationTypes from '@/store/mutationTypes.js' const mutations = { [mutationTypes.ADD_NEW_RECIPT](state, item) { state.recipeList.push(item); }, [mutationTypes.CHANGE_CURR_TAB](state, index) { state.currRecipe=index; } } ; export default mutations
import mutationTypes from '@/store/mutationTypes.js' const actions = { add_new_recipt:({commit,state}, type)=>{ commit(mutationTypes.ADD_NEW_RECIPT,type); }, change_curr_tab:({commit},index)=>{ commit(mutationTypes.CHANGE_CURR_TAB,index) } }; export default actions
從上面的例子能夠看出,action和mutation使用的是同一個常量表,能夠更好的管理咱們的修改動做,而不會出現對不上的錯誤;
最後,咱們在組件內引入vuex中存放的state和action,以下
import {mapActions, mapState} from 'vuex' ... computed: { ...mapState({ recipeList: state => state.recipeList, currRecipe: state => state.currRecipe }) }, methods: { ...mapActions([ 'add_new_recipt', 'change_curr_tab' ]), addNewRecipt(type) { this.add_new_recipt(type) } }
這裏是推薦你們按照例子中,使用mapActions和mapState以及利用三點擴展符來引入state 和action,state最好存放在組件的computed 屬性內,這樣當state中的數據發生改變的時候,也會實時的修改computed裏定義的變量值,來實現數據的綁定,同時,當咱們修改了某些數據的時候,也要同步到state中去,這樣數據源才能夠保持一致性與準確性;
寫這個的時候,只是給個思路去搭建本身的工程文件,並非說把全部相關知識點都講一遍,須要有必定的相關知識,不過相信還沒本身搭建過工程文件的小夥伴會不知道如何去安排,能夠參考參考,這裏推薦你們安裝chrome的擴展插件Vue.js devtools,能夠頗有效的幫助咱們追蹤數據,定位錯誤。