1.$route和$router的区别?
routes : 数组。 路由匹配规则
router : 对象。 路由对象
$router : 对象。 用于跳转路由 和 传递参数
$route :对象。 用于接收路由跳转参数
- beforeCreate 初始化实例前(在当前阶段 data、methods、computed 以及 watch 上的数据和方法都不能被访问。)
- created 实例创建完成之后被调用
- beforeMount 挂载开始之前被调用(相关的 render 函数首次被调用)
- mounted 挂载之后 (在当前阶段真实的DOM挂载完毕,数据完成双向绑定,可以访问DOM节点)
- beforeUpdate 数据更新前调用 (不会触发重新渲染过程)
- updated 更新完成之后
- beforeDestory 实例销毁之前调用
- destroyed 实例销毁之后调用 (Vue实例指示的东西都会解绑,所有事件监听移除)
- activated keep-alive专属,组件被激活时调用
- deactivated keep-alive专属,组件被销毁是调用
可以在钩子函数 created、beforeMount、mounted 中进行异步请求,因为在这三个钩子函数中,data已经创建,可以将服务器端返回的数据进行赋值。
如果异步请求不需要依赖 DOM 推荐加载 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:
能更快获取到服务端数据,减少页面loading时间;
如果依赖DOM元素:需要再mounted里面进行请求
- beforeCreate -> 使用 setup()
- created -> 使用 setup()
- beforeMount -> onBeforeMount
- mounted -> onMounted
- beforeUpdate -> onBeforeUpdate
- updated -> onUpdated
- beforeDestroy -> onBeforeUnmount
- destroyed -> onUnmounted
- errorCaptured -> onErrorCaptured
组件的data写成一个函数,数据以函数返回值形式定义
这样每复用一次组件,就会返回一分新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。
而单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。
- 避免组件被复用时,数据存在引用关系。
- vue组件可能存在多个实例,如果使用对象形式,会导致多个组件共用一个data,从而使一个组件影响其他组件。
- 如果用函数定义,会返回一个全新的对象,避免了组件间之间data的相互影响。
- props 和 $emit。
父组件向子组件传递数据是通过props传递的,
子组件传递给父组件是通过$emit触发事件来做到的。
- $parent 和 $children 获取单签组件的父组件和当前组件的子组件。
- $refs 获取组件实例
- 父传子孙:provide 和 inject
- vuex 状态管理(实现不同组件之前的数据共享)
--------------------------------------------
父传子
1.子组件props定义变量
2.父组件在使用子组件时通过行内属性给props变量传值
特点:单向数据流
子传父
1.子组件:$emit触发父的事件
2.父在使用组件用@自定义事件名=父的方法 (子把值带出来)
特点:事件监听
非父子组件
vuex
- 数据总是从父组件传递到子组件,子组件没有权利修改从父组件传过来的数据,只能请求父组件对原始数据进行修改。
- computed 是计算属性,依赖其他属性计算值,并且computed的值具有缓存性,当计算值发生变化时才会返回内容。
- watch 监听到值得变化就会调用。
计算属性一般用在模板渲染中,某个值是依赖其它响应对象甚至是计算属性而来;
而侦听属性适用于观测某个值的变化去完成一段复杂的业务逻辑。
- vuex可以实现不同组件之间的状态共享
- vuex可以实现组件内数据的持久化
为什么需要 vuex
由于组件只维护自身的状态(data),组件创建时或者路由切换时,组件会被初始化,从而导致 data 也 随之销毁。
使用方法
在 main.js 引入 store,注入。只用来读取的状态集中放在 store 中, 改变状态的方式是提交
mutations,这是个同步的事物,异步逻辑应该封装在 action 中。
什么场景下会使用到 vuex
如果是 vue 的小型应用,那么没有必要使用 vuex,这个时候使用 vuex 反而会带来负担。组件之间的 状态传递使用 props、自定义事件来传递即可。 但是如果 涉及到 vue 的大型应用 ,那么就需要类似于 vuex 这样的集中管理状态的状态机来管理所有 组件的状态。例如登录状态、加入购物车、音乐播放等,总之只要是开发 vue 的大型应用,都推荐使 用 vuex 来管理所有组件状态
- vuex的核心概念
(1)、state:设置初始值
(2)、getter:允许组件从state中获取数据
(3)、Mutation:修改state中状态的方法,且必须是同步函数
(4)、Action:用于提交mutation,可以包含任何异步请求
(5)、Module
- vuex流程
在vue组件里面,通过dispatch来触发actions提交修改数据的操作,
然后通过actions的commit触发mutations来修改数据,mutations接收到commit的请求,就会
自动通过mutate来修改state,最后由store触发每一个调用它的组件的更新。
- 不需要响应式的数据不要放在 data 中
- v-if 和 v-show 区分使用场景
- computed 和 watch 区分场景使用
- v-for 遍历必须加 key,key最好是id值,且避免同时使用 v-if
- 长列表滚动到可视区域加载
- 防止内部泄露,组件销毁后把全局变量和时间销毁
- 图片懒加载
- 路由懒加载
- SPA 页面采用keep-alive缓存组件
- key保证唯一
- 第三方模块的按需加载
- 适当采用 keep-alive 缓存组件
- 防抖、节流
- 增加loading用户体验
- 骨架屏
----
- 预渲染
- 服务端渲染SSR
----
- 压缩代码
- 使用cdn加载第三方模块
- 首屏加载慢原因:第一次加载页面有很多组件数据需要渲染
- 解决方案:
(1)路由懒加载
(2)UI组件按需加载
(3)gzip按需加载
- 解决白屏:
(1)使用v-text渲染数据
(2)使用{{}}语法渲染数据,同时使用v-cloak指令
- 加载慢的原因
1、网络延时问题
2、资源文件体积是否过大
3、资源是否重复发送请求去加载了
4、加载脚本的时候,渲染内容堵塞了
- 常见的几种SPA首屏优化方式
1、减小入口文件积
2、静态资源本地缓存
3、UI框架按需加载
4、图片资源的压缩
5、组件重复打包
6、开启GZip压缩
7、使用SSR
- spa仅在web页面初始化的时候加载html、js、css
- 页面一旦加载完成就不会因为用户的操作而进行页面的重新加载和渲染
- 页面的变化是利用路由机制实现html内容的变换,避免页面的重新加载
- vue是组件级更新,当前组件里的数据变了,它就会去更新这个组件。
当数据更改一次组件就要重新渲染一次,性能不高,为了防止数据一更新就更新组件,所以做了个异步更新渲染。
-(核心的方法就是nextTick)
- 第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子
加载渲染过程
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created
-> 子 beforeMount -> 子 mounted -> 父 mounted
子组件更新过程
父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
父组件更新过程
父 beforeUpdate -> 父 updated
销毁过程 父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
总结: 父组件先开始 子组件先结束
我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有一个
User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。那么,我们可以在 vue-router 的路由路径中使用 “ 动态路径参数 ” ( dynamic segment )来达到这个效果:
const User = {
template: "User",
};
const router = new VueRouter({
routes: [
// 动态路径参数 以冒号开头
{ path: "/user/:id", component: User },
],
问题 : vue-router 组件复用导致路由参数失效怎么办?
解决方案 :
1 、通 过 watch 监听 路由参数再发请求
watch:{
"router":function(){
this.getData(this.$router.params.xxx)
}
}
2 、用 :key 来阻止复用
router-view :key="$route.fullPath"
需要做 vuex 数据持久化 ,一般使用本地储存的方案来保存数据,
-使用router-link时
query传参:
跳转
使用this.$route.query.id获取
params传参
-router.js
{
name:'asd',
path:'xxxx/:id/:name',
component:Detail
}
接收参数this.$route.params.id
-使用params传参时,若是对象写法,需要在router.js中配置响应的name属性,并且需要占位。
-使用编程式路由导航
this.$router.push({
name:'xxx',
params:{
id:xxx,
title:xxx
}
})
对路由进行权限控制
router.beforeEach:全局前置路由守卫,to:目标路由,from:来源路由,next():放行;自定义参数需要配置在路由元信息(meta)里配置,用来控制权限。
router.afterEach():全局后置路由守卫,可用于动态更改页面标题。
beforeEnter():单个路由配置,路由独享守卫,对某一个路由进行权限设置。
beforeRouteEnter():组件内置守卫,通过路由规则,进入组件之前调用。
beforeRouteLeave():组件内置守卫,通过路由规则,离开组件之前调用。
-性能提升
打包大小减少41%
初次渲染快55%,更新渲染快133%
内存减少54%
-源码升级
使用proxy代替defineproperty实现响应式
重写虚拟dom的实现和剔除多余代码(tree-shaking)
-vue3可以更好的支持typescript
-新特性
composition API(组合api)
setup配置
ref与reactive
新的内置组件
fragment
teleport
新的生命周期钩子
移除keycode支持作为v-on的修饰符
data始终是一个函数
-computed:是计算函数,注重计算出来的值,所以必须写返回值
-watchEffect:是监视函数,注重过程,不用写返回值
1.vue在渲染的时候,会 先把 新DOM 与 旧DOM 进行对比, 如果dom结构一致,则vue会复用旧的dom。 (此时可能造成数据渲染异常)
2.使用key可以给dom添加一个 唯一标识符,让vue强制更新dom
[vue中key值作用逐字稿]
面试官你好,我是这么理解key值的,key值的主要作用是给元素添加一个唯一标识符,用于提高vue渲染性能,当data发生变化的时候,vue会使用diff算法来对比新旧虚拟DOM.如果key值相同,才会考虑复用元素.如果key值不同,则会强制更新元素.一般通过给元素key设置为id,来保证vue更新数据的时候可以最大限度复用相同的key值的元素.
给每个dom元素加上key作为唯一标识 ,diff算法可以正确的识别这个节点,使页面渲染更加迅速!
会改变原数组:
pop (删除数组的最后一个元素并返回删除的元素)
push(向数组的末尾添加一个或更多元素,并返回新的长度)
shift(删除并返回数组的第一个元素)
unshift(向数组的开头添加一个或更多元素,并返回新的长度)
reverse(反转数组的元素顺序)
sort(对数组的元素进行排序)
splice(用于插入、删除或替换数组的元素)
不会改变原数组:
concat---连接两个或更多的数组,并返回结果。
every---检测数组元素的每个元素是否都符合条件。
some---检测数组元素中是否有元素符合指定条件。
filter---检测数组元素,并返回符合条件所有元素的数组。
indexOf---搜索数组中的元素,并返回它所在的位置。
join---把数组的所有元素放入一个字符串。
toString---把数组转换为字符串,并返回结果。
lastIndexOf---返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索。
map---通过指定函数处理数组的每个元素,并返回处理后的数组。
slice---选取数组的的一部分,并返回一个新数组。
valueOf---返回数组对象的原始值
每一个实例对象上有一个proto属性,指向的构造函数的原型对象,构造函数的原型对象也是一个对象,也有proto属性,这样一层一层往上找的过程就形成了原型链。
利用子绝父相定位方式来实现
利用Css3的transform,可以轻松的在未知元素的高宽的情况下实现元素的垂直居中。
flex
所谓同源策略就是浏览器的一种安全机制,来限制不同源的网站不能通信(域名、协议、端口号相同)
首先 防抖就是触发下一个事件时停掉上一个事件
节流是 触发当前事件需要在上一个事件结束以后
通过设置节流阀(定时器)
跨域原因:浏览器出于安全考虑保护资源,同源策略。(协议、域名、端口号)
解决跨域:
jsonP 但只能使用get 原理-将请求的接口设置给script标签的src属性传递一个函数给后台实现跨域。后台响应的是一个函数调用
cors:最常用。
反向代理:本地前端发送到本地后端,不会跨域,(同源)本地后端接收请求后转发到其他服务器(服务器和服务器之间不会跨域)代理是需要路径中的特殊标志。
33.