前言:
Ⅰ. demo所用vue-router的一些基本操作。vue-router中文文檔,快速瀏覽一遍即可 http://router.vuejs.org/zh-cn/
Ⅱ. 整個demo所用到的技術棧 vueJS(2.0) vue-cli vue-resource es6
Ⅲ. 所需構建工具 nodeJS Git
第一步:安裝
OK,正題開始,首先保證nodeJS,Git,webpack已安裝完畢。打開項目文件夾,安裝vue-cli。
全局安裝 vue-cli$ npm install --global vue-cli
創建一個基於webpack的模板vue init webpack my-project
創建過程中,vue-router為必須,其他語法檢測,單元測試等按需求安裝。
創建完成后進入項目文件夾,安裝依賴$ npm install
安裝到此結束,運行如下代碼,顯示為圖片所示,則安裝成功。$ npm run dev
第二步:項目文件及運行流程
Ⅰ: 項目文件
打開已經創建好的模板
如圖所示,只會用到,src,static,index.html這三個文件。首先解釋一下三個文件的作用:
Ⅰ: src 存放路由JS,模板.vue文件,入口JS,以及一個入口.vue文件
Ⅱ: static 存放靜態文件
Ⅲ: index 入口html文件
這里解釋一下xxx.vue文件是什么,官網叫其為單文件組件,通過webpack源碼轉換,會全部轉換為對應的文件。
說白了就是一個包裹,里邊含有三部分 一部分模板template
,一部分樣式style
,一部分JSjavascript
,他們封裝在一起。
如下圖所示:
Ⅱ: 運行流程
寫起來比較麻煩,做了一張圖,直截了當。
第三步:搭建基本路由框架
項目文件明了之后,我們開始搭建一個簡單的SPA路由構架:
Ⅰ: 頁面中有倆個及倆個以上的分類
Ⅱ: 每個分類中可以點擊進入到詳情頁面
Ⅲ: URL輸入錯誤后展示404頁面
Ⅳ: 在頁面中刷新,根據URL重新獲取數據,渲染頁面
根據基礎框架創建對應的文件。
文件詳解:
Ⅰ: src中components文件夾里新建三個xxx.vue文件,
①error.vue 此為404頁面
②showone.vue 此為第一個分類頁面
③showtwo.vue 此為第二個分類頁面
Ⅱ: src中zjapp.vue這是路由入口文件
Ⅲ: static中img為詳情頁面大圖,thumbnail為分類頁面縮略圖
Ⅳ: 倆個JSON文件,分別代表分類一和分類二的數據來源
Ⅴ: bootstrap.css 樣式CSS
到此路由的基本框架搭建完成,后面開始代碼的填充。
第四步:主頁面代碼編寫
Ⅰ: index.html
作為頁面入口文件,先引入Bootstrap.CSS,如果是本地文件放在static文件夾里。可以使用CDN或者npm安裝。
為了方便后面閱讀將id="app"更改為id="index"。當然,也可以不更改,main.js中有多個為app的名字,避免混淆。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>spa-vue-demo</title> <link rel="stylesheet" href="static/bootstrap.min.css" /> </head> <body> <div id="index"></div> <!-- built files will be auto injected --> </body> </html>
Ⅱ: main.js
main.js為入口JS文件,Vue的實例在這里書寫。el 掛載在 index.html 中 id="index" 的標簽上。
import Vue from 'vue' import App from './zjapp' import router from './router' Vue.config.productionTip = false new Vue({ el: '#index', router, template: '<App/>', components: { App } })
Vue 開始渲染時,加載 components: { App } 組件替換生成在 id="index" 內的 <App></App> 標簽,那么{ App }來自哪里呢?
答案在 import App from './zjapp' 這里是ES6語法,引入zjapp.vue模塊中暴露出來的接口,后綴可以不寫。
Vue 實例中的 router 屬性也是ES6中對象的字面量寫法,等於router:router。同理 import router from './router' 這里引入router。
因為,router中index.js暴露接口時沒有署名,這里也可以改一個名字,比如:
import Vue from 'vue' import App from './zjapp' //修改名字一樣可以。 import changeES6 from './router' Vue.config.productionTip = false new Vue({ el: '#index', //修改在這里 router:changeES6, template: '<App/>', components: { App } })
最后,可能有人會問 Vue.config.productionTip = false 是做什么用的,其實這里是關閉了生產模式即部署到服務器后給出的提示。
Ⅲ: zjapp.vue
這個文件是 Vue 一開始渲染組件時的文件,首先貼出全部代碼,很多,但是會全部講解作用,含義。
<template> <div class="container"> <div class="row"> <div id="index" class="col-xs-12 col-lg-12 col-md-12" style="padding: 0;"> <transition name='animate' appear mode='out-in'> <router-view v-bind:router-data="allData" v-bind:key="change"></router-view> </transition> <transition name='btn' appear mode='out-in'> <div class="app-btn" v-show="allData.mainShow"> <button class="btn btn-success app-btn-back" v-show="back==0?false:true" v-bind:key="back" v-on:click="dosom('back')">上一頁</button> <button class="btn btn-success app-btn-next" v-show="next==0?false:true" v-bind:key="next" v-on:click="dosom('next')">下一頁</button> </div> </transition> <div class="app-loading" v-show="loading"> <img src="../static/loading/loading.gif" style="margin:0 auto;display: block;" alt="loading" /> </div> </div> </div> </div> </template> <script> import router from './router' export default{ data(){ return{ allData:{ showData:null, detailedData:{}, num:0, mainShow:true }, loading:false, change:true, back:0, next:1, } }, created(){ this.routePath(); }, watch:{ "$route"(to){ this.routePath(); } }, methods:{ buttonToggle(){ var nowNum=this.allData.num; this.back=nowNum; this.next=2-nowNum; }, dosom(str){ str=="next"?this.allData.num++:this.allData.num--; this.buttonToggle(); //當前user/當前頁面/當前頁面路由 router.push(this.$route.path.slice(0,8)+this.allData.num); }, routePath(){ if(this.$route.fullPath=="/"){ router.push("/user/0/0"); this.load(); } else if(this.$route.fullPath.length==9 || this.$route.fullPath.length==20){ this.load(); } else{ router.push("/user/error"); this.back=0; this.next=0; } }, load(){ var numData=null, listData=null; // /user/lisData/numData numData=this.$route.path.slice(8,9); listData=this.$route.path.slice(6,7); // 初始化 this.allData.num=numData; this.buttonToggle(); this.change=!this.change; if(this.$route.path.indexOf("con")>0){ //獲取list中第幾個 var typeData=this.$route.query.type; this.$nextTick(e=>{ this.$http.get("static/data-"+listData+".json").then(rea=>{ this.loading=true; setTimeout(e=>{ //vue-resource加載數據存在於data.body中 var listNum=rea.body.allData.slice(numData*6,numData*6+6); //詳細顯示頁面數據來源 this.allData.detailedData=listNum.slice(typeData,typeData+1)[0]; this.loading=false; },700); }); }); this.allData.mainShow=false; }else{ this.$nextTick(e=>{ this.loading=true; setTimeout(e=>{ this.$http.get("static/data-"+listData+".json").then(rea=>{ this.allData.showData=rea.body.allData.slice(numData*6,numData*6+6); this.loading=false; }); },700); }); this.allData.mainShow=true; } } } } </script> <style> /*切換中動畫*/ .animate-enter-active,.animate-leave-active{ transition: all 0.5s ease; } .animate-enter{ transform: translateX(-80px); opacity: 0; }