從壹開始前后端分離 [ Vue2.0+.NET Core2.1] 二十二║Vue實戰:個人博客第一版(axios+router)


前言

今天正式開始寫代碼了,之前鋪墊了很多了,包括 6 篇基礎文章,一篇正式環境搭建,就是為了今天做准備,想溫習的小伙伴可以再看看《Vue 基礎入門+詳細的環境搭建》,內容很多,這里就暫時不復習了,今天呢,咱們就說說用昨天創建的空項目來搭建一個簡單的個人博客系統,首先先分析下整體工作流程,然后再動手寫代碼,主要涉及到 axios 和 vue-router 的相關概念,好啦,開始今天的講解。

 

零、要完成的右下角褐色的部分

 

 

一、Vue 項目是如何運轉的?

1、SPA的掛載頁面 —— Index.html

首先你得明白,單頁面應用程序是如何讀取信息的,作為開發者,我們都經過各種URL配置,也都明白 URl 的組成部分,隨便舉個栗子:

https://www.cnblogs.com/laozhang-is-phi/p/9629026.html?test=2#index

這個 URL 包含了多個部分:

https:           //1、頁面請求的協議。
www.cnblogs.com  //2、為頁面所屬的域名。
p/9629026.html   //3、是匹配到某一篇文章的id。
?test=2          //4、頁面通過 url 傳遞 get 請求的參數
#index           //5、為頁面的錨點區域

由此可見,之所以 SPA 單頁面應用程序的前四個都是一樣的,因為只有一個單頁面提供入口,所以我們只能通過第五個屬性,也就是錨點來實現路由的切換,根據url 的不同路由配置,從而達到頁面不刷新的效果,

這個時候你應該能明白了 SPA 是如何運行的,那這個時候你就會問了,是誰承擔着工作呢,沒錯就是——index.html 頁面,整個項目都是在這個文件的基礎上進行變化,可以說是一個模板,因為就只有這一個頁面。

<!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>

不過這個時候你會問,好吧,我知道了單頁面的原理,開始如何做出來動態效果呢?請往下看

2、App.vue —— 頁面所有路由對應組件的容器

聽起來感覺很拗口哈,說人話呢就是,我們如果想要實現內容的切換,以前都是每一頁面進行頁面渲染發到瀏覽器,但是 SPA 不是這樣,因為只有一個頁面,所以就必須有一個空的容器,用來接納不同的組件內容,就好像上邊的那個動圖,都是在一個容器內,根據當前路由,將不同的子組件內容填充到 App.vue 容器里,這樣就可以了,還記得咱們之前說到的 banner 切換么,用的就是這個道理。

  <div id="app">
    <div id="nav">
    </div>
    <router-view/>//這里就是 路由子組件容器
  </div>

這個時候,你應該腦子里有點兒感覺了,哦!我在一個入口頁面里畫一個坑,然后根據不同的 URL 路徑,去配置路由,然后顯示這些東西,那如何控制呢?沒錯,你很聰明,請往下看

 

3、main.js —— 入口文件,初始化vue實例並使用需要的插件

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,並把組件和入口頁面聯系起來。

 

4、router.js —— 路由文件,配置着 url 路徑 和 頁面的關系

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 頁面的使用,有兩種方式:

1、通過 import 導入文件的形式,定義變量使用,就是 Home 頁面的使用方法;

2、直接在 routes 中配置要導入的文件,就是 About 頁面的使用方法;

兩者沒有太大的差別,個人更傾向於第一種。

 

5、多級路由 

注意,在定義路由的時候,可以定義多級路由,我實驗過四層的,多了不知道啥效果,定義方法很簡單:

{
    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 工作原理

 首先我們一定要安裝 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

 

三、實現個人博客首頁—— axios 獲取數據

1、什么是 axios

官網地址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 ,只要使用一遍就可以掌握。


2、首先我們需要安裝 axios。

進入當前文件夾 執行   npm install --save axios

 

 

以后會用到ElementUI:
npm i element-ui -S

 

3、安裝成功后,我們就可以封裝我們的 axios 請求方法了。

 這里我使用網上的一個封裝方法,原作者 @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) } }

 

4、添加好后,在 主方法 main.js 中 引用該 js 文件,並定義全局變量,這樣,就可以在所有的頁面內,使用 $api 方法了。

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");

 

5、修改 Home 頁面的代碼,直接粘貼進去

<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端口,如果大家想用我的這個后端接口,需要這兩個端口。

配置好端口后,再看頁面哈哈哈,出來啦!

6、當然這個樣式還是比較丑陋的,咱們引用 css 樣式文件吧

我們在 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 的講解也慢慢接近了尾聲,其實內容很多,知識點永遠是說不完滴,大家加油鴨~~

 

五、Github

https://github.com/anjoy8/Blog.Vue

注意:如果下載好了,首先需要 執行 npm install 安裝依賴

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM