1. VUE CLI 相关
1.1 vuecli-脚手架的介绍与安装
-
Vue cli是一个官方发布的vue.js项目脚手架
-
受用vue-cli可以快速搭建Vue开发环境以及对应的webpack配置
-
Vue CLI使用前提 - Node与Webpack
-
安装Node.js:可以在官网中下载安装:http://nodejs.cn/download/
-
检测安装的版本:默认情况下自动安装Node(要求8.9版本以上)和NPM
-
-
在cmd中安装Vue脚手架:npm install -g @vue/cli
官网:https://cli.vuejs.org/zh/guide/installation.html -
拉取 2.x 模板 (旧版本):Vue CLI >= 3 和旧版使用了相同的
vue
命令,所以 Vue CLI 2 (vue-cli
) 被覆盖了。如果你仍然需要使用旧版本的vue init
功能,你可以全局安装一个桥接工具npm install -g @vue/cli-init # `vue init` 的运行效果将会跟 `vue-cli@2.x` 相同 vue init webpack my-project # Vue CLI2初始化项目 Vue create my-project # Vue CLI3初始化项目
1.2 vuecli-初始化项目过程
- 现在终端输入:vue init webpack vuecli2test
-
vuecli2-CLI2的目录结构解析: https://www.jb51.net/article/154629.htm
-
下面依次简单简述下各目录和文件的作用:
build:webpack的配置,但这里主要是插件、项目运行相关的配置
config:也是webpack的配置,但不同是他主要是配置一些变量。和springboot的application.yml类似
node_modules:依赖保存的地方
src:写代码的地方
static:静态资源存放的地方,比如html,css等等,不过像图片的话是放在src/assets目录下的
.babelrc:babel的配置文件;babel是能将ES6转化成ES5的工具
.editorconfiig:文本配置,也就是像文本代码,如html,css,js等使用的编码,缩进格式,换行符的配置
.eslintignore:eslint是用来约束代码规范的,该代码也就是说哪些文件是不需要约束的,忽视掉
.eslintrc:eslint的配置文件
.gitigore:在上传到github时,哪些文件不需要上传
index.html:项目的入口页面
package.json:配置项目的基本信息和依赖的大概版本,这里强调一下,该文件的依赖版本只是指定大概的范围,具体真实下载的版本以package-lock.json为主
package-lock.json:记录node_modules依赖的真实版本
README.md:项目的说明书这样子 -
cli2生成的package.json中的脚本:
dev:是在开发时启动项目使用的脚本,一般都会使用webpack-dev-server作为本地服务器来热加载,方便测试
build:打包项目到dist,但我们仔细看,cli2这使用的是node命令去执行 build文件夹下的build.js来打包;在没学习node前,我们对JS的印象是,它得在html中进行引入使用,最终在浏览器才能进行执行
1.3 安装CLI错误和ESLint规范
-
当安装CLI出现错误,首先在cmd运行npm clean cache --force,再进行下载,如果还是报错,则将node卸载重新下载,如果还不行,则在打开cmd的时候用管理员权限打开进行上述操作或者进入下面文件夹删除红框所选文件夹,再进行安装
-
ESLint规范:https://www.jianshu.com/p/c021912d67d2
不想用ESLint规范,在下面文件中将true改为false
1.4 runtime-compiler与runtime-only的区别
通过这两种方法创建的脚手架,区别在于main.js(在src文件夹中)
-
在Vue实例中,runtime-compiler创建的项目中参数是:components和template
-
runtime-only创建的项目中参数为:render函数
runtimecompiler渲染过程:template -> ast --> render --> vdom -->UI
runtimeonly渲染过程:render --> vdom --> UI
-
runtimeonly:性能更高,代码量更少
-
runtime-only:将template在打包的时候,就已经编译为render函数
runtime-compiler:在运行的时候才去编译template
-
如果在之后的开发中,依然使用template,就需要选择runtime-compiler
如果开发使用的是.vue文件开发,那么可以选择runtime-only
组件是如何被渲染到页面中的?
- template —> ast —> render —> vDom —> 真实的Dom —> 页面
- ast:抽象语法树
- vDom:虚拟DOM
将rutimecompiler的main.js改成render函数类型
import Vue from 'vue'
import App from './App'
Vue.config.productionTip = false
/* eslint-disable no-new */
const cpn={
template:`<div>{{ message }}</div>`,
data(){
return {
message:'我是组件message'
}
}
}
new Vue({
el: '#app',
// components: { App },
// template: '<App/>'
render:function (createElement){
// 1. 通用法:createElement('标签',{标签的属性},['标签的内容']) 会替换前面app的内容
// return createElement('h2',{class:'box'},['hello world'])
// return createElement('h2',
// {class:'box'},
// ['hello world',createElement('button',['按钮'],)])
// 2. 传入组件对象
// return createElement(cpn)
return createElement(App)
}
})
1.4 VueCLI3创建项目与目录结构
-
输入命令创建项目:vue create testvuecli3
-
创建流程
-
如果在创建项目时不行要preset,可找到下面图片的文件,将其删除掉即可
-
目录结构
1.5 VueCLI3配置文件的查看和修改
-
输入:vue ui 启动一个GUI 进行 项目管理
-
在网页上导入项目,然后vue与vue-template-compiler插件的版本必须保持一致
-
在项目中创建一个文件vue.config.js,修改自己独有的一些配置
1.6 箭头函数的使用与this指向
1.6.1 箭头函数的基本使用
箭头函数:也是一种定义函数的基本方式
// 1. 定义函数的方式:function
const aaa=function (){
}
// 2. 对象字面量中定义函数
const obj={
bbb(){
}
}
// 3. ES6中的箭头函数
const ccc= (参数列表) => {}
1.6.2 箭头函数的参数和返回值
// 1. 参数问题
// 1.1 放入两个参数
const sum=(num1,num2)=>{
return num1+num2;
}
// 1.2 放入一个参数:省略括号
const power=num=>{
return num*num;
}
// 2. 函数中返回值的问题
// 2.1 函数代码块中有多行代码时
const test=()=>{
// 1. 打印hello world
console.log("Hello World");
// 2. 打印Hello Vuejs
console.log('Hello Vuejs');
}
// 2.2 函数代码块中只有一行代码时
// const mul=(num1,num2)=>{
// return num1+num2;
// }
const mul=(num1,num2)=>num1+num2;
// const demo=()=>{
// console.log("Hello Demo");
// }
const demo=()=>console.log("Hello Demo");
console.log(demo());
1.6.3 箭头函数中this的使用
// 什么时候使用箭头函数:准备把一个函数作为参数,传到另外一个函数里面的时候
// setTimeout(function (){
// console.log(this)
// },1000);
// setTimeout(()=>{
// console.log(this);
// },1000)
// 结论:箭头函数中的this引用的就是最近作用域中的this
const obj={
aa(){
setTimeout(function (){
console.log(this) // Window
});
setTimeout(()=>{
console.log(this); // Object对象
});
}
}
obj.aa();
const obj2={
bb(){
setTimeout(function (){
setTimeout(function (){
console.log(this) // Window
})
});
setTimeout(()=>{
console.log(this); // window
});
setTimeout(()=>{
setTimeout(function (){
console.log(this) // Window
});
setTimeout(()=>{
console.log(this) // obj
})
})
}
}
2. 路由和其映射关系
2.1 什么是路由
路由:就是通过互联的网络把信息从源地址传输到目的地址的活动,
路由器提供了两种机制:路由和传送
- 路由是决定数据包从来源到目的地的路径
- 传送将输入端的数据转移到合适的输出端
路由有一个非常重要的概念叫路由表:本质就是一个映射表,决定了数据包的指向
2.2 前端渲染和后端渲染和前端路由和后端路由
-
后端渲染:服务器直接生产渲染好对应的HTML页面, 返回给客户端进行展示。比如:jsp页面
好处:前端耗时少,即减少了首屏时间,模板统一在后端。前端(相对)省事,不占用客户端运算资源(解析模板)
坏处:占用服务器资源
-
前端渲染:浏览器中显示的网页中的大部分内容,都是由前端写的 js 代码在浏览器中执行,最终渲染出来的网页。也可以说后端返回JSON数据,前端利用预先写的html模板,循环读取JSON数据,拼接字符串,并插入页面。
好处:网络传输数据量小。不占用服务端运算资源(解析模板),模板在前端(很有可能仅部分在前端),改结构变交互都前端自己来了,改完自己调就行。
坏处:前端耗时较多,对前端工作人员水平要求相对较高。前端代码较多,因为部分以前在后台处理的交互逻辑交给了前端处理。占用少部分客户端运算资源用于解析模板
-
后端路由阶段:浏览器在地址栏中切换不同的 url 时,每次都向后台服务器发出请求,服务器响应请求,服务器渲染好整个页面, 并且将页面返回给客户端。这种情况下渲染好的页面, 不需要单独加载任何的js和css, 可以直接交给浏览器展示, 这样也有利于SEO的优化.
优点:分担了前端的压力,html和数据的拼接都是由服务器完成。
缺点:当项目十分庞大时,加大了服务器端的压力,同时在浏览器端不能输入制定的url路径进行指定模块的访问。另外一个就是如果当前网速过慢,那将会延迟页面的加载,对用户体验不是很友好。HTML代码和数据以及对应的逻辑会混在一起, 不利于编写和维护
-
前后端分离阶段:后端只提供API来返回数据,前端通过Ajax获取数据,并且可以通过JavaScript将数据渲染到页面中,这样做最大的优点是前后端责任的清晰,后端专注于数据上,前端专注于交互和可视化上;并且当移动端出现后,后端不需要进行任何处理,依然使用之前的一套API即可。
-
前端路由:是一种不用使浏览器刷新来进行页面跳转的技术,通常用来构建SPA(单页应用)
在处理多个页面时,服务器会对URL进行正则匹配,并且最后交给一个Controller来处理.最终生成HTML返回给前端
2.3 url的hash和HTML的history
2.3.1 url的hash
- url的hash就是锚点,本质上是改变window.location的href属性
- 可以通过直接赋值location.hash来改变href,但是页面不发生刷新
改变url的hash:
-
先在页面控制台输入:location.hash = ‘aaa’
-
页面路径:
-
控制台Network显示无请求
2.3.2 HTML的history
history.back()等价于history.go(-1)
history.forword()等价于history.go(1)
3. vue-router的学习
3.1 vue-router的安装和配置
vue-router是Vue.js官方的路由插件,它和Vue.js是深度集成的,适合用于构建当页面应用
- vue-router是基于路由和组件的
- 路由用于设定访问路径,将路径和组件映射起来
- 在vue-router的单页面应用中,页面的路径的改变就是组件的切换
-
vue-router的安装
- 输入 npm install vue-router --save
-
在模块化工程中使用它(因为是一个插件,所以可以通过Vue.use()来安装路由功能)
-
导入路由对象,并且调用 Vue.use(VueEouter)
-
创建路由实例,并且传入路由映射配置
-
在Vue实例中挂载创建的路由实例
// 配置路由相关的信息 import VueRouter from "vue-router"; import Vue from 'vue' // 1. 通过Vue.use(插件),安装插件 Vue.use(VueRouter); // 2. 创建路由对象 const routes=[ ] const router = new VueRouter({ // 配置路径和组件之间的映射关系 routes }) // 3. 将router对象传入到vue实例 export default router
-
3.2 路由映射配置和呈现出来
使用vue-router的步骤:
-
创建路由组件
-
src/components/Home.vue
<template> <div> <h2>我是首页</h2> <p>我是首页内容,哈哈哈哈</p> </div> </template> <script> export default { name: "Home" } </script> <style scoped> </style>
-
src/components/About.vue
<template> <div> <h2>我是关于</h2> <p>我是关于内容,哈哈哈哈</p> </div> </template> <script> export default { name: "About" } </script> <style scoped> </style>
-
-
配置路由映射:组件和路由映射关系
// 配置路由相关的信息 src/router/index.js import VueRouter from "vue-router"; import Vue from 'vue' import Home from '../components/Home' import About from '../components/About' // 1. 通过Vue.use(插件),安装插件 Vue.use(VueRouter); // 2. 创建路由对象 const routes=[ { path:'/home', component:Home }, { path:'/about', component:About } ] const router = new VueRouter({ // 配置路径和组件之间的映射关系 routes // routes 不能自定义 }) // 3. 将router对象传入到vue实例 export default router
-
使用路由:通过和标签
-
:该标签是vue-router中已经内置的组件,他会被渲染成一个标签
-
:该标签会根据当前的路径,动态渲染出不同的组件
-
在路由切换时,切换的是挂载的组件,其他内容不会改变,并且该标签的位置就是挂载组件的位置
<!-- src/App.vue --> <template> <div id="app"> <router-link to="/home">首页</router-link> <router-link to="/about">关于</router-link> <router-view></router-view> </div> </template> <script> export default { name: 'App' } </script> <style> </style>
-
3.3 路由的默认值和修改为 history模式
-
默认显示首页
-
路径去掉
3.4 router-link的其他属性
-
to:用于指定跳转的路径
-
tag:可以指定之后渲染成什么组件,比如将其渲染成button
<template> <div id="app"> <router-link to="/home" tag="button">首页</router-link> <router-link to="/about" tag="button">关于</router-link> <router-view></router-view> </div> </template>
-
replace:不会留下history记录,在使用之后不可以使用网页的后退键返回上一页面
<router-link to="/home" tag="button" replace>首页</router-link>
-
active-class:当对应的路由匹配成功时,会自动给当前元素设置一个router-link-active的class,设置active-class可以修改默认的名称
<template> <div id="app"> <!-- 1.直接在每一个上面直接改active-class="active" --> <!-- <router-link to="/home" tag="button" replace active-class="active">首页</router-link>--> <!-- <router-link to="/about" tag="button" replace active-class="active">关于</router-link>--> <!-- 2. 在路由中修改 --> <!-- <router-link to="/home" tag="button" replace>首页</router-link>--> <!-- <router-link to="/about" tag="button" replace>关于</router-link>--> <!-- 路由代码跳转 --> <button @click="homeClick">首页</button> <button @click="aboutClick">关于</button> <router-view></router-view> </div> </template> <script> export default { name: 'App', methods:{ // 通过代码的方式修改路径 vue-router homeClick(){ // push => pushState // this.$router.push('./home'); this.$router.replace('./home'); }, aboutClick(){ // this.$router.push('./about'); this.$router.replace('./about'); } } } </script> <style> /*.router-link-active{ router-link-active是默认名字 color:red; }*/ .active{ color:red; } </style>
修改active-class="active"方法二:路由中的配置:
3.5 vue-router-动态路由的使用
-
配置一个User.vue组件
<template> <div> <h2>我是用户界面</h2> <p>我是用户的相关信息,呵呵呵呵</p> <h2>{{userId}}</h2> </div> </template> <script> export default { name: "User", computed:{ userId(){ return this.$route.params.userId } } } </script> <style scoped> </style>
-
在App.vue中配置
<template> <div id="app"> <router-link to="/home">首页</router-link> <router-link to="/about">关于</router-link> <router-link :to="'/user/'+userId">用户</router-link> <router-view></router-view> </div> </template> <script> export default { name: 'App', data(){ return { userId:'lisi' } } </script> <style> .active{ color:red; } </style>
-
在index.js中配置路径
// 配置路由相关的信息 import VueRouter from "vue-router"; import Vue from 'vue' import Home from '../components/Home' import About from '../components/About' import User from '../components/User' // 1. 通过Vue.use(插件),安装插件 Vue.use(VueRouter); // 2. 创建路由对象 const routes=[ { path:'', redirect:'/home' }, { path:'/home', component:Home }, { path:'/about', component:About }, { path:'/user/:userId', component: User } ] const router = new VueRouter({ // 配置路径和组件之间的映射关系 routes, // routes 不能自定义 mode:"history", linkActiveClass:'active' }) // 3. 将router对象传入到vue实例 export default router
3.6 vue-router-打包文件的解析
3.7 vue-router-路由懒加载的使用
-
懒加载:用到时再加载
-
路由懒加载:主要作用是将路由对应的组件打包成一个个的js代码块,只有这个路由被访问到的时候,才加载对应的组件
-
懒加载的方式
-
结合Vue的异步组件和webpack的代码分子
const Home=resolve=>{require.ensure(['../components/Home.vue'],()=>{resolve(require('../components/Home.vue'))})}
-
AMD写法
const About=resolve=>require(['../components/About.vue'],resolve);
-
在ES6中,我们可以有更加简单的写法来组织Vue异步组件和webpack的代码分割
const Home=()=>import('../components/Home.vue')
-
3.8 vue-router-路由的嵌套使用
-
嵌套路由:一个路径映射一个组件,访问这两个路径也会分别渲染两个组件
-
实现嵌套路由的步骤:
-
创建对应的子组件,并且在路由映射中配置对应的子路由
// HomeVews 组件 <template> <div> <ul> <li>新闻1</li> <li>新闻2</li> <li>新闻3</li> <li>新闻4</li> </ul> </div> </template> // HomeMessage组件 <template> <div> <ul> <li>消息1</li> <li>消息2</li> <li>消息3</li> <li>消息4</li> </ul> </div> </template>
// 配置路由相关的信息 import VueRouter from "vue-router"; import Vue from 'vue' // import Home from '../components/Home' // import About from '../components/About' // import User from '../components/User' // 懒加载方式 const Home=()=>import('../components/Home') const HomeNews=()=>import('../components/HomeNews') const HomeMessage=()=>import('../components/HomeMessage') const About=()=>import('../components/About') const User=()=>import('../components/User') // 1. 通过Vue.use(插件),安装插件 Vue.use(VueRouter); // 2. 创建路由对象 const routes=[ { path:'', redirect:'/home' }, { path:'/home', component:Home, children:[ { // 默认路径 path:'', redirect:'news' }, { path:'news', // 子组件路径不需要加 '/' component:HomeNews }, { path:'message', component: HomeMessage } ] }, { path:'/about', component:About }, { path:'/user/:userId', component: User } ] const router = new VueRouter({ // 配置路径和组件之间的映射关系 routes, // routes 不能自定义 mode:"history", linkActiveClass:'active' }) // 3. 将router对象传入到vue实例 export default router
-
在组件内部使用标签
// 在Home.vue进行配置子路径 <template> <div> <h2>我是首页</h2> <p>我是首页内容,哈哈哈哈</p> <router-link to="/home/news">新闻</router-link> <router-link to="/home/message">消息</router-link> <router-view></router-view> </div> </template>
-
3.9 vue-router-参数传递
-
传递参数的两种类型:params和query
-
params的类型:
- 配置路由格式:/router/:id
- 传递的方式:在path后面跟上对应的值
- 传递后形成的路径:/router/123 , /router/abc
-
query的类型:
-
配置路由格式:/router,也就是普通配置
-
传递的方式:对象中使用query的key作为传递方式
-
传递后形成的路径:/router?id=123, /router?id=abc
// 新建一个组件:Profile.vue <template> <div> <h2>我是profile组件</h2> <h2>{{$route.query.name}}</h2> <h2>{{$route.query.age}}</h2> <h2>{{$route.query.height}}</h2> </div> </template> // 在App.vue中配置 <router-link :to="{path:'/profile',query:{name:'zhiyu',age:18,height:1.88}}">档案</router-link> // 在index.js中配置路径
-
使用代码跳转:
3.10 router和route的由来
- 所有的组件都继承自vue类的原型
- $router为VueRouter实例,想要导航到不同的URL,则使用router.push()方法
- $route为当前router跳转对象里面可以获取name,path,query,params等
3.11 vue-router-全局导航守卫
官网学习:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html
created() { // 创建出来组件会会回调的
console.log("created");
},
mounted() { // 在template挂载在整个DOM上会回调的
console.log("mounted");
},
updated() { // 当界面发生刷新时会回调的
console.log("updated");
页面title改变案例:
-
在每个组件里面加一个方法
created() { // 创建出来组件会会回调的 console.log("created"); document.title='首页'; },
-
路由方法
// 在路径中添加一个属性meta, { path:'/home', component:Home, meta: { title: '首页' }, }, // 然后在index.js中添加以下代码
3.12 vue-router–keep-alive及其问题
-
keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染,减少加载时间及性能消耗,提高用户体验性
-
router-view也是一个组件,如果直接被包在keep-alive里面,所有路径匹配到的视图组件都会被缓存
-
下图所示编写可以减少组件的频繁创建于销毁,提高运行速度
-
点击其他页面之后,点击首页还是与原来一样
-
去掉默认路径
-
使用组件导航
-
-
activated:在 keep-alive 组件激活时调用,该钩子函数在服务器端渲染期间不被调用
deactivated:在 keep-alive 组件停用时调用,该钩子在服务器端渲染期间不被调用
-
被包含在 keep-alive 中创建的组件,会多出两个生命周期的钩子: activated 与 deactivated
-
使用 keep-alive 会将数据保留在内存中,如果要在每次进入页面的时候获取最新的数据,需要在 activated 阶段获取数据,承担原来 created 钩子函数中获取数据的任务。
-
注意: 只有组件被 keep-alive 包裹时,这两个生命周期函数才会被调用,如果作为正常组件使用,是不会被调用的,以及在 2.1.0 版本之后,使用 exclude 排除之后,就算被包裹在 keep-alive 中,这两个钩子函数依然不会被调用!另外,在服务端渲染时,此钩子函数也不会被调用。
-
-
keep-alive属性:
include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
max - 数字。最多可以缓存多少组件实例。
项目代码:
链接:https://pan.baidu.com/s/1g9oD4UeDFiU0iub93ABNbA
提取码:g20w