基於vue-cli 建立一個模板項目 經過 npm root -g 能夠查看vue全局安裝目錄,進而知道本身有沒有安裝vue-cli 若是沒有安裝的話,使用以下命令全局安裝 cnpm install -g vue-cli 建立一個基於webpack的新項目,在這過程當中, 會安裝依賴 vue init webpack 項目名 啓動 cd vue-router-demo npm start
若是咱們的項目是經過腳手架搭建的,這已是一個比較完善的種子項目了css
|-- build : webpack 相關的配置文件夾(基本不須要修改) |-- config: webpack 相關的配置文件夾(基本不須要修改) |-- index.js: 指定的後臺服務的端口號和靜態資源文件夾 |-- node_modules: 在上面安裝的依賴,都存放在這個文件夾下 |-- src : 源碼文件夾,咱們後續開發的組件和js分門別類的放在這裏面 |-- main.js: 應用入口 js |-- static: 靜態資源文件夾 |-- .babelrc: babel 的配置文件 |-- .editorconfig: 經過編輯器的編碼/格式進行必定的配置 |-- .eslintignore: eslint 檢查忽略的配置 |-- .eslintrc.js: eslint 檢查的配置 |-- .gitignore: git 版本管制忽略的配置 |-- index.html: 主頁面文件 |-- package.json: 他就至關於maven的pom.xml, 裏面存放着相關的依賴信息和項目的版本信息 |-- README.md: 應用描述說明的 readme 文件
能夠在config/index.js中作一下的經常使用配置html
在開發的時候咱們主要仍是關注src文件, 後來須要的路由,store,ajaxApi,以及其餘組件所有在建立在這個文件夾下vue
const path = require('path') module.exports = { dev: { // Paths assetsSubDirectory: 'static', assetsPublicPath: '/', proxyTable: {}, //添加跨域的配置 // Various Dev Server settings host: 'localhost', // can be overwritten by process.env.HOST port: 9528, // 配置是否打開瀏覽器 autoOpenBrowser: true, //配置是否打開瀏覽器 errorOverlay: true, notifyOnErrors: false, poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- // Use Eslint Loader? // If true, your code will be linted during bundling and // linting errors and warnings will be shown in the console. useEslint: false, // If true, eslint errors and warnings will also be shown in the error overlay // in the browser. showEslintErrorsInOverlay: false,
通常作好這不配置以後main就不用再改動了node
import App from './App' import router from './router' import store from './store' Vue.use(ElementUI, { locale }) new Vue({ el: '#app', router, store, template: '<App/>', components: { App } })
其實每個組件均可以完整的擁有下面三部分, 固然若是哪一個組件中不須要添加css樣式,能夠把最後一個style或者script標籤去掉webpack
<template> <div> <!-- 這裏存放 --> </div> </template> <//script> export default { name: 'app' } <///script> <style> </style>
好比根組件想使用hello.vue組件,怎麼作呢?ios
像下面這樣,三步走git
<template> <div> <!--第三步使用標籤--> <hello/> <div/> <template/> <script> import hello form './XXX/hello.vue' export default{ // 將組件映射成標籤 components:{ hello } } <style> </style>
第二步中引入標籤時也能夠去掉.vue後綴web
或者直接這樣寫,是從@/ 表明的是 src/ajax
import hello form '@/XXX/hello'
npm run build
項目通過打包,產出是一個dist文件,裏面分別是index.html 和 靜態資源文件夾, 這也是先後端分離開發的特點,後端想控制view層,也難了,只有一張index.htmlvue-router
命令:
npm install -g serve // 安裝工具 serve dist
注意點,使用tomcat當服務器,要求文件夾的名字和項目的名字要同樣,修改的步驟以下:
/build/webpack_prod.conf.js
文件output:{ ... pathPath:'項目名稱' }
npm run build
好的習慣就是使用它,規範本身的代碼風格, 可是也得說一下怎麼禁用eslint'
*.js *.vue 通常咱們就寫這兩部分,這一會兒全忽略了
由於eslint有個莫名其妙的要求,代碼最後一行要求是空行,能夠經過下面的方法三取消掉
rules:{ ... // 添加 'indent':0 }
在差分組件的時候,本着多個組件共享的數據放在根組件的原則, 因而咱們把共用的數據放在根組件,於此同時操做這些數據的方法也被咱們定義在根組件,子組件想要使用這些數據,想要操做這些數組怎麼辦呢? 想下面那樣,進行組件之間的數據傳遞
使用:強制數據綁定的方法, ChildTarget是咱們在components模塊將子組件映射得來的子組件標籤, name能夠是vue中data的方法,也能夠是方法
<template> <ChildTarget :name="name"/> </template>
export default{ props:['name','name2'] }
@click
最經常使用的就是使用@click="方法名"
, 或者@click="value = !value"
或者@click="value = true
若是咱們向上面那樣, 把公共的數據放在父組件中, 那麼事件的觸發必定是發生在子組件中, 子組件通常經過@click
給模板中的元素綁定上指定的動做,進而調用父組件的傳遞進來的方法,操做父組件傳遞進來的值
此外,在全部的組件中,vue的data部分都向下面這樣寫,是規定
data(){ return{ name:'' } }
watch:{ 監視的data中的對象 name:{ deep:true, // 深度監視 handler: function(value){ // value就是變化後的新的值 // todo } } }
從緩存中把去出來的字符串轉換成json串
JSON.parse(window.localStorage.getItem('')||'默認值');
把對象,存儲進瀏覽器的緩存
window.localStorage.setItem('自定義的key',JSON.stringfy(value))
像上面那樣,若是不存在父子組件的關係,父組件不引入子組件,也就沒辦法把他映射成標籤, 既然映射不成標籤也就無法像上面那樣,經過 : 冒號 強制進行數據的綁定達到傳遞值的效果,因而有了消息訂閱
組件之間的通訊方式: 發佈/訂閱
綁定監聽: 訂閱事件
觸發事件: 發佈事件
藉助插件-public.js
安裝命令:
npm install --save pubsub-js
場景: 咱們給模板上的按鈕綁定點擊事件,一旦被點解他就發佈事件
import PubSub from 'public-js'
使用:消息的發佈
<button @click="search">Search</botton> export default{ methods:{ search(name){ // search是方法名 // name 是攜帶的參數,沒參數就不用寫 Publish.publish('search',name) } } }
消息的訂閱:
mounted: { PubSub.subscribe("search",(name)=>{ // todo with name });
安裝插件axios
npm install axios --save
import axios from 'axios'
發送一個get請求
axios.get(url) .then(res=>{ // todo with res }) .catch(error){ // todo }
vue是如何作到使後端乖乖交出view層的控制權的?,難道是直接使用window.location.href = url嗎?
其實學過路由才知道, 使用的是vue-router,一個官方提供的路由框架,可使用我經過組合組件來組成應用程序,仰仗它的路由插件vue-router,咱們輕鬆控制頁面的切換
咱們要作的就是將組件components映射到routers,而後告訴vue-router到哪裏去渲染他們
安裝插件
npm install vue-router --save
編碼,其實你們都會把關於路由的編碼單獨放到一個叫router的文件夾中,並且,它的編碼基本上是機械化的編碼,分爲以下幾步
注意點 下面的配置部分, routes 不寫亂寫!!!
import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) import Home from './Home.vue' import About from './About.vue' import Me from './Me.vue' export default new VueRouter({ // 添加路由 routes:[ { path:'/home', component:Home, meta:{ // 添加自定義的字段,能夠當成flag,也能夠文本 } }, { path:'/about', component:About, meta:{ // 添加自定義的字段,能夠當成flag,也能夠文本 }, childred:[ // 嵌套路由 { path:'/about', component:About, meta:{ // 添加自定義的字段,能夠當成flag,也能夠文本 } } ] } }, { path:'', // 默認訪問空的話,重定向到/home redirect:'/home' } ] })
原來進行頁面的跳轉咱們一般使用a標籤,(通常把a標籤設計成按鈕,或者導航欄的樣子,點擊發送請求,進而跳轉頁面了), 而vue的路由其實和a標籤差很少,咱們使用vue的 router-link標籤替換a標籤
<router-link to:'/about' class="可讓我看起來像按鈕的css樣式"> </router-link> <router-link to:'/home' class="可讓我看起來像按鈕的css樣式"> </router-link> <router-view ></router-view>
這樣用戶點擊 router-link,就會把相應的子組件移植到
補充:
屬性 | 類型 | 含義 |
---|---|---|
to | string | Location | 表示目標路由的連接。當被點擊後,內部會馬上把 to 的值傳到 router.push() ,因此這個值能夠是一個字符串或者是描述目標位置的對象。 |
replace | boolean | 設置 replace 屬性的話,當點擊時,會調用 router.replace() 而不是 router.push() ,因而導航後不會留下 history 記錄。 |
append | boolean | 設置 append 屬性後,則在當前(相對)路徑前添加基路徑。例如,咱們從 /a 導航到一個相對路徑 b ,若是沒有配置 append ,則路徑爲 /b ,若是配了,則爲 /a/b |
咱們能夠在按鈕上添加下面的動做,是路由回退一級
<button @click="$router.back()"></button>
使用以下標籤包裹咱們的router-view,這樣當咱們再回退到上一個路由時,用戶加進去的狀態依然存在
<keep-alive> <router-view ></router-view> </keep-alive>
$router是路由器對象,說白了就是用它去跳轉頁面,美其名曰:編程式路由導航
$route是路由對象,說白了就是某一個路由對象,既然是某一個,就不能進行頁面的跳轉,相反是能夠獲取出當前路由組件的屬性,它的結構圖以下:
$route的組成圖
需求: 咱們想發送這樣的請求 http:localhost:8080/home/1/羊肉串,在路徑上攜帶着參數1
路由怎麼接收參數呢?--> 使用:佔位
export default new VueRouter({ // 添加路由 routes:[ { path:'/home/:id/:type', // 若是想在路徑上傳遞值進來,就使用:佔位 component:Home, meta:{ // 添加自定義的字段,能夠當成flag,也能夠文本 flag:true } },
當咱們添加了/:以後,它的組成結構就變成了這個樣子
像下面這樣傳遞值進去,發起請求
<router-link to:`/home/${id}/${type}` class="可讓我看起來像按鈕的css樣式"> </router-link>
同時,咱們也能夠向下面這樣使用$route. 在對應不一樣的路由組件中,把裏面的屬性取出來, 注意啊,這樣取值,前提是咱們前面使用 /:id佔位,而且也整整傳遞值進去了
<h1>id= {{$route.params.id}}</h1>
使用<router-view >
標籤傳遞值
<router-view msg='abc'></router-view>
在路由組件中經過props取出值,而後能夠直接使用
export default{ props:[ msg:String ] }
編程式的路由導航說白了就是,不用router-link標籤轉而使用代碼路由的跳轉唄, 舉個例子,咱們使用手機qq,最下面有幾個導航欄,點擊不一樣的按鈕轉換到不一樣的頁面去,若是用編程式的路由導航就很好作
vue提供了兩種編程式的路由導航實現
this.$router.replace(`/home/${id}`)
this.$router.push(`/home/${id}`)
它是個和 rout-view 和像的標籤,都是用來佔位的,它能夠接受父組件傳遞給他的一段html
舉個例子: 有四張路由組件,他們共用一個叫header的組件看成本身的頭部, 可是他們須要傳遞進去屬於本身的不一樣的值, 下面使用slot實現
在 MyHeader.vue中
<!--首頁頭部--> <header class="header"> <!-- 這裏使用插槽佔位--> <slot name="left"></slot> <span"> <span >我是header</span> </span> <!-- 這裏使用插槽佔位--> <slot name="right"></slot> </header>
在父組件中使用:注意啊,下面的組件想往MyHeader.vue中的插槽中,傳遞進去代碼片斷,前提是他要把MyHeader.vue映射成標籤,成爲他的父組件
<div> <MyHeader> <span class="header_search" slot="left"> <i class="iconfont icon-sousuo"></i> /*在插槽的左邊植入一個icon*/ </span> <!-- 給右邊的插槽傳遞模板 --> <span class="header_login" slot="right"> <a href="" >登陸|註冊</a> /* 在插槽的右邊植入一個連接 */ </span> </MyHeader> </div>
官方的解釋: vuex是專門爲Vue.js應用程序開發的狀態管理模式,它採用集中式的儲存應用中全部組件的狀態,並以相應的規則保證狀態以一種可預期的方式發生變化
說白了: 當咱們劃分組件以後,每個組件都有本身的屬性,可是不一樣的組件的數據是不能共享的,因而咱們可使用從父組件往子組件傳播數據的模式, 並且徹底不相干的兩個組件可能須要對方data裏的數據,又怎麼傳遞呢? vuex 就應對 迎戰這個問題
vuex就是一個單獨存儲的區域,用於存放公共的屬性
npm install --save vuex
建立vuex的四個組件對象,如上圖
狀態對象,存放一系列的狀態,其實就是把子組件中data裏面的字段賦複製過來
state.js文件 export default { arr: [] }
超級重要的組件, 在這個組件中咱們能夠提交異步事件, 最經常使用的就是用戶直接經過$store.dispatch('action中的方法名'), action會觸發 mutation的調用, 間接更新狀態
action.js // add方法的方法第一個參數是不變的{commit}, 其實他就是 $store 對象 // 經過這個commit方法, 把數據包裝成對象傳遞給 mutations // 第二個參數的可選的,能夠是調用者傳遞進來的參數,也能夠是state對象 export default { add({commit},item){ // 提交mutation請求 commit(ADD_TODO,{item}); // 把數據包裝成對象傳遞給 mutations },
真正的去執行action傳進來,更新state中數據的操做
mutations.js export default { add(state,{item}){ state.arr.unshift(item); } }
包含了全部的基於state的 get計算屬性, 這一點也很好用,他是一種雙向的數據綁定
getters.js export default { // 計算屬性 totalCount (state) { return state.arr.length }, }
編碼實現: store.js
store.js import Vue from 'vue' import Vuex from 'vuex' import state from './state' import actions from './actions' import mutations from './mutations' import getters from './getter2' Vue.use(Vuex) // 對外暴露你匿名 store對象 export default new Vuex.Store({ state, actions, mutations, getters }) 把store對象,註冊進main.js
作好了上面的配置,在任何地方都能用下面的方式獲取出store裏面的數據
this.$store.state.屬性
添加上前綴,再使用
this.$store.commit('matations中的方法名','可選的參數') // 注意哦, action中是能夠提交異步函數的 this.$store.dispach('action中的方法名','可選的參數')
也能夠像下面這樣,先進行映射就能夠再也不添加任何前綴,直接使用他們
// 從vuex中引入映射 import {mapState,mapGetters,mapActions} from 'vuex' export default { computed:{ ...mapState(['state中的屬性值']) ...mapGetters(['getters.js中的方法名']) }, methods:{ ...mapActions(['actions.js中的方法名']) } }