今天正式開始寫代碼了,以前鋪墊了不少了,包括 6 篇基礎文章,一篇正式環境搭建,就是爲了今天作準備,想溫習的小夥伴能夠再看看《Vue 基礎入門+詳細的環境搭建》,內容不少,這裏就暫時不復習了,今天呢,我們就說說用昨天建立的空項目來搭建一個簡單的我的博客系統,首先先分析下總體工做流程,而後再動手寫代碼,主要涉及到 axios 和 vue-router 的相關概念,好啦,開始今天的講解。javascript
首先你得明白,單頁面應用程序是如何讀取信息的,做爲開發者,咱們都通過各類URL配置,也都明白 URl 的組成部分,隨便舉個栗子:css
https://www.cnblogs.com/laozhang-is-phi/p/9629026.html?test=2#index
這個 URL 包含了多個部分:html
https: //一、頁面請求的協議。 www.cnblogs.com //二、爲頁面所屬的域名。 p/9629026.html //三、是匹配到某一篇文章的id。 ?test=2 //四、頁面經過 url 傳遞 get 請求的參數 #index //五、爲頁面的錨點區域
因而可知,之因此 SPA 單頁面應用程序的前四個都是同樣的,由於只有一個單頁面提供入口,因此咱們只能經過第五個屬性,也就是錨點來實現路由的切換,根據url 的不一樣路由配置,從而達到頁面不刷新的效果,vue
這個時候你應該能明白了 SPA 是如何運行的,那這個時候你就會問了,是誰承擔着工做呢,沒錯就是——index.html 頁面,整個項目都是在這個文件的基礎上進行變化,能夠說是一個模板,由於就只有這一個頁面。java
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title>blogvue3</title> </head> <body> <noscript> <strong>We're sorry but blogvue3 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </noscript> <div id="app"></div><!-- 經過app 提供掛載元素,動態的路由加載--> <!-- built files will be auto injected --> </body> </html>
不過這個時候你會問,好吧,我知道了單頁面的原理,開始如何作出來動態效果呢?請往下看node
聽起來感受很拗口哈,說人話呢就是,咱們若是想要實現內容的切換,之前都是每一頁面進行頁面渲染髮到瀏覽器,可是 SPA 不是這樣,由於只有一個頁面,因此就必須有一個空的容器,用來接納不一樣的組件內容,就好像上邊的那個動圖,都是在一個容器內,根據當前路由,將不一樣的子組件內容填充到 App.vue 容器裏,這樣就能夠了,還記得我們以前說到的 banner 切換麼,用的就是這個道理。android
<div id="app"> <div id="nav"> </div> <router-view/>//這裏就是 路由子組件容器 </div>
這個時候,你應該腦子裏有點兒感受了,哦!我在一個入口頁面裏畫一個坑,而後根據不一樣的 URL 路徑,去配置路由,而後顯示這些東西,那如何控制呢?沒錯,你很聰明,請往下看webpack
import Vue from "vue"; //導入vue import App from "./App.vue";//導入 app.vue 主組件 import router from "./router";//導入路由 也能夠寫 router.js import store from "./store"; Vue.config.productionTip = false; //將上邊的全局變量賦給 vue 實例化,並掛載到 #app上 new Vue({ router, store, render: h => h(App) }).$mount("#app");
說白了,main.js 就好像一個管理者,經過實例化 vue,並把組件和入口頁面聯繫起來。ios
import Vue from "vue"; import Router from "vue-router";// 引用路由 import Home from "./views/Home.vue";//導入方法1 Home頁面 Vue.use(Router); export default new Router({ mode: "history", base: process.env.BASE_URL, routes: [ { path: "/", name: "home", component: Home }, { path: "/about",//路徑 name: "about",//名字 component: () => import(/* webpackChunkName: "about" */ "./views/About.vue")//導入方法2,導入About頁面 } ] });
在上邊的配置中能夠看到,整個 router.js 文件都在管控着咱們的路由原則,已經 vue 頁面的使用,有兩種方式:git
一、經過 import 導入文件的形式,定義變量使用,就是 Home 頁面的使用方法;
二、直接在 routes 中配置要導入的文件,就是 About 頁面的使用方法;
二者沒有太大的差異,我的更傾向於第一種。
注意,在定義路由的時候,能夠定義多級路由,我實驗過四層的,多了不知道啥效果,定義方法很簡單:
{ path: '/tourcard', icon: 'android-settings', name: 'tourcard', title: '父路由', component: Main, children: [{ path: 'tourcard-card', title: '子路由1', name: 'tourcard-card', component: () => import ('@/views/tourcard/tourcard-card/tourcard-main.vue'), children: [{ path: 'tourcard-main', title: '孫路由1', name: 'tourcard-main', component: () => import ('@/views/tourcard/tourcard-card/tourcard-card/tourcard-card.vue'), }, { path: 'tourcard-detail', title: '孫路由2', name: 'tourcard-detail', component: () => import ('@/views/tourcard/tourcard-card/tourcard-detail/tourcard-detail.vue') }] }, { path: 'tourcard-saleOrder', title: '子路由2', name: 'tourcard-saleOrder', component: () => import ('@/views/tourcard/tourcard-saleOrder/tourcard-saleOrder.vue') }] },
以上四個文件的配合,就是整個項目的運轉獲得了保證,懂得了其中的原理,下邊我們就開始動手寫代碼!
首先咱們必定要安裝 vue-router 這個你們如今不用安裝,昨天已經安裝了,還記得麼,就是咱們經過鍵盤的 空格鍵 選擇了不少插件,若是不記得能夠去上一篇文章看一看。
路由,其實就是指向的意思,當我點擊頁面上的 home 按鈕時,頁面中就要顯示 home 的內容,若是點擊頁面上的 about 按鈕,頁面中就要顯示 about 的內容。因此在頁面上有兩個部分,一個是點擊部分,一個是點擊以後,顯示內容的部分,這兩部分經過配置造成映射。 那麼點擊以後,vue 是如何作到正確的對應,好比,我點擊home 按鈕,頁面中怎麼就正好能顯示home的內容。這就要在js 文件中配置路由。
由於咱們頁面中全部內容都是組件化的,咱們只要把路徑和組件對應起來就能夠了,而後在頁面中把組件渲染出來。
1, 頁面實現(html模模板中)
在vue-router中, 咱們看到它定義了兩個標籤<router-link> 和<router-view>來對應點擊和顯示部分。<router-link> 就是定義頁面中點擊的部分,<router-view> 定義顯示部分,就是點擊後,區配的內容顯示在什麼地方。因此 <router-link> 還有一個很是重要的屬性 to,定義點擊以後,要到哪裏去, 如:<router-link to="/home">Home</router-link>
2, js 中配置路由
首先要定義route, 一條路由的實現。它是一個對象,由兩個部分組成: path和component. path 指路徑,component 指的是組件。如:{path:’/home’, component: home}
咱們這裏有兩條路由,組成一個routes:
const routes = [ { path: '/home', component: Home }, { path: '/about', component: About } ]
最後建立router 對路由進行管理,它是由構造函數 new vueRouter() 建立,接受routes 參數。
const router = new VueRouter({ routes // routes: routes 的簡寫 })
配置完成後,把router 實例注入到 vue 根實例中,就可使用路由了
const app = new Vue({ router }).$mount('#app')
執行過程:當用戶點擊 router-link 標籤時,會去尋找它的 to 屬性, 它的 to 屬性和 js 中配置的路徑{ path: '/home', component: Home} path 一一對應,從而找到了匹配的組件, 最後把組件渲染到 <router-view> 標籤所在的地方。全部的這些實現纔是基於hash 實現的。
文章參考自:@https://www.cnblogs.com/SamWeb/p/6610733.html
官網地址:https://www.npmjs.com/package/axios
axios 是一個基於Promise 用於瀏覽器和 nodejs 的 HTTP 客戶端,它自己具備如下特徵:
從瀏覽器中建立 XMLHttpRequest
從 node.js 發出 http 請求
支持 Promise API
攔截請求和響應
轉換請求和響應數據
取消請求
自動轉換JSON數據
客戶端支持防止 CSRF/XSRF
能夠經過 <script src="https://unpkg.com/axios/dist/axios.min.js"></script> 來引用,也能夠用 npm install axios
直接來安裝。
在上邊的官網中,有特別詳細的講解,特別像咱們平時用的 ajax ,只要使用一遍就能夠掌握。
進入當前文件夾 執行 npm install --save axios
之後會用到ElementUI:
npm i element-ui -S
這裏我使用網上的一個封裝方法,原做者 @https://www.cnblogs.com/zhaowy/p/8513070.html
在 src 目錄下新建 api 文件夾,而後在 添加一個 http.js 文件,並填寫下邊的方法
// 配置API接口地址 var root = 'http://apk.neters.club/api' // 引用axios var axios = require('axios') // 自定義判斷元素類型JS function toType (obj) { return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase() } // 參數過濾函數 function filterNull (o) { for (var key in o) { if (o[key] === null) { delete o[key] } if (toType(o[key]) === 'string') { o[key] = o[key].trim() } else if (toType(o[key]) === 'object') { o[key] = filterNull(o[key]) } else if (toType(o[key]) === 'array') { o[key] = filterNull(o[key]) } } return o } /* 接口處理函數 這個函數每一個項目都是不同的,我如今調整的是適用於 https://cnodejs.org/api/v1 的接口,若是是其餘接口 須要根據接口的參數進行調整。參考說明文檔地址: https://cnodejs.org/topic/5378720ed6e2d16149fa16bd 主要是,不一樣的接口的成功標識和失敗提示是不一致的。 另外,不一樣的項目的處理方法也是不一致的,這裏出錯就是簡單的alert */ function apiAxios (method, url, params, success, failure) { if (params) { params = filterNull(params) } axios({ method: method, url: url, data: method === 'POST' || method === 'PUT' ? params : null, params: method === 'GET' || method === 'DELETE' ? params : null,
//headers 是即將被髮送的自定義請求頭,還記得咱們的jwt驗證麼,能夠封裝進來,注意!這裏若是要添加 headers ,必定要是正確的值
headers:{"Authorization":"Bearer xxxxxxx"}, baseURL: root, withCredentials: false }) .then(function (res) { if (res.data.success === true) { if (success) { success(res.data) } } else { if (failure) { failure(res.data) } else { window.alert('error: ' + JSON.stringify(res.data)) } } }) .catch(function (err) { let res = err.response if (err) { window.alert('api error, HTTP CODE: ' + res.status) } }) } // 返回在vue模板中的調用接口 export default { get: function (url, params, success, failure) { return apiAxios('GET', url, params, success, failure) }, post: function (url, params, success, failure) { return apiAxios('POST', url, params, success, failure) }, put: function (url, params, success, failure) { return apiAxios('PUT', url, params, success, failure) }, delete: function (url, params, success, failure) { return apiAxios('DELETE', url, params, success, failure) } }
import Vue from "vue"; import App from "./App.vue"; import router from "./router1.js"; import store from "./store"; // 引用API文件 import api from './api/http.js' // 將API方法綁定到全局 Vue.prototype.$api = api Vue.config.productionTip = false; new Vue({ router, store, render: h => h(App) }).$mount("#app");
<template> <div class="home"> <div class="l_body"> <div class='container clearfix'> <div class='l_main'> <section class="post-list"> <div v-for="i in list" :key="i.bID" class='post-wrapper'> <article class="post "> <section class="meta"> <h2 class="title"> <router-link :to="'/content/' + i.bID"> {{ i.btitle }} </router-link> </h2> <time> {{i.bCreateTime}} </time> <div class='cats'> <a href="javascript:void(0)">{{i.bsubmitter}}</a> </div> </section> <section class="article typo"> <article v-html="i.bcontent"></article> <div class="readmore"> <a href="/dotnet/asp.net core???????????/">查看更多</a> </div> <div class="full-width auto-padding tags"> <a href="javascript:void(0);">{{i.bcategory}}</a> </div> </section> </article> </div> </section> <nav id="page-nav"> <router-link :to="'/?page=' + (page>1?page-1:1)" class="prev" rel="prev"> {{(page<=1? "": "Previous")}} </router-link> <router-link :to="'/?page=' + (page>=TotalCount? TotalCount: page+1)" class="next" rel="next"> {{(page>=TotalCount? "": "Next")}} </router-link> </nav> </div> <aside class='l_side'> <section class='m_widget categories'> <div class='header'>標籤</div> <div class='content'> <ul class="entry"> <li><a class="flat-box" href="javascript:void(0);"> <div class='name'>博客</div> <div class='badget'>11</div> </a></li> <li><a class="flat-box" href="javascript:void(0);"> <div class='name'>隨筆</div> <div class='badget'>10</div> </a></li> </ul> </div> </section> </aside> </div> </div> </div> </template> <script> // @ is an alias to /src export default { name: "home", components: {}, data() { return { page: 1, TotalCount: 1, isShow: true, list: [] } }, created() { this.getData() }, methods: { getData() { var that = this var urlPage = that.$route.query.page if (urlPage) { that.page = urlPage } this.$api.get('Blog?page=' + that.page, null, r => {this.list = r.data this.page = r.page this.TotalCount = r.pageCount this.isShow=false }) } }, watch: { '$route'(to, from) { this.list=[] this.isShow=true this.page = to.query.page this.getData() } } }; </script>
這個時候,你滿懷幸福的眼神去登錄查看,發現沒有結果?彆着急,機智如我,F12 查看,果真是跨域了
這個你必定特別熟悉,對不對,還記得我們講到 .net core api 的跨域的時候,折磨了不少小夥伴的問題,終於遇到了,有沒有一種修的圓滿的趕腳,這個時候怎麼辦呢,固然是修改端口咯,相信你們都會了,我這裏只是開放了8080,和8081端口,若是你們想用個人這個後端接口,須要這兩個端口。
配置好端口後,再看頁面哈哈哈,出來啦!
咱們在 src 根目錄下,新建 style 文件夾,而後新建 stylehome.css 文件,而且在 主頁面入口 app.vue 中引用
<template> <div id="app"> <div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> </div> <router-view/> </div> </template> <style lang="css"> @import "./style/stylehome.css";//就是在這裏引用 </style>
而後你們在切換瀏覽器查看!哇哈哈,不同了
今天呢咱們對 vue 建立的工做作了簡要說明,也對其中的工做流程有了必定的感受,核心就是 一個頁面(index.html),一個配置(main.js),一個 入口(app.vue),一個路由(router.js)共四部分,其餘的就是在此基礎上配置的,詳情頁尚未寫,你們能夠本身玩一玩,基本的vue 開發,你們已經掌握啦!vue 的講解也慢慢接近了尾聲,其實內容不少,知識點永遠是說不完滴,你們加油鴨~~
https://github.com/anjoy8/Blog.Vue
注意:若是下載好了,首先須要 執行 npm install 安裝依賴