前言

今天正式开始写代码了,之前铺垫了很多了,包括 6 篇基础文章,一篇正式环境搭建,就是为了今天做准备,想温习的小伙伴可以再看看《Vue 基础入门+详细的环境搭建
<https://www.cnblogs.com/laozhang-is-phi/category/1292730.html>
》,内容很多,这里就暂时不复习了,今天呢,咱们就说说用昨天创建的空项目来搭建一个简单的个人博客系统,首先先分析下整体工作流程,然后再动手写代码,主要涉及到
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 tocontinue.</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 routerfrom "./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 页面的使用方法;

两者没有太大的差别,个人更倾向于第一种。

 

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

二、深入说明  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 <https://www.npmjs.com/package/axios>

axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征:

从浏览器中创建 XMLHttpRequest

从 node.js 发出 http 请求

支持 Promise API

拦截请求和响应

转换请求和响应数据

取消请求

自动转换JSON数据

客户端支持防止 CSRF/XSRF
<http://baike.baidu.com/link?url=iUceAfgyfJOacUtjPgT4ifaSOxDULAc_MzcLEOTySflAn5iLlHfMGsZMtthBm5sK4y6skrSvJ1HOO2qKtV1ej_>

可以通过 <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://123.206.33.109:8012/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":"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'>
<sectionclass='m_widget categories'> <div class='header'>标签</div> <div class='
content'> <ul class="entry"> <li><a class="flat-box" href="javascript:void(0);"
> <divclass='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/Get?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 <https://github.com/anjoy8/Blog.Vue>

注意:如果下载好了,首先需要 执行 npm install 安装依赖

 

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信