从壹开始先后端分离 [ Vue2.0+.NET Core2.1] 二十二║Vue实战:我的博客初版(axios+router)

前言

今天正式开始写代码了,以前铺垫了不少了,包括 6 篇基础文章,一篇正式环境搭建,就是为了今天作准备,想温习的小伙伴能够再看看《Vue 基础入门+详细的环境搭建》,内容不少,这里就暂时不复习了,今天呢,我们就说说用昨天建立的空项目来搭建一个简单的我的博客系统,首先先分析下总体工做流程,而后再动手写代码,主要涉及到 axios 和 vue-router 的相关概念,好啦,开始今天的讲解。javascript

 

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

 

 

1、Vue 项目是如何运转的?

一、SPA的挂载页面 —— Index.html

首先你得明白,单页面应用程序是如何读取信息的,做为开发者,咱们都通过各类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

二、App.vue —— 页面全部路由对应组件的容器

听起来感受很拗口哈,说人话呢就是,咱们若是想要实现内容的切换,之前都是每一页面进行页面渲染发到浏览器,可是 SPA 不是这样,由于只有一个页面,因此就必须有一个空的容器,用来接纳不一样的组件内容,就好像上边的那个动图,都是在一个容器内,根据当前路由,将不一样的子组件内容填充到 App.vue 容器里,这样就能够了,还记得我们以前说到的 banner 切换么,用的就是这个道理。android

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

这个时候,你应该脑子里有点儿感受了,哦!我在一个入口页面里画一个坑,而后根据不一样的 URL 路径,去配置路由,而后显示这些东西,那如何控制呢?没错,你很聪明,请往下看webpack

 

三、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,并把组件和入口页面联系起来。ios

 

四、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 页面的使用,有两种方式: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')
    }]
},

 

 

以上四个文件的配合,就是整个项目的运转获得了保证,懂得了其中的原理,下边我们就开始动手写代码!

2、深刻说明  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

 

3、实现我的博客首页—— axios 获取数据

一、什么是 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 ,只要使用一遍就能够掌握。


二、首先咱们须要安装 axios。

进入当前文件夹 执行   npm install --save axios

 

 

之后会用到ElementUI:
npm i element-ui -S

 

三、安装成功后,咱们就能够封装咱们的 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) } }

 

四、添加好后,在 主方法 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");

 

五、修改 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端口,若是你们想用个人这个后端接口,须要这两个端口。

配置好端口后,再看页面哈哈哈,出来啦!

六、固然这个样式仍是比较丑陋的,我们引用 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>

而后你们在切换浏览器查看!哇哈哈,不同了

 

4、结语

今天呢咱们对 vue 建立的工做作了简要说明,也对其中的工做流程有了必定的感受,核心就是 一个页面(index.html),一个配置(main.js),一个 入口(app.vue),一个路由(router.js)共四部分,其余的就是在此基础上配置的,详情页尚未写,你们能够本身玩一玩,基本的vue 开发,你们已经掌握啦!vue 的讲解也慢慢接近了尾声,其实内容不少,知识点永远是说不完滴,你们加油鸭~~

 

5、Github

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

注意:若是下载好了,首先须要 执行 npm install 安装依赖