目录
1、computed和watch的理解
2、computed 与 watch的区别?
3.computed计算属性
4.组件中 data,computed 和 watch 的区别
5.vue的响应式原理中 object.defineproperty有什么缺陷?
6.面试题:react、vue中的key有什么作用?(key的内部原理)
7.请简述你对 vue 的理解
8.优化vue性能的方法
9.数据请求在create与mouted的区别
10.生命周期执行
11.写出 vue中的所有的生命周期函数,分别有什么作用
12.什么是vue框架
13.五.vuex的五个核心
14.vuex优点
15.声明周期划分四个
16。“单向数据流”理念
17。ref/$refs通信方式与获取dom
18。Vuex中 action 和 mutation 的区别
19。Axios 是什么
20.Vuex和单纯的全局对象有什么区别?
21.vuex是什么?怎么使用?哪种功能场景使用它
22.写出nextTick的作用,以及用法
23.什么是多个组件共享状态
24.请简述 vue 的单向数据流
25.vue组件之间通信的方式有哪些,是如何通信的
26.写出你对vue的mixin的理解,有什么应用场景?
27.的作用是什么?什么场景使用?常用属性?生命周期?
28.出vue插槽有哪些,如何使用
· computed是计算属性,具有缓存性。当页面中有某些数据依赖其他数据进行变动的时候,可以使用计算属性。依赖的数据发生变化时,触发属性重新计算。Computed本质是一个具备缓存的watch,依赖的属性发生变化就会更新视图。 适用于计算比较消耗性能的计算场景。
· Watch没有缓存性,更多的是观察的作用,可以监听某些数据执行回调。用于观察props,$emit或者本组件的值,当数据变化时来执行回调进行后续操作。页面重新渲染时值不变化也会执行。当我们需要深度监听对象中的属性时,可以打开deep:true选项,这样便会对对象中的每一项进行监听。这样会带来性能问题,可以使用字符串监听进行优化,如果没有写到组件中,不要忘记使用unWatch手动注销。
· 应用场景:当我们要进行数值计算,而且依赖于其他数据,那么把这个数据设计为computed。如果你需要在某个数据变化时做一些事情,使用watch来观察这个数据变化。
功能不同:
watch:
侦听属性,侦听数据是否发生变化,执行对应的回调
computed:
计算属性,依赖一个值计算另一个值,当数据发生变化时,使用该数据地方也会发生变化
是否调用缓存:
computed:
只有数据发生变化才会重新计算,否则从缓存中读取
watch:
数据发生变化时,执行对应的回调,不会调用缓存
是否调用return:
computed:
必须要用return返回数据
watch:
不是必须要用return
首次加载是否监听:
watch:
首次加载默认不做监听,如果需要,添加属性immediate:true
computed:
首次加载默认做监听
是否支持异步:
computed:
不支持异步,内部有异步操作时失效,且无法监听数据变化
watch:
支持异步
使用场景:
computed:
一个数据受多个数据影响
watch:
一个数据影响多个数据
a.自身需要依赖另一个值得改变而使当前所在dom更新
b.计算属性不可以与data中的数据重名
c.计算属性的方法不需要添加括号调用,方法需要单独加括号调用,因为计算属性不属于方法,属于属性
d.计算属性有缓存机制:当计算属性第一次获取到响应式数据时,会缓存,在后期渲染时,会观察响应式数据是否改变,如果改变就会调用计算属性,如果没有改变会读取存储的数据,方法只用更新就会重新调用
c.当获取计算属性时会触发getter,当设置修改计算属性时会触发setter
注意:计算属性不可以使用箭头函数,否则this不会指向这个组件的实例
相同点:
在 Vue 组件中,data、computed 和 watch 都是用来处理数据的
不同点:
data: 组件内部的数据源,可以用来存储和处理组件内部的数据。通过在组件中定义 data 属性来声明一个数据源。
computed: 计算属性,用于计算和处理从 data 中获取的数据,提供一种简洁的方式来处理模板中的复杂逻辑。computed 属性具有缓存机制,只有在它的依赖项发生变化时才会重新计算。
watch: 用于观察和响应数据的变化,当被观察的数据发生变化时,watch 中的回调函数会被调用。可以用 watch 来处理一些需要在数据变化时立即执行的操作,例如异步操作等。
总的来说,data 用于存储组件内部的数据,computed 用于计算和处理需要从 data中获取的数据,而 watch 用于处理数据的变化,如果你需要在某个数据变化时做一些事情,使用 watch 来观察这个数据变化
Object.defineproperty()无法监控到数组下标的变化,导致通过数组下标添加元素Object.defineproperty()不能实时响应;
Object.defineProperty .只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。
Proxy 可以劫持整个对象,并返回一个新的对象不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性
a. 虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较
b.对比规则:
(1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!
②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
(2).旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到到页面。
c. 用index作为key可能会引发的问题:
1. 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
2. 如果结构中还包含输入类的DOM:
会产生错误DOM更新 ==> 界面有问题。
d. 开发中如何选择key?:
1.最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
Vue 是一套构建用户界面的渐进式的自底向上增量开发的 MVVM 框架,核心是关注视图层,vue 的核心是为了解决数据的绑定问题,为了开发大型单页面应用和组件化,所以 vue 的核心思想是数据驱动和组件化,这里也说一下 MVVM 思想,MVVM 思想是 模型 视图 vm 是 v 和 m 连
接的桥梁,当模型层数据修改时,VM 层会检测到,并通知视图层进行相应修改
a.路由懒加载.有效拆分应用大小,访问时才异步加载
b.keep-alive缓存页面,避免重复创建组件实例,且能保留缓存组件状态
c.v-for遍历的同时避免使用v-if.实际上在vue3中已经是一个错误用法
d.长列性能优化,可采用虚拟列表
c.v-once.不再变化的数据使用v-once
d.事件销毁.组件销毁后把全局变量和定时器销毁
e.图片懒加载
f.第三方插件按需引入
g.子组件分割.较重的状态组件适合拆分
h.服务端渲染
created:是在组件实例一旦创建完成的时候立刻调用,这时候页面的dom节点并未完成
mounted:是在页面dom节点渲染完毕之后立刻执行,触发时机上created要比mounted创建的更早
两者相同点:
都能拿到实例对象的属性和方法
这个问题本质就是触发的时机,放在mounted请求有可能导致页面闪动(页面dom结构已经生成),但如果在页面加载前完成这不会,出现此情况建议:放在created生命周期当中
beforeCreat()-----创建前 在new一个vue实例后,只有一些默认的生命周期钩子和默认事件,其他的东西都还没创建。不能在这个阶段使用data中的数据和methods中的方法
created()----------- 被创建 data 和 methods都已经被初始化好了,可以调用了
beforeMount() ----挂载前 在内存中已经编译好了模板,但是还没有挂载到页面中,此时,页面还是旧的
mounted()-------已挂载 Vue实例已经初始化完成了。此时组件脱离了创建阶段,进入到了运行阶段。 如果我们想要通过插件操作页面上的DOM节点,最早可以在和这个阶段中进行
beforeupdate()--更新前 页面中的显示的数据还是旧的,data中的数据是更新后的, 页面还没有和最新的数据保持同步
updated()---------更新 页面显示的数据和data中的数据已经保持同步了,都是最新的
activited()---------- 在组建被激活时调用(使用了
deactivited---------- 在组件被销毁时调用(使用了
beforeDestroy()----- 销毁前 Vue实例从运行阶段进入到了销毁阶段,这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于可用状态。还没有真正被销毁
destroyed()-------被销毁 这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于不可用状态。组件已经被销毁了。
beforecreate: 实例已经初始化,但不能获取 DOM 节点。(没有 data,没有el)
created:实例已经创建,仍然不能获取 DOM 节点。(有 data,没有el )
载入阶段:
beforemount:模板编译完成,但还没挂载到界面上。(有 data,有 el)
mounted: 编译好的模板已挂载到页面中(数据和 DOM 都已经染出来)。
更新阶段:
beforeupdate: 数据发生变化立即调用,此时 data 中数据是最新的,但页面上数据仍然是旧的(检测到数据更新时,但 DOM 更新前执行)。
updated: 更新结束后执行,此时 data 中的值和页面上的值都是最新的。
销毁阶段:
beforedestroy:当要销毁 vue 实例时,在销毁之前执行。
destroyed:在销毁vue 实例时执行。
actived:在 keep-alive 中使用,缓存组件激活
deactived:在 keep-alive 中使用,缓存组件不激活
vue 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。vue 的核心是只关注视图层,并且还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
1. state:存放状态(全局状态数据) 必填项
2. mutations:对于 state 成员进行同步修改操作(也可以支持异步操作)
3.getters:获取 state 中的数据,类似于组件中的计算属性
4. actions:进行异步操作,异步得到结果后通知 mutation 修改 state 成员
5. modules:模块化状态管理,多状态文件管理时使用,开发项目时多为多模块项目
在多模块 vuex 中会有配置namespaced:true开启命名空间
1. 能够在 vuex 中集中管理共享的数据,便于开发和后期进行维护
2. 能够高效的实现组件之间的数据共享,提高开发效率
3. 存储在 vuex 中的数据是响应式的,当数据发生改变时,页面中的视图也会同步更新
4.vuex中的数据操作可以在开发阶段通过开发调试工具来进行追踪,便于开发
简单来说,vuex 就是为了实现组件间通信的。使用 vuex 的好处:可以跨层级进行通信;vuex 中的所有操作都有记录;vuex 独立于组件系统,是专门用来管理数据的框架。
1- 初始化
beforeCreate
created
过程:
1- new Vue()
2- 初始化事件与生命周期函数
3- beforeCreate:立即执行函数,不能操作data 与 methods
4- vue内部添加data 或者 methods
5- created 立即执行函数, 可以访问 data,methods
6- 开始编译,是否有el选项 el选项挂载到哪里
6.1- 没有调用$mount
6.2- 有 是否有模板
2- 挂载
beforeMount
mounted
过程:
1- 有 模板 编译模板template 返回render渲染函数
2- 没有 编译el选项对应的模板
3- 虚拟dom渲染为真实dom -- 准备工作 html结构
4- beforeMount 立即执行
5- 将虚拟dom挂载到真实dom -- 数据
6- 挂载完毕 Mounted 立即执行
3- 更新
beforeUpdate
updated
1- 当data数据被更新、修改时 触发钩子函数 beforeUpdate 此阶段获取不到更新的真实dom
2- 虚拟dom 重新渲染到真实dom
3- 触发钩子函数 updated
4- 当data数据再次发生改变时 ,重复执行此操作
4- 销毁
beforeDestroy
destroyed
1- 当$destroy 触发时 (比如组件的dom被移除)
2- beforeDestroy 被触发
3- 拆卸数据监视器 、 子组件 和事件侦听器
4- 当实例销毁后 触发destroyed
面试题:
页面第一次加载时会触发几个钩子
beforeCreate created beforeMount mounted
dom渲染在哪个周期完成?
mounted中完成
状态,驱动应用的数据源;
视图,以声明方式将状态映射到视图;
操作,响应在视图上的用户输入 导致的状态变化
.ref可以作为父子组件通信的一种方式,通信形式为父组件引用子组件。
特殊属性ref
1.在vue中,组件或原生标签上的ref属性用于注册引用信息。
2.通过ref我们可以获取
(1)原生标签的dom对象
(2)组件实例,
3.通过获取的原生标签的dom对象,我们可以使用
(1)dom对象上的属性
(2)dom对象的方法
4.通过组件实例我们可以使用组件的
(1)数据(定义的data,props,computed等等)
(2)方法。
5.组件实例属性$refs
1.每一个组件都有一个实例属性$refs,用于获取该组件下所有注册的引用信息
2.通过获取的引用,父组件可以直接访问该引用子组件的数据和方法,从而实现通信。
注意事项
1.$refs 只会在组件渲染完成之后生效,且有时就算写在mounted生命周期里都访问不到
Action 可以包含任意异步操作。
Action 提交的是 mutation,而不是直接变更状态。
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,
因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
Axios 是一个基于 promise 网络请求库
特性
1.从浏览器创建 XMLHttpRequests
2. 从 node.js 创建 http 请求
3. 支持 Promise API
4. 拦截请求和响应
5. 转换请求和响应数据
6. 取消请求
7. 自动转换JSON数据
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会得到高效更新。不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解应用。
vuex 就是一个仓库,仓库里放了很多对象。
state 存放的是数据状态,不可以直接修改里面的数据。
getters类似vue的计算属性,主要用来过滤一些数据。
mutations:存放的是动态修改Vuex的state中保存的数据状态的方法。
actions:保存的触发mutations中方法的方法,可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。
一般什么样的数据会放在 State 中呢?
目前主要有两种数据会使用 vuex 进行管理
1、组件之间全局共享的数据
2、通过后端异步请求的数据 比如做加入购物车、登录状态等都可以使用Vuex来管理数据状态
怎么使用Vuex?
在main.js引入store,注入。新建了一个目录store,… export
场景有:单页应用中,组件之间的状态、音乐播放、登录状态、加入购物车
作用:获取数据更新之后的dom元素
用法:
将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。
new Vue({
methods: {
// ...
example: function () {
// 修改数据
this.message = 'changed'
// DOM 还没有更新
this.$nextTick(function () {
// DOM 现在更新了
// `this` 绑定到当前实例
this.doSomethingElse()
})
}
}
})
多个视图依赖于同一状态。
来自不同视图的行为需要变更同一状态。
父级 prop 的更新会向下流动到子组件中,每次父组件发生更新,子组件所有的 prop 都会刷新为最新的值
数据从父组件传递给子组件,只能单向绑定,子组件内部不能直接修改父组件传递过来的数据,(可以使用 data 和 computed 解决)
1. 父传子 通过在父组件自定义属性,在子组件通过props接收
2. 子改父或者子传父 在父组件中通过自定义事件传递方法,在子组件中通过$emit接收自定义事件
3. 兄弟之间通信 通过一个事件总线(eventBus 其实是一个空实例),在A组件中通过$on绑定自定义事件 在B组件中通过$emit接收组件
4.通过$parent /$children/$refs $parent指的是父组件实例 $children/$refs是子组件实例
5. $attrs & $listeners
$attrs获取父组件中不被props接收的自定义属性 并且可以通过 v-bind="$attrs" 传入内部组件
$listeners获取父组件中的自定义事件
6.provide & inject 祖先和后代之间的通信
Provide的值可以是对象或者是返回对象的函数
mixin(混入),提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。
本质其实就是一个js对象,它可以包含我们组件中任意功能选项,如data、components、methods、created、computed等等
我们只要将共用的功能以对象的方式传入 mixins选项中,当组件使用 mixins对象时所有mixins对象的选项都将被混入该组件本身的选项中来
在Vue中我们可以局部混入跟全局混入
使用场景
在日常的开发中,我们经常会遇到在不同的组件中经常会需要用到一些相同或者相似的代码,这些代码的功能相对独立
这时,可以通过Vue的mixin功能将相同或者相似的代码提出来
Keep-alive 是 Vue.js 内置的一个抽象组件,用于缓存有状态组件,可以在组件切换时保留组件的状态避免重新渲染。它有以下两个作用:
缓存有状态的组件,避免组件在切换时被重新渲染;
在缓存的组件被激活时触发 activated 钩子函数,在缓存的组件被停用时触发 deactivated 钩子函数。
使用 Keep-alive 可以提高组件的性能,尤其是在组件状态比较复杂或需要较长时间计算的情况下,通过缓存组件避免重复渲染,提高应用的性能。
插槽就是子组件中的提供给父组件使用的一个占位符,用
插槽又分为三种,1.匿名插槽 2.具命插槽 3.作用域插槽
1.匿名插槽 : 父组件传递 一个html结构 给子组件
(1)子组件:
(2)父组件: <子组件> html结构 子组件>
2.具名插槽 : 父组件传递 多个html结构 给子组件
(1)子组件: 给插槽添加一个name(插槽名)
(2)父组件: 使用 v-slot:插槽名 或 #插槽名
<子组件>
html结构
子组件>
3.作用域插槽: 子组件传递 数据 给父组件插槽
(1)子组件 : 给
(2)父组件 : 使用 v-slot="对象名"