由于在学习该项目的过程中发现了原讲义存在的一些问题,所以该笔记基于「学成在线」微服务项目 PDF
讲义进行编写,并且投入了时间去优化了笔记的格式、代码的高亮、重点的标记等。
以及一些原讲义中所描述的一些知识点使我无法理解的内容,我会对这些内容的表达方式进行修改或者提出一些问题,并且用我自己所理解的一些想法去重新的解释这个问题。
总结一下原 PDF
讲义中已知的一些问题:
PDF
中复制出来的代码,部分特殊符号的编码有问题,并且不易被发现,例如横杠 -
,从PDF直接复制出来的话是无法运行的。如有不足的地方,欢迎小伙伴们补充、填坑。
为了方便后续回顾该项目时能够清晰的知道本章节讲了哪些内容,并且能够从该章节的笔记中得到一些帮助,所以在完成本章节的学习后在此对本章节所涉及到的知识点进行总结概述。
本章节为【学成在线】项目的 day02
的内容
vue
基础语法
对 webpack
与 webpack-dev-server
的基本使用,理解 webpack
的打包过程。
CMS
前端工程的基础构建
解决前端跨域请求的问题,并理解前端请求数据的流程。
配合使用 Element-UI
的 table
组件进行分页查询
vue基础部分内容的笔记略过,如过你仍需要该阶段的学习,阅读官方的讲义或者移步:https://cn.vuejs.org/v2/guide/ 进行阅读和练习。
使用vue.js开发大型应用需要使用 webpack
打包工具,本节研究webpack的使用方法。
Webpack 是一个前端资源的打包工具,它可以将js、image、css等资源当成一个模块进行打包。
从图中我们可以看出,Webpack 可以将js、css、png等多种静态资源 进行打包
模块化开发
程序员在开发时可以分模块创建不同的js、 css等小文件方便开发,最后使用webpack将这些小文件打包成一个文
件,减少了http的请求次数。
webpack可以实现按需打包,为了避免出现打包文件过大可以打包成多个文件。
编译typescript、ES6等高级js语法
随着前端技术的强大,开发中可以使用javascript的很多高级版本,比如:typescript、ES6等,方便开发,
webpack可以将打包文件转换成浏览器可识别的js语法。
CSS预编译
webpack允许在开发中使用Sass 和 Less等原生CSS的扩展技术,通过sass-loader、less-loader将Sass 和 Less的
语法编译成浏览器可识别的css语法。
1、配置有些繁琐
2、文档不丰富
node.js
已经集成了npm工具,在命令提示符输入 npm -v 可查看当前npm版本,node可以直接去官网下载安装
设置包路径
npm config set prefix "C:\Program Files\nodejs\npm_modules"
npm config set cache "c:\Program Files\nodejs\npm_cache"
执行以下命令
npm install -g cnpm --registry=https://registry.npm.taobao.org
安装完成后执行命令 cnpm -v
node.js 安装包分为两种模式
本地安装
npm install --save-dev webpack 或 cnpm install --save-dev webpack
npm install --save-dev webpack-cli (4.0以后的版本需要安装webpack-cli)
全局安装
全局安装加-g,如下:全局安装就将webpack的js包下载到npm的包路径下。
npm install webpack -g 或 cnpm install webpack -g
安装 webpack 指定的版本:
进入webpacktest测试目录,运行:cnpm install --save-dev [email protected]
全局安装:npm install [email protected] -g
或 cnpm install [email protected] -g
通过本入门程序体会webpack打包的过程及模块化开发的思想。
通过入门程序实现对js文件的打包,体会webpack是如何对应用进行模块化管理。
对上边1+1=2的例子使用webpack进行模块化管理
在webpacktest01
目录下创建model01.js
将本程序使用的加法运算的js方法抽取到一个js文件,此文件就是一个模块 ,代码如下
//定义add函数
function add(x, y) {
return x+y;
}
//导出add函数
module.exports.add = add;
在webpacktest01
目录下创建main.js
,main.js
是本程序的js主文件,包括如下内容:
1、在此文件中会引用model01.js模块
2、引用vue.min.js(它也一个模块)
3、将html页面中构建vue实例的代码放在main.js中。
var {add} = require("./model01.js")
var Vue = require("./vue.min")
// 实例化Vue对象
//vm :叫做MVVM中的 View Model
var VM = new Vue({
el:"#app",//表示当前vue对象接管app的div区域
data:{
name:'黑马程序员',// 相当于是MVVM中的Model这个角色
num1:0,
num2:0,
result:0,
url:'http://www.itcast.cn'
},
methods:{
change:function(){
this.result = add(Number.parseInt(this.num1),Number.parseInt(this.num2));
}
}
});
上边将 mode01.js
模块及 main.js
主文件编写完成,下边使用 webpack
对这些js文件进行打包
1、进入程序目录,执行 webpack main.js -o build.js
,这段指令表示将 main.js
打包输出为 build.js
文件执行完成,观察程序目录是否出现 build.js
。
2、在创建一个html ,这里我命名为 vue_02.html
并 中引用 build.js
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>vue.js入门程序</title>
</head>
<body>
<div id="app">
{{name}}
<input type="text" v-model="num1">+
<input type="text" v-model="num2">=
<input type="text" v-model="result">
<button v-on:click="change">计算</button>
</div>
</body>
<script src="build.js"></script>
</html>
webpack-dev-server
开发服务器,它的功能可以实现热加载 并且自动刷新浏览器。
创建一个新的程序目录,这里我们创建 webpacktest02
目录,将 webpack
入门程序( webpacktest01
)的代码拷贝进来,并在目录下创建 src
目录、dist
目录,并将main.js和model01.js拷贝到src目录。
使用 webpack-dev-server
需要安装webpack、 webpack-dev-server 和 html-webpack-plugin三个包。
cnpm install webpackwebpack-dev-server html-webpack-plugin
安装完成,会发现程序目录出现一个package.json文件,此文件中记录了程序的依赖。
在package.json中配置script
"scripts": {
"dev": "webpack-dev-server --inline --hot --open --port 5008"
}
–inline:自动刷新
–hot:热加载
–port:指定端口
–open:自动在默认浏览器打开
–host:可以指定服务器的 ip,不指定则为127.0.0.1,如果对外发布则填写公网ip地址
此时package.json的文件内容如下:
{
"devDependencies": {
"html-webpack-plugin": "^3.2.0",
"webpack-dev-server": "^3.10.3"
},
"scripts": {
"dev": "webpack-dev-server --inline --hot --open --port 5008"
}
}
devDependencies:开发人员在开发过程中所需要的依赖。
scripts:可执行的命令
在 webpacktest02
目录下创建 webpack.config.js
, webpack.config.js
是 webpack
的配置文件。
在此文件中可以配置应用的入口文件、输出配置、插件等,其中要实现热加载自动刷新功能需要配置 html-webpack-plugin
插件。
html-webpack-plugin
的作用是根据 html
模板在内存生成 html
文件,它的工作原理是根据模板文件在内存中生成一个 index.html
文件。
将原来的 vue_02.html
作为模板文件,为了和内存中的 index.html
文件名区别,注意将 vue_02.html
中的script
标签去掉,内容如下:
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>vue.js入门程序title>
head>
<body>
<div id="app">
{{name}}
<input type="text" v-model="num1">+
<input type="text" v-model="num2">=
<input type="text" v-model="result">
<button v-on:click="change">计算button>
div>
body>
html>
在 webpack.config.js
中配置 html-webpack-plugin
插件
var htmlwp = require('html-webpack-plugin');
module.exports={
entry:'./src/main.js', //指定打包的入口文件
output:{
path : __dirname + '/dist', // 注意:__dirname表示webpack.config.js所在目录的绝对路径
filename:'build.js' //输出文件
},
plugins:[
new htmlwp({
//生成的页面标题首页
title: '首页',
//webpack-dev-server在内存中生成的文件名称,自动将build注入到这个页面底部才能实现自动刷新功能
filename: 'index.html',
//根据vue_02.html这个模板来生成(这个文件请程序员自己生成)
template: 'vue_02.html'
})
]
}
启动文件:
1、进入 webpacktest02
目录,执行npm run dev
2、使用webstorm,右键package.json
文件,选择 “Show npm Scripts”
打开窗口:
双击 dev
。
注意:dev 就是在 package.json
中配置的 webpack dev server
命令。
发现启动成功自动打开浏览器。
修改src中的任意文件内容,自动加载并刷新浏览器。
使用了 webpack
之后就不能采用传统js的调试方法在 chrome
中打断点。
webpack
将多个源文件打包成一个文件,并且文件的内容产生了很大的变化,webpack
提供 devtool
进行调试,devtool
是基于 sourcemap
的方式,在调试时会生成一个 map
文件,其内容记录生成文件和源文件的内容映射,即生成文件中的哪个位置对应源文件中的哪个位置,有了 sourcemap
就可以在调试时看到源代码。
配置如下
1、在webpack.config.js中配置:
devtool: 'eval‐source‐map',
devtool: ‘eval‐source‐map’,
var htmlwp = require('html‐webpack‐plugin');
module.exports={
entry:'./src/main.js', //指定打包的入口文件
output:{
path : __dirname+'/dist', // 注意:__dirname表示webpack.config.js所在目录的绝对路径
filename:'build.js' //输出文件
},
devtool: 'eval‐source‐map',
......
2、在js中跟踪代码的位置上添加debugger
一个例子:
在add方法中添加debugger
// 定义add函数
function add(x, y) {
debugger
return x + y
}
启动应用,刷新页面跟踪代码:
点击“计算” 即进入debugger代码位置,此时可以使用chrome进行调试了。
谷歌浏览器中先按下 F12
打开调试模式后在点击 计算
按钮进行触发代码中的 debugger
如果你根据黑马官方的项目讲义进行配置,并且一些环境遇到 命令无法找到
,不用怀疑,其实你的配置并没有错,因为黑马提供的PDF文档有的部分配置,大部分人都是直接复制的,而不会浪费时间去一个个的敲(也没必要)当你复制到 IDE 编辑器中的时候,看起来跟文档一点区别都没有,例如下面的例子:
从图片上可以看到,在IDE中看该配置没有任何问题,但是从外部的cmd中运行时,提示了未找到 webpack-dev-server
这个命令,但实际上博主已按网上的各种办法,例如将项目下的 node_modules
文件夹删除再重新 npm install --save
安装模块,但无果,仔细一看猜发现TM有其中一个横杠 -
不是正常的字符,导致无法找到该命令,原因猜测是该配置文件我是从讲义的PDF中直接复制导致的,但乍一眼看根本看不出问题。
建议用 JB系列的 IDE 替换项目文件夹下的 -
为 -
(仔细一看,这两个杠还是优点区别的。。)
本篇笔记也已全部替换。。
启动成功,虽然踩坑花了不少时间,但是阅读错误信息的能力感觉提升了一些。
CMS系统使用Vue-cli脚手架创建, Vue-cli
是 Vue
官方提供的快速构建单页应用的脚手架,github
地址:
https://github.com/vuejs/vue-cli(有兴趣的同学可以参考官方指导使用vue-cli创建前端工程),本项目对 Vue-cli
创建的工程进行二次封装,下边介绍CMS工程的情况。
如果我要基于Vue-Cli创建的工程进行开发还需要在它基础上作一些封装,导入课程资料中提供Vue-Cli封装工程。
资料/xc-ui-pc-sysmanage.7z
拷贝到UI工程目录中,并解压,用WebStorm
打开 xc-ui-pc-sysmanage
目录。
package.json记录了工程所有依赖,及脚本命令:
开发使用:npm run dev
打包使用:npm run build
webpack.base.conf.js
就是 webpack 的 webpack.config.js
配置文件,在此文件中配置了入口文件及各种Loader
。webpack 是通过vue-load
解析 .vue
文件,通过 css-load
打包 css
文件等。
main.js
是工程的入口文件,在此文件中加载了很多第三方组件,如:Element-UI、Base64、VueRouter 等。
index.html
是模板文件。
src目录下存放页面及js代码。
下级目录以模块名命名,下边以cms举例:
优点:
1、用户操作体验好,用户不用刷新页面,整个交互过程都是通过Ajax来操作。
2、适合前后端分离开发,服务端提供http接口,前端请求http接口获取数据,使用JS进行客户端渲染。
缺点:
1、首页加载慢
单页面应用会将js、 css打包成一个文件,在加载页面显示的时候加载打包文件,如果打包文件较大或者网速慢则
用户体验不好。
2、SEO不友好
SEO(Search Engine Optimization)为搜索引擎优化。它是一种利用搜索引擎的搜索规则来提高网站在搜索引擎
排名的方法。目前各家搜索引擎对JS支持不好,所以使用单页面应用将大大减少搜索引擎对网站的收录。
总结:本项目的门户、课程介绍不采用单页面应用架构去开发,对于需要用户登录的管理系统采用单页面开发。
在model目录创建 cms模块的目录结构
在page目录新建page_list.vue,扩展名为.vue。
.vue文件的结构如下:
测试页面显示...
在页面的template
中填写 “测试页面显示…”。
注意:template
内容必须有一个根元素,否则vue会报错,这里我们在template
标签内定义一个div
。
在 cms
目录下创建 page_list.vue
页面。
现在先配置路由,实现 url 访问到页面再进行内容完善与调试。
1、在cms的router下配置路由
import Home from '@/module/home/page/home.vue';
import page_list from '@/module/cms/page/page_list.vue';
export default [{
path: '/cms',
component: Home,
name: 'CMS内容管理',
hidden: false,
children:[
{path:'/cms/page/list',name:'页面列表',component: page_list,hidden:false}
]
}
]
2、在base目录下的router导入cms模块的路由
// // 导入路由规则
import HomeRouter from '@/module/home/router'
import CmsRouter from '@/module/cms/router'
// 合并路由规则
concat(HomeRouter)
concat(CmsRouter)
3、测试
启动工程,刷新页面,页面可以外正常浏览,并且看到“测试页面显示…”字样
本功能实现的页面列表,用户可以进行分页查询、输入查询条件查询,通过查看 Element-UI
库,我们需要Table
表格、Form
表单 及Pagination
分页组件。
进入Element-UI官方,找到 Table
组件,拷贝源代码到 vue
页面中,如下:
测试:
通过查看代码发现,el-table
组件绑定了tableData
模型数据,tableData
模型数据在script
标签中定义。
根据需求完善页面内容,完善列表字段,添加分页组件。
查询
测试
在cms模块的 api
目录定义cms.js
,
在 cms.js
中定义如下js方法,此方法实现 http
请求服务端页面查询接口。
//public是对axios的工具类封装,定义了http请求方法
import http from './../../../base/api/public'
//页面查询
export const page_list = (page,size,params) => {
//定义方法,请求服务端查询接口
return http.requestQuickGet('http://localhost:31001/cms/page/list/'+page+'/'+size)
}
axios
实现了http
方法的封装,vue.js
官方不再继续维护 vue-resource
,推荐使用 axios
。
前端 page_list.vue
页面导入cms.js,调用js方法请求服务端页面查询接口。
请求的参数根据后端的 Swagger
文档进行配置 http://localhost:31001/swagger-ui.html
配置
测试 上边的代理 ,结果 报错如下 :
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin
'http://localhost:11000' is therefore not allowed access.
原因:浏览器的同源策略不允许跨域访问,所谓同源策略是指协议、域名、端口相同。
解决:采用 proxyTable
解决。
vue-cli提供的解决vue开发环境下跨域问题的方法,proxyTable的底层使用了 http-proxymiddleware
(https://github.com/chimurai/http-proxy-middleware),它是http代理中间件,它依赖 node.js
,
基本原理是用服务端代理解决浏览器跨域:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hUU8JtHj-1595563918814)(C:\Users\root\AppData\Roaming\Typora\typora-user-images\image-20200319111906042.png)]
1、访问页面http://localhost:11000/
2、页面请求http://localhost:11000/cms
由于url由http://localhost:31001/cms…改为“http://localhost:11000/cms.",所以不存在跨域
3、通过proxyTable由node服务器代理请求 http://localhost:31001/cms.
服务端不存在跨域问题
具体的配置如下:
1、修改api
方法中url
的定义
请求前加/api前缀
//public是对axios的工具类封装,定义了http请求方法
import http from './../../../base/api/public' //ES6 导入
let sysConfig = require('@/../config/sysConfig')
let apiUrl = sysConfig.xcApiUrlPre
//页面查询
export const page_list = (page,size,params) => {
//定义方法,请求服务端查询接口
return http.requestQuickGet(apiUrl + '/cms/page/list/'+page+'/'+size)
}
2、在 config/index.js
下配置 proxyTable
'/api/cms': {
target: 'http://localhost:31001',
pathRewrite: {
'^/api': ''//实际请求去掉/api
}
1、定义分页视图
2、定义数据模型对象
data() {
return {
list:[],
total:0, //数据总量
params:{
page:1,//默认页码
size:10//默认每页显示个数
}
}
},
3、定义分页方法,接收页码参数
//触发分页参数变动
handleSizeChange(val) {
this.params.size = val
console.log(`每页 ${val} 条`);
},
handleCurrentChange(val) {
this.params.page = val
console.log(`当前页: ${val}`);
},
//分页查询,接收page页码
changePage(){
this.query()
},
//查询
query:function () {
//调用服务端接口
cmsApi.page_list(this.params.page, this.params.size).then((res) =>{
//将res结果数据赋值给数据模型对象
this.list = res.queryResult.list
this.total = res.queryResult.total
})
}
修改完毕,分页测试效果如下
目前实现的功能是进入页面点击查询按钮向服务端表求查询,实际的需求是进入页面立即查询。
那么如何实现?
这要用到 vue
的钩子函数,每个 Vue
实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM
并在数据变化时更新 DOM
等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会 。
通常使用最多的是 created
和 mounted
两个钩子:
created
:vue实例已创建但是DOM元素还没有渲染生成。
mounted
:DOM元素渲染生成完成后调用 。
本例子在两个方法的任意一个都满足需求:
添加如下代码:
mounted() {
//默认查询页面
this.query()
}
重新刷新页面。
参考 “讲义–>前后端请求响应流程.png”,如下:
根据图中所示,我们总结流程如下:
1、在浏览器输入前端url
2、前端框架 vue.js
根据 url
解析路由,根据路由找到 page_list.vue
页面
3、首先执行 page_list.vue
中的钩子方法
4、在钩子方法中调用 query
方法。
5、在 query
方法中调用 cms.js
中的 page_list
方法
6、cms.js
中的 page_list
方法通过 axios
请求服务端接口
7、采用 proxyTable
解决跨域问题,node.js
将请求转发到服务端(http://localhost:31001/cms/page/list)
8、服务端处理,将查询结果响应给前端
9、成功响应调用 then
方法,在 then
方法中处理响应结果,将查询结果赋值给数据模型中的total和list变量。
10、vue.js
通过双向数据绑定将list数据渲染输出 。
作者: LCyee ,全干型代码
自建博客:https://www.codeyee.com
记录学习以及项目开发过程中的笔记与心得,记录认知迭代的过程,分享想法与观点。
CSDN 博客:https://blog.csdn.net/codeyee
记录和分享一些开发过程中遇到的问题以及解决的思路。
欢迎加入微服务练习生的队伍,一起交流项目学习过程中的一些问题、分享学习心得等,不定期组织一起刷题、刷项目,共同见证成长。