后端的vue笔记
下面是我作为后端对vue的看法
前言
vue知识点总结,我认为的后端需要了解的程度,学习永远是学的多,会的少。学的尽可能的往深里研究,毕竟以后也没这机会了
前置
需要掌握一定的ES6相关语法,我这里也总结了一点,可以去网上了解更多
es6属性的简写
什么时候方法的()可以省略
必须满足两个条件,类似下图
- 事件监听
- 方法没有参数
当条件为false的时候,v-if不会存在dom中,v-show会出现,加了一个样式dispaly:none。就是F12查看的时候有没有 使用建议:如果频繁切换使用v-show,只切换一次v-if
let i in 遍历的对象,此时i是当前索引 let i of 遍历的对象,此时i是当前对象
如果需要以下三个需求应该怎么写代码
- 筛选数组中小于100的数字
- 将筛选出的结果x2
- 将结果进行相加
最直接的方法就是套的写,官方叫做链式编程,也叫函数式编程
1 | let total = nums.filter(function(n){ |
如果了解过Java8新特性的也可以采用lambda编程,更加简洁明了
1 | const nums = [10,20,15,30,22] |
let和var
总结一句话:以后用let不要用var
原因:事实上var的设计可以看成JavaScript语言设计上的错误,这种错误多半不能修复和移除,有个人修复了这个问题,他添加了一个关键字:let,所以可以将let看作更完美的var
为什么不推荐用var?
js没有像Java一样是强类型语言,所以涉及一个作用域的问题。Java中可以在for循环中每次都int i,但var i不行。
js中使用var来证明一个变量,作用域主要和函数的定义有关
针对于其他定义来说是没有作用域的,比如if,for,所以开发中会遇到一些问题
虽然说闭包可以解决作用域的问题,但是会影响工作效率,程序员应该把时间用到业务逻辑上,不应该承担语言所带来的缺陷。
const
修饰变量,const也就相当于Java中的final,不可修改,必须初始化。一般用于定义Vue对象,和一些常量。其中的标识(zhi)符不能改变其中指向,能改变指向的值。经常使用的const app = new Vue(){}
axios
相较于jq的ajax来说,axios更专注于网络请求,比jq封装的异步请求更加专业
返回的数据data才是服务器真实的数据,其他数据都是axios追加的数据
await
只能用在async
修饰的方法中,好处是可以不用写then方法,返回值就是结果,不加修饰的话就是返回一个promise
对象,这里标记的三个陌生名词是ES的语法,如果遇到这个写法,那就是国际写法,我这里简单总结了几点前置概念有需要的看看
promise
目的
:为了解决回调地狱的问题,ES6新增了promise的概念
概念
;是一个构造函数,new一个promise,该对象代表一个异步操作,可以在该对象的原型对象上.then()方法
.then()的作用为预先指定成功和失败的回调函数,比如p.then(result => {}, error => {}),成功是必选的,失败是可选的
如果.then()返回了一个新的promise对象,则可以通过下一个.then继续进行处理,通过对then的链式调用,来解决回调地狱的问题,在链式调用的操作过程中发生了错误可以通过catch来对方法进行捕获处理
回调地狱
可以理解为多层套娃,如图,这种代码的耦合性强,会产生大量冗余的代码
async / await
是ES8的语法,简化promise的异步操作,在async / await出现之前,只能使用链式.then的方式来处理promise的异步操作,此方式解决了回调地狱的问题,但会造成代码冗余的问题,代码如下
使用方式
await用于方法内部,用作修饰之后就不在返回一个promise对象,而是其中的内容
注意事项
- 如果方法内部用到了await则方法外必须使用async进行修饰,否则会报语法错误
- 第一个await之前的代码会同步执行,之后修饰的会异步执行
1 | 结果 |
vue2中全局配置axios
main.js文件中
1 | //导入axios |
vue3中全局配置axios
为什么要全局配置?
在实际项目开发中,几乎每个组件都会用到axios去发送数据请求,那么会有如下问题
- 每个组件都需要导入
- 每次发请求都需要写全部路径
如何全局配置
在main.js中,通过app.config.globalPropeties全局挂载axios
拦截器
每次发起ajax请求和得到响应的时候会自动触发
应用场景
- token认证
- loading效果
如何配置axios.interceptors.request.use(成功回调函数,失败回调函数)
失败的回调可以忽略
示例代码—验证token
1 | import axios from 'axios' |
proxy跨域问题
如果没有开启CROS跨域资源共享,如下接口i昂无法请求成功
解决方案
- 后端帮忙处理跨域问题
- 使用代理的方式进行解决
附上一段我开发过程中企业使用的代码
在vue.config.js中,声明如下配置1
2
3
4
5
6
7
8
9
10
11
12
13
14
15module.exports = {
devServer: {
port: 8888,
proxy: {
"/api": {
target: "http://localhost:8088", // 要请求的后台地址
ws: true, // 启用websockets
changeOrigin: true, // 是否跨域
pathRewrite: {
"^/api": "/" // 这里理解成用‘/api’代替target里面的地址,后面组件中我们掉接口时直接用api代替
}
}
}
}
}
EventLoop
js是单线程语言,如果前一个任务耗时则会使后面的一直等待
同步任务:不耗时的任务,由js主线程次序执行
异步任务:耗时的任务,js委托给宿主环境执行,执行完之后会通知js主线程执行回调函数。
执行过程
主线程—>异步(执行完哪个就把哪个放到队列中,主线程执行完之后会按照队列中的顺序执行)
宏任务和微任务
它们都是异步任务,但有执行先后顺序,交替执行,先宏后微
宏任务:ajax、计时器、文件操作
微任务:promise.then .catch .finally、process.nextTick
执行顺序举例
webpack
vue在利用脚手架构建项目的时候已经实现了一套默认的配置。但有些东西还是需要去了解下
概念
前端模块化打包工具。兼容ES6语法,用来打包,就是将浏览器不认识的语法打包成认识的
知识点
- webpack默认只能处理js文件,而且只能处理一般的js语法,让它拥有强大的打包能力是基于各种loader,如果处理高级的js语法,则需要安装babel-loader
- webpack的插件很多,如果有不知道功能的百度下就可以
- sourceMap显示报错目标行号,生产建议不用。或者配置生产行号点不进去源码
- base64适合小文件的处理,好处是减少请求,提高性能
- 一切皆模块,都可以写入为js的格式
SPA
单页面应用程序(single page application),指一个web网站仅有一个html页面
优点
- 良好的交互体验,内容改变不需要重新加载整个页面,没有页面跳转
- 良好的前后端分离模式。API接口复用,专注于页面渲染,有利于前端工程化的发展
- 减轻服务器的的压力。服务端只提供数据,不负责页面生成和逻辑处理,吞吐能力提升
缺点
- 首屏加载慢、不利于SEO
为什么要介绍SPA
vue可以通过vite和vue-cli去创建SPA项目
ref
虽然vue中不建议程序员直接操作DOM元素,但也提供了方法,可以在不依赖JQ的情况下操作DOM元素和组件实例
在每个vue实例对象中都会包含一个$refs,使用示例
1 | <h3 ref="myh3">自定义</h3> |
this.$nextTick(callback),将括号中的代码延期执行,当dom完全渲染之后调用
数组
foreach的缺点,无法被停止,不像Java中有个break,所以性能不是很好
some弥补了这一缺点,再找到元素后,可以通过return true来终止循环
every可以判断是否全选(结合计算属性)
1 | arr.every(item => item.state) //返回一个true |
reduce把每一次循环的结果累加起来
1 | arr.reduce((累加变量sum,当前循环项item) =>{return 计算过程},初始值) |
vue相关
- 概念
- 优点
- 全家桶
概念
构架用户界面的一个前端框架
优点
- 渲染页面结构更加方便(数据驱动视图)
- 提供独特的书简绑定机制,轻松处理交互行为
- 工作重心转移,不在放在处理DOM上
全家桶
- vue(核心库)
- vue-router(路由)
- vuex(状态管理)
- vue组件库(快速搭建UI效果的方案)
特性
1、数据驱动视图(单向数据绑定)vue起到了监听数据变化的作用
数据的变化会驱动视图自动更新
2、双向数据绑定
辅助开发者在不操作DOM的前提下,自动把用户填写的内容同步到数据源中
MVVM(Model-View-ViewModel)
实现两大特性的核心原理
工作原理
vue使用
引入vue.js,在<script>
中new vue对象,如下图
常用指令
内容渲染:v-text、{{定义的变量}}
、v-html
属性绑定:v-bind(简写为英文状态下的冒号:
)— 单向绑定
事件绑定:v-on(简写为@)
事件对象:$event(不常用)
事件修饰符:@click.prevent(阻止对象的默认行为)@click.stop(阻止对象冒泡)
按键修饰符:@keyup.esc(按键盘的Esc执行相应方法)
双向绑定指令:v-model(表单元素才有意义,保证数据内外同步)
v-model.number(获取到的值转为number类型).trim(去除空白).lazy(失去焦点值发生变化)
条件渲染:v-if(初始状态为false,常用) | v-show(添加display:none样式,适合频繁变换的情况)
列表渲染指令:v-for 示例<v-for="(item,index) in json">
官方建议:用v-for绑定key,默认为id值,不能将索引作为key,原因:不用key不具有强关联关系,它只是记住当前位置,加了之后会与内容进行绑定。
过滤器
vue2支持,vue3砍了,简单了解下
常用于文本的格式化,插值和v-bind里使用
{{ message | function}}
呈现function的返回值 “ | “叫做管道符,function定义到fitters节点下
一定要有返回值 | 调用采取就近原则,优先私有过滤器
监听器
监听数据的某些变化,如图,username变化之后会执行username方法,其中有个属性immediate默认值为false,如果为true则进入页面就会调用一次侦听器,同样的开启deep进行深度监听,可以监听到对象中属性的变化
应用场景:用户名是否被占用,请求接口返回用户名是否存在
计算属性
- computed,执行一系列运算后,最终得到一个属性值。用于复用
- 本质是一个function函数,可以实时监听data中的变化,并return一个计算的值(return是必须的)
- 相较于method的区别是,计算的结果会被缓存,当再次被使用的时候如果数据没有变化,那么方法将不会被调用,调用的时候按照一个变量去调用,如下图应该为
{{ plus }}
,而不是{{ plus() }}
vue-cli
- 单页面应用程序:只有一个html,其余由js,css等支撑
- vue-cli可以快速搭建单页面应用,简化了程序员webpack创建工程化vue项目的过程,相当于springboot,减免了ssm的一些配置,程序员可以更专注于业务
- 脚手架,官方提供的快速生成vue工程化项目的工具
优点
- 开箱即用
- 基于webpack
- 功能丰富且易于拓展
- 支持vue2和vue3
利用cli构建项目
安装vue-cli、创建项目
1 | npm install -g @vue/cli |
目录结构如下
怎么跑起来的
通过main.js吧App.vue渲染到index.html指定区域中(vue2与vue3有些许不同)
vue2
1 | //导入vue包,得到vue的构造函数 |
vue3
1 | //按需导入createApp函数,用来创建单页面应用实例 |
vue运行过程
template—>解析成 ast(抽象语法树)—>编译成 render —>转成 虚拟dom —>转成真实dom—UI
runtime-only直接就到了render阶段,所以快,性能更高,代码量更少
vue的组成
vue文件是一个组件,由三部分构成。组件时UI结构的复用
1 | <template> //html </template> |
template—>模板结构,存放html结构
script—>js语句
- 其中包含data节点,存放定义数据
- methods节点,存放方法
- emits存放自定义事件
style—>样式
组件的注册方式
全局注册和局部注册,先注册后使用,推荐使用大驼峰命名
顾名思义,全局表示任意一个组件都可以使用,局部只可以在指定范围内使用
组件的使用
- 导入组件 import 组件名 from ‘组件路径’
- 使用components来注册组件
- 以标签的形式使用
组件库
在实际开发中,前端开发者可以把自己开发的.vue组件整理打包发布为npm的包,以供他人下载和使用。这种现成组件就叫vue的组件库
与bootStrap的区别
bootStrap只提供了原材料(html+css+js),还需要开发者进行组装和改造
vue组件库遵循了vue语法,高度定制的现成组件,开箱即用
常用组件库
PC端:Element UI、View UI
移动端:Mint UI、Vant
Element UI
饿了么开源的一套PC端vue组件库。支持vue2+vue3
vue2:Element UI
vue3:Element Plus
prop
- prop可以使公共组件自定义初始值,提高组件复用性
- 定义一个组件后,导入该组件后赋予其属性
<test msg="content"></test>
- prop中的属性也可以直接按照插值中去使用,比如
{{ msg }}
- prop是只读的,不可以被直接修改,需要转存到data中
- 相关属性:defalut,给定一个默认值。type:给定一个类型。required:是否为必填项
- 定义类型的时候不只可以指定一个类型,还可以指定多个可能的类型,总共有8种基础校验类型:String | Number | Boolean | Array | Object | Date | Function | Symbol,常见写法如下
1
2
3
4title: {
type: [Number,String]
defalut: 0
} - 在绑定属性的时候,如果数据类型定义为大驼峰,则绑定属性推荐用-去进行来连接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<component
v-for="item in arrs"
:key="item.id"
:user-name:"item.name"
></component>
//另一个组件
data() {
return {
key: {
type:String
default: ''
}
userName: {
type:String
default: ''
}
}
}
为什么data中需要传一个函数?
假如有一种情况,你定义了一个计数器组件,点击增加或者减少互不影响,为什么,这时候函数的作用就体现出来了,每一次使用组件的时候总会调用一个return去返回一个新的对象,所以是互不影响,这也是为什么使用函数的原因。
组件之间的通信
父 —> 子(自定义属性)
子 —> 父(自定义事件$emit)
父 <—> 子(组件上的v-model)
兄弟之间(EventBus,组件离得远的都可以用)
后代关系(provide & inject)
全局数据共享
vuex:是终极的组件之间的数据共享方案。在企业级vue的项目开发中,vuex可以让组件之间的数据变得高效、清晰、易于维护,如图所示,左侧没有使用vuex,比较混乱。右侧使用了vuex,有一个专门管理数据的地方
动态组件
动态切换组件的显示和隐藏
vue提供了一个默认的<compents>
组件,占位符,is属性,写哪个渲染哪个
在切换之后会遇到重新渲染的问题,可以使用keep-alive标签来避免组件销毁,在浏览器中会被缓存
1 | <keep-avlive> |
keep-alive有独自的生命周期函数,可以被频繁触发
当组件被缓存时,会触发组件的deactivated声明周期函数
当组件被激活时,会触发组件的activated生命周期函数
includes属性与exclude属性(但只能同时存在一个)
生命周期
创建—运行—销毁,指一个时间段
生命周期有很多的钩子函数,不论是谁的生命周期也都是从创建到销毁,之前的servlet,线程之类的也都一样,很多都是相通的。通过钩子函数可以了解到元素分别在不同的函数中加载情况,这样的话可以自定义函数选择在那个生命周期中加载。(自己写下相关代码会更清楚)
beforecreated:el和data均未加载
created:data完成初始化,el没有。常用于异步获取数据时候使用
beforemount:完成el和data初始化
mounted:完成挂载,将内存中的HTML渲染到浏览器中,此时可以操作DOM(最早操作DOM的阶段)
updated:可以操作数据变化后的最新DOM
插槽
一般使用居多,定义较少,不是专业前端了解下就可以了,封装组件的时候会被用到,实现UI结构的复用,把不确定和希望用户自定义的部分叫做插槽
用slot占位,供用户自定义使用(联想到小霸王游戏机,插哪个玩哪个)
v-slot简写为#
默认情况下名称为default
需要作用域template标签中
具名插槽:具有名字的插槽。没有指定名字的插槽叫做”default”<slot name=""></slot>>
传参解构
1 | //插槽 |
自定义指令
官方的够用了,了解即可
官方提供了一些指令如:v-if、v-for、v-model、v-text等指令,除此之外,开发者还可以自定义指令
私有自定义指令:组件中自己用
全局自定义指令:全局都可以用
关键字directives声明私有自定义指令,与method平级,当指令被绑定到元素中时,会自动触发bind函数
比如定义的时候为color,用的时候为v-color
bind函数只会调用一次,update函数则会在dom每次更新的时候被调用
如果bind和update逻辑完全相同,那么可以简写
vue3调用方式
全局自定义指令Vue.directive,需要放到main.js中
ESlint
用来约束代码风格。坑爹东西,搭配插件后让强迫症受不了,我最后是把它关了,帮你修正代码中的格式错误,有错误不让运行
比如他会把单引号在你保存的时候变为双引号,每一句结束都要加上;
号,还得花时间去设置,我是拜拜了
如果往后公司要求,那就按公司来,公司一般也都设置好了一套规则,不用自己去设置,遭不住也得遭了
配置过程
- 配置项,在创建项目的过程中,选择eslint
- 一般选标准配置
- on save表示保存的时候会校验,另一个表示提交的时候会校验,一般选第一个
- 创建完项目之后会出现一个eslint的js文件
- 可以在其中的rules中配置一些规则
官方语法规则见:ESLint中文文档
需要掌握当编辑器报错的时候,知道是由于格式引起的,还能定位到哪一行
路由
也是vue中一个比较重要的概念,用来指定hash地址和组件的对应关系。路由的本质就是对应关系
后端路由
请求方式、请求地址、function处理函数的对应关系
前端路由
在SPA项目中,利用前端路由实现组件之间的切换
工作方式
- 点链接(触发)
- url地址栏发生变化
- 前端路由监听到hash地址的变化
- 将hash地址的组件渲染到组件中
实际上vue-router已经提供了封装,是vue官方给出的一个路由解决方案,可以轻松管理SPA页面组件之间的切换
vue-router3与vue-router4的最主要区别:创建路由模块的方式不同,在vue2的项目中只能使用vue-router3的路由
vue-router3
1 | // 导入vue2的构造函数 |
vue-router4
1 | //按需导入需要的方法 |
- 安装路由模块
- 创建路由模块
- 导入并挂载
- 声明地址和占位符
src下创建router文件夹创建index.js文件,其中写入以下代码
1 | // 导入vue和vuerouter的包 |
去main.js中使用,又叫挂载
在vue-router3中挂载方式为
1 | // 导入路由模块 |
在vue-router4中挂载方式为
1 | const app = craeateApp(App) |
如果名称一致可以简写为router替代router: router
导入模块可简写为import router from ‘./router’,因为默认导入模块中的index.js文件
当访问链接时会自动跳转到对应的组件,使用router-link来代替a标签,实际上渲染出来也是a标签
1 | <a href="#/C1">C1</a> => <router-link to="/C1">C1</router-link> |
常见用法
路由重定向,避免用户看见空页面
{ path: “/“, redirect: ‘/home’ }
嵌套路由
1 | // 创建路由实例对象 |
相当于代替{ path: “/c2/tab1”, component: Tab1 }
默认子路由,替换重定向
{ path: “”, component: Tab1 }
动态路由匹配
在路由配置中使用冒号去接收
{ path: “/c1/:cid”, component: C1 }
使用this.$route.params.cid获取值,或者开启props为true,在组件中定义props,插值使用
1 | //定义 |
上述的<router-link>
使用的是声明式导航,还有一种编程式导航,比如js的locaton.href
vue-router中也提供了很多API
最常用的API为
- this.$router.push(‘hash地址’)
跳转到具体的hash地址,并增加一条记录
- this.$router.replace(‘hash地址’)
跳转到具体的hash地址,并增加一条记录
- this.$router.go(数值n),n可以为正负数,1表示前进1页,-2表示后退两页
如果只是前进后退一个页面,vue提供了简单的方法$router.back()和$router.forward()
导航守卫
可以控制路由的访问权限,可以理解为一个前端的拦截器
vite
vue3的内容,仅适用于vue3,特点是小而巧,缺点是目前不适合于企业级开发
创建vite项目
1 | npm init vite-app 项目名称 |
项目结构
与vue-cli类似
1 | node_modules //第三方依赖包 |
其中src下
1 | assets //存放所有的静态文件 |
运行过程
- 通过main.js把App.vue渲染到index.html指定区域中
- App.vue表示待渲染的模板结构
- index.html需要预留一个el区域
根节点
在vue3中取消了只有一个根节点的限制