下面是我作为后端对vue的看法

后端程序员应该对vue了解多少

前言

vue知识点总结,我认为的后端需要了解的程度,学习永远是学的多,会的少。学的尽可能的往深里研究,毕竟以后也没这机会了

前置

需要掌握一定的ES6相关语法,我这里也总结了一点,可以去网上了解更多

es6属性的简写

img

什么时候方法的()可以省略

必须满足两个条件,类似下图

  1. 事件监听
  2. 方法没有参数

当条件为false的时候,v-if不会存在dom中,v-show会出现,加了一个样式dispaly:none。就是F12查看的时候有没有 使用建议:如果频繁切换使用v-show,只切换一次v-if

let i in 遍历的对象,此时i是当前索引 let i of 遍历的对象,此时i是当前对象

如果需要以下三个需求应该怎么写代码

  1. 筛选数组中小于100的数字
  2. 将筛选出的结果x2
  3. 将结果进行相加

最直接的方法就是套的写,官方叫做链式编程,也叫函数式编程

1
2
3
4
5
6
7
let total = nums.filter(function(n){
return n < 100
}).map(function(n){
return n * 2
}).reduce(function(preValue, n){
return preValue + n
})

如果了解过Java8新特性的也可以采用lambda编程,更加简洁明了

1
2
3
const nums = [10,20,15,30,22]
let total = nums.filter(n => n < 100).map(n => n * 2).reduce((pre, n) => pre + n)
console.log(total)

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封装的异步请求更加专业
image-20210825181208193

返回的数据data才是服务器真实的数据,其他数据都是axios追加的数据
image-20210825182858119

await只能用在async修饰的方法中,好处是可以不用写then方法,返回值就是结果,不加修饰的话就是返回一个promise对象,这里标记的三个陌生名词是ES的语法,如果遇到这个写法,那就是国际写法,我这里简单总结了几点前置概念有需要的看看

promise

目的:为了解决回调地狱的问题,ES6新增了promise的概念

概念;是一个构造函数,new一个promise,该对象代表一个异步操作,可以在该对象的原型对象上.then()方法

.then()的作用为预先指定成功和失败的回调函数,比如p.then(result => {}, error => {}),成功是必选的,失败是可选的

如果.then()返回了一个新的promise对象,则可以通过下一个.then继续进行处理,通过对then的链式调用,来解决回调地狱的问题,在链式调用的操作过程中发生了错误可以通过catch来对方法进行捕获处理

回调地狱

可以理解为多层套娃,如图,这种代码的耦合性强,会产生大量冗余的代码
image-20210906144405887

async / await

是ES8的语法,简化promise的异步操作,在async / await出现之前,只能使用链式.then的方式来处理promise的异步操作,此方式解决了回调地狱的问题,但会造成代码冗余的问题,代码如下
image-20210906154141739

使用方式
await用于方法内部,用作修饰之后就不在返回一个promise对象,而是其中的内容
image-20210906154418590

注意事项

  • 如果方法内部用到了await则方法外必须使用async进行修饰,否则会报语法错误
  • 第一个await之前的代码会同步执行,之后修饰的会异步执行

image-20210906154845698

1
2
3
4
5
6
结果
A
B
C
1 2 3
D

vue2中全局配置axios

main.js文件中

1
2
3
4
5
6
//导入axios
import axios from 'axios'
//配置请求根路径
axios.defaults.baseURL = "https//www.xxx.xxx"
//全局配置axios
Vue.prototype.$http = axios

vue3中全局配置axios

为什么要全局配置?
在实际项目开发中,几乎每个组件都会用到axios去发送数据请求,那么会有如下问题

  1. 每个组件都需要导入
  2. 每次发请求都需要写全部路径

如何全局配置
在main.js中,通过app.config.globalPropeties全局挂载axios
image-20210908164159214

拦截器

每次发起ajax请求和得到响应的时候会自动触发
image-20210909151803388

应用场景

  • token认证
  • loading效果

如何配置
axios.interceptors.request.use(成功回调函数,失败回调函数)失败的回调可以忽略

示例代码—验证token

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import axios from 'axios'

axios.defaults.baseURL = "xxx"

//配置请求的拦截器
axios.interceptors.request.use(
config => {
//为当前请求配置token认证字段
config.headers.Authorization = 'token'
return config
}
)

//配置响应拦截器
axios.interceptors.response.use(
response => {
return response
}
)

Vue.prototype.$http = axios

proxy跨域问题

如果没有开启CROS跨域资源共享,如下接口i昂无法请求成功
image-20210909154723025

解决方案

  1. 后端帮忙处理跨域问题
  2. 使用代理的方式进行解决
    image-20210909154922263
    附上一段我开发过程中企业使用的代码
    在vue.config.js中,声明如下配置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    module.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主线程执行回调函数。

执行过程
image-20210906155421597

主线程—>异步(执行完哪个就把哪个放到队列中,主线程执行完之后会按照队列中的顺序执行)

宏任务和微任务

它们都是异步任务,但有执行先后顺序,交替执行,先宏后微
image-20210906160144360
宏任务:ajax、计时器、文件操作
微任务:promise.then .catch .finally、process.nextTick

执行顺序举例

image-20210906160756181

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项目
image-20210906171701615

ref

虽然vue中不建议程序员直接操作DOM元素,但也提供了方法,可以在不依赖JQ的情况下操作DOM元素和组件实例
在每个vue实例对象中都会包含一个$refs,使用示例

1
2
3
4
5
6
7
<h3 ref="myh3">自定义</h3>
//...
show() {
let v1 = this.$refs.myh3;
console.log(v1);
v1.style.color = 'green';
}

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起到了监听数据变化的作用
数据的变化会驱动视图自动更新
image-20210823192330191

2、双向数据绑定
辅助开发者在不操作DOM的前提下,自动把用户填写的内容同步到数据源中
image-20210823192802732
MVVM(Model-View-ViewModel)

实现两大特性的核心原理
image-20210823193148997

工作原理
image-20210906164344403

vue使用

引入vue.js,在<script>中new vue对象,如下图
image-20210823194447037

常用指令

内容渲染: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进行深度监听,可以监听到对象中属性的变化
image-20210825170621082

应用场景:用户名是否被占用,请求接口返回用户名是否存在
image-20210825174909234

计算属性

  • computed,执行一系列运算后,最终得到一个属性值。用于复用
  • 本质是一个function函数,可以实时监听data中的变化,并return一个计算的值(return是必须的)
  • 相较于method的区别是,计算的结果会被缓存,当再次被使用的时候如果数据没有变化,那么方法将不会被调用,调用的时候按照一个变量去调用,如下图应该为{{ plus }} ,而不是{{ plus() }}
    image-20210907134101249

vue-cli

  • 单页面应用程序:只有一个html,其余由js,css等支撑
  • vue-cli可以快速搭建单页面应用,简化了程序员webpack创建工程化vue项目的过程,相当于springboot,减免了ssm的一些配置,程序员可以更专注于业务
  • 脚手架,官方提供的快速生成vue工程化项目的工具

优点

  • 开箱即用
  • 基于webpack
  • 功能丰富且易于拓展
  • 支持vue2和vue3

利用cli构建项目

安装vue-cli、创建项目

1
2
npm install -g @vue/cli
vue create 项目名

目录结构如下
image-20210825201815908

怎么跑起来的

通过main.js吧App.vue渲染到index.html指定区域中(vue2与vue3有些许不同)
image-20210825202902742
vue2

1
2
3
4
5
6
7
8
9
10
//导入vue包,得到vue的构造函数
import Vue from 'vue'
//导入根组件,把App.vue中的模板结构,渲染到html页面中
import App from './App.vue'

//创建vue的实例对象
new Vue({
//把render函数指定的组件,渲染到HTML页面中,替换掉#app的div
render: h => h(App),
}).$mount('#app')

vue3

1
2
3
4
5
6
7
8
//按需导入createApp函数,用来创建单页面应用实例
import { createApp } from 'vue'
//导入待渲染的App组件
import App from './App.vue'
import './index.css'

//调用createApp函数,返回的是一个单页面应用实例,调用该实例的mount方法来指定vue要控制的区域
createApp(App).mount('#app')

vue运行过程

template—>解析成 ast(抽象语法树)—>编译成 render —>转成 虚拟dom —>转成真实dom—UI

runtime-only直接就到了render阶段,所以快,性能更高,代码量更少

vue的组成

vue文件是一个组件,由三部分构成。组件时UI结构的复用

1
2
3
<template> //html </template>
<style> //css</style>
<script>//js</script>

template—>模板结构,存放html结构

script—>js语句

  • 其中包含data节点,存放定义数据
  • methods节点,存放方法
  • emits存放自定义事件

style—>样式

组件的注册方式

全局注册和局部注册,先注册后使用,推荐使用大驼峰命名

顾名思义,全局表示任意一个组件都可以使用,局部只可以在指定范围内使用
image-20210906193950857
image-20210825211524767

组件的使用

  1. 导入组件 import 组件名 from ‘组件路径’
  2. 使用components来注册组件
  3. 以标签的形式使用
    image-20210906194343409

组件库

在实际开发中,前端开发者可以把自己开发的.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
    4
    title: {
    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去返回一个新的对象,所以是互不影响,这也是为什么使用函数的原因。

组件之间的通信

父 —> 子(自定义属性)
image-20210830201332261

子 —> 父(自定义事件$emit)
image-20210830202156111

父 <—> 子(组件上的v-model)

兄弟之间(EventBus,组件离得远的都可以用)
image-20210830203535477

后代关系(provide & inject)

全局数据共享
vuex:是终极的组件之间的数据共享方案。在企业级vue的项目开发中,vuex可以让组件之间的数据变得高效、清晰、易于维护,如图所示,左侧没有使用vuex,比较混乱。右侧使用了vuex,有一个专门管理数据的地方
image-20210908163338173

动态组件

动态切换组件的显示和隐藏

vue提供了一个默认的<compents>组件,占位符,is属性,写哪个渲染哪个

在切换之后会遇到重新渲染的问题,可以使用keep-alive标签来避免组件销毁,在浏览器中会被缓存

1
2
3
<keep-avlive>
<Compoents is:"custom"></Compoents>
</keep-avlive>

keep-alive有独自的生命周期函数,可以被频繁触发

当组件被缓存时,会触发组件的deactivated声明周期函数

当组件被激活时,会触发组件的activated生命周期函数

includes属性与exclude属性(但只能同时存在一个)
image-20210831164444921

生命周期

创建—运行—销毁,指一个时间段
image-20210830191839160

生命周期有很多的钩子函数,不论是谁的生命周期也都是从创建到销毁,之前的servlet,线程之类的也都一样,很多都是相通的。通过钩子函数可以了解到元素分别在不同的函数中加载情况,这样的话可以自定义函数选择在那个生命周期中加载。(自己写下相关代码会更清楚)

beforecreated:el和data均未加载

created:data完成初始化,el没有。常用于异步获取数据时候使用

beforemount:完成el和data初始化

mounted:完成挂载,将内存中的HTML渲染到浏览器中,此时可以操作DOM(最早操作DOM的阶段)

updated:可以操作数据变化后的最新DOM

image-20210908161149575

插槽

一般使用居多,定义较少,不是专业前端了解下就可以了,封装组件的时候会被用到,实现UI结构的复用,把不确定和希望用户自定义的部分叫做插槽

用slot占位,供用户自定义使用(联想到小霸王游戏机,插哪个玩哪个)

v-slot简写为#

默认情况下名称为default

需要作用域template标签中

image-20210831180222312

具名插槽:具有名字的插槽。没有指定名字的插槽叫做”default”
<slot name=""></slot>>

传参解构

1
2
3
4
5
6
//插槽
<slot name="名称" msg="属性" :user="userinfo"></slot>
//使用
<template #名称="{userinfo对象比如 '{ name }'}">
{{ msg }}
</template>

自定义指令

官方的够用了,了解即可
官方提供了一些指令如:v-if、v-for、v-model、v-text等指令,除此之外,开发者还可以自定义指令

私有自定义指令:组件中自己用

全局自定义指令:全局都可以用

关键字directives声明私有自定义指令,与method平级,当指令被绑定到元素中时,会自动触发bind函数
image-20210901153809517

比如定义的时候为color,用的时候为v-color

bind函数只会调用一次,update函数则会在dom每次更新的时候被调用
image-20210901154753906

如果bind和update逻辑完全相同,那么可以简写
image-20210901155108590

vue3调用方式
image-20210909110048265

全局自定义指令Vue.directive,需要放到main.js中
image-20210901155339023

ESlint

用来约束代码风格。坑爹东西,搭配插件后让强迫症受不了,我最后是把它关了,帮你修正代码中的格式错误,有错误不让运行
比如他会把单引号在你保存的时候变为双引号,每一句结束都要加上;号,还得花时间去设置,我是拜拜了
如果往后公司要求,那就按公司来,公司一般也都设置好了一套规则,不用自己去设置,遭不住也得遭了

配置过程

  1. 配置项,在创建项目的过程中,选择eslint
    image-20210901162755782
  2. 一般选标准配置
    image-20210901162828548
  3. on save表示保存的时候会校验,另一个表示提交的时候会校验,一般选第一个
    image-20210901162917948
  4. 创建完项目之后会出现一个eslint的js文件
    image-20210901163552057
  5. 可以在其中的rules中配置一些规则
    image-20210901163623580
    官方语法规则见:ESLint中文文档
    需要掌握当编辑器报错的时候,知道是由于格式引起的,还能定位到哪一行

路由

也是vue中一个比较重要的概念,用来指定hash地址和组件的对应关系。路由的本质就是对应关系

后端路由

请求方式、请求地址、function处理函数的对应关系

前端路由

在SPA项目中,利用前端路由实现组件之间的切换

工作方式

  1. 点链接(触发)
  2. url地址栏发生变化
  3. 前端路由监听到hash地址的变化
  4. 将hash地址的组件渲染到组件中
    image-20210901192344468

实际上vue-router已经提供了封装,是vue官方给出的一个路由解决方案,可以轻松管理SPA页面组件之间的切换

vue-router3与vue-router4的最主要区别:创建路由模块的方式不同,在vue2的项目中只能使用vue-router3的路由
vue-router3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 导入vue2的构造函数
import Vue from "vue"
// 导入vuerouter3的包
import VueRouter from "vue-router"
//导入路由组件
import C1 from "../components/C1.vue"
import C2 from "../components/C2.vue"
import Tab1 from "../components/Tab1.vue"
import Tab2 from "../components/Tab2.vue"

// 调用Vue.use,把vuerouter安装为vue的插件
Vue.use(VueRouter)

// 创建路由实例对象
const router = new VueRouter({
// 定义映射关系
routes: [
{ path: "/", redirect: '/c1' },
{ path: "/c1/:cid", component: C1 , props: true},
//嵌套路由
{
path: "/c2",
component: C2,
children: [
{ path: "tab1", component: Tab1 },
{ path: "tab2", component: Tab2 }
]
},

]
})

// 共享路由实例对象
export default router

vue-router4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//按需导入需要的方法
import { createRouter, createWebHistory} from "vue-router"
//导入路由组件
import C1 from "../components/C1.vue"
import C2 from "../components/C2.vue"
import Tab1 from "../components/Tab1.vue"
import Tab2 from "../components/Tab2.vue"

// 创建路由实例对象
const router = new VueRouter({
history: createWebHistory() //指定通过hash来管理路由的切换
// 定义映射关系
routes: [
{ path: "/", redirect: '/c1' },
{ path: "/c1/:cid", component: C1 , props: true},
//嵌套路由
{
path: "/c2",
component: C2,
children: [
{ path: "tab1", component: Tab1 },
{ path: "tab2", component: Tab2 }
]
},

]
})

// 共享路由实例对象
export default router
  1. 安装路由模块
  2. 创建路由模块
  3. 导入并挂载
  4. 声明地址和占位符

src下创建router文件夹创建index.js文件,其中写入以下代码

1
2
3
4
5
6
7
8
9
10
11
12
// 导入vue和vuerouter的包
import Vue from 'vue'
import VueRouter from 'vue-router'

// 调用Vue.use,把vuerouter安装为vue的插件
Vue.use(VueRouter)

// 创建路由实例对象
const router = new VueRouter()

// 共享路由实例对象
export default router

去main.js中使用,又叫挂载

在vue-router3中挂载方式为

1
2
3
4
5
6
7
8
9
10
// 导入路由模块
import router from './router'

//创建vue的实例对象
new Vue({
//把render函数指定的组件,渲染到HTML页面中,替换掉#app的div
render: h => h(App),
router
}).$mount('#app')

在vue-router4中挂载方式为

1
2
3
const app = craeateApp(App)
app.use(router)
app.mount('#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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 创建路由实例对象
const router = new VueRouter({
// 定义映射关系
routes: [
{ path: "/", redirect: '/c1' },
{ path: "/c1", component: C1 },
//嵌套路由
{
path: "/c2",
component: C2,
children: [
{ path: "tab1", component: Tab1 },
{ path: "tab2", component: Tab2 }
]
}
]
})

相当于代替{ path: “/c2/tab1”, component: Tab1 }

默认子路由,替换重定向

{ path: “”, component: Tab1 }

动态路由匹配

在路由配置中使用冒号去接收

{ path: “/c1/:cid”, component: C1 }

使用this.$route.params.cid获取值,或者开启props为true,在组件中定义props,插值使用

1
2
3
4
5
6
7
8
//定义
{ path: "/c1/:cid", component: C1 , props: true}
//组件
export default {
props: ['cid']
}
//使用
c1--->{{ cid }}

上述的<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()

导航守卫

可以控制路由的访问权限,可以理解为一个前端的拦截器

image-20210902173630887

vite

vue3的内容,仅适用于vue3,特点是小而巧,缺点是目前不适合于企业级开发

创建vite项目

1
2
3
4
npm init vite-app 项目名称
cd 项目
npm i
npm run serve

项目结构

与vue-cli类似
image-20210906174226243

1
2
3
4
5
node_modules //第三方依赖包
public //公共资源文件
src //源码
index.html //SPA项目唯一html页面
package.json //包管理文件

其中src下
image-20210906174342731

1
2
3
4
5
assets //存放所有的静态文件
components //存放所有的组件
App.vue //项目根组件
index.css //全局样式表
main.js //项目打包入口文件

运行过程

  1. 通过main.js把App.vue渲染到index.html指定区域中
  2. App.vue表示待渲染的模板结构
  3. index.html需要预留一个el区域
    20210906174932.png

根节点

在vue3中取消了只有一个根节点的限制