vue面试题
2024-05-18 18:29:25
浏览量: 1012
- 组件通信方式
- props
- emit
- provide/inject
- vuex
- 总线: $bus(vue2语法)、mitt(插件)
- 通过ref获取组件实例
- $attrs(未使用props接收的属性)、$refs(所有子实例)、$parent(父实例)
- 插槽slot-匿名插槽/具名插槽/作用域插槽(子向父传参)
<div @click="test($attrs, $refs, $parent, $event)"/>
// <!-- 作用域插槽 -->
<slot :row="123"></slot>
<template v-slot="{row}"><div>{{ row }}</div></template>
- 数据的双向绑定
// <!-- 输入框的双向绑定原理 -->
<input v-model="mValue" />
// <!--编译后: <input :value="mValue" @input="mValue=$event.target.value" /> -->
// <!-- 自定义双向绑定原理 -->
<DsVModel v-model="mValue" />
// <!--编译后: <DsVModel :model-value="mValue" @update:model-value="mValue = $event" /> -->
- v-bind和v-model区别
- v-bind单向数据绑定,v-bind:xxx=''简写:xxx=''
- v-model双向数据绑定
- vue3 api
- ref reactive shallowRef, shallowReactive
- setup onBeforeMount,onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted
- readonly shallowReadonly
- toRaw 获取响应式数据的原始数据
- markRaw 标记一个对象,禁止对其进行响应式处理
- customRef 自定义ref响应式数据
import { ref, defineComponent } from 'vue'
// 使用defineComponent自定义组件
const MyVueElement = defineComponent({
props:{},
// 在setup函数中有两个参数props和ctx上下文,可以在setup中返回一个渲染函数,支持jsx语法
setup(props, { attrs, slots, emit, expose }) {
const count = ref(0)
expose({
fn(){ count.value++ }
})
return () => {
return <div>div</div>
}
}
})
- vue3 内置组件
- slot
- Teleport 传送门
- Suspense 异步引入组件,当子组件内部有异步任务时,使用Suspense包裹可设置预加载内容
- app 全局api
- vue3
- app.component
- app.config 通过config挂在全局变量,不推荐使用
- app.use
- app.directive 自定义指令
- app.mount
- app.unmount
- vue2
- Vue.directive
- Vue.extend 构造器
- Vue.filter 构造器
- Vue.component 构造器
- Vue.use 构造器
- Vue.mixin 构造器
- vue3 对 vue2的非兼容性改变
- 过渡类名v-enter改成了v-enter-from,v-leave改成了v-leave-from
- 去掉了keyCode作为v-on修饰符的支持, 例如:允许@keyup.enter不允许@keyup.13
- v-model指令重新设计,替换掉了v-bind.sync
- v-if和v-for在同一个组件上使用时,优先级发生了变化,v-if高于v-for
- 移除了实例上的$on $off $once等方法
- 移除了filter过滤器方法
- 移除了$children属性
- pina状态管理
//main.js
createApp(App).use(createPinia())//这里不需要注入store
// 定义
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
getters: {
double: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
},
},
})
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, doubleCount, increment }
})
// 使用
import { useCounterStore } from '@/stores/counter'
const counterStore = useCounterStore()
counterStore.count += 1 //可以直接操作store中的数据
- vue中updated()和$nextTick()的区别
- updated是vue的声明周期每当数据变化以及dom更新后都会触发;nextTick是异步函数只触发一次,将回调延迟到下次dong更新之后执行
- 执行顺序不同,当数据变化时vue会进行虚拟dom对比和更新,这时会执行beforeUpdate和updated声明周期,update执行后会立即执行nextTick中的异步函数
- vue2和vue3的区别
- vue2使用Options API;vue3推荐使用Composition API可将同一逻辑的内容写到一起,增强了代码的可读性
- 生命周期的变化,Composition API中的声明周期函数以on开头,可以在不同的地方多次注册事件。setup代替了beforeCreate 和 created 生命周期
- Vue3 支持多个根节点的模版语法,一个组件中不需要定义唯一的根节点
- 响应式原理:Vue2 响应式原理基础是 Object.defineProperty;Vue3 响应式原理基础是 Proxy。
- Vue3 由 TypeScript 重写,相对于 Vue2 有更好的 TypeScript 支持
- vue2中diff算法是整体全量比对,对整颗vdom树进行循环对比操作;而在vue3中加入了静态标记(PatchFlag)和最长递增序列的概念
- vue2与vue3都有静态标记,区别在于vue2只能标记全量的静态,vue3 采取的是优化静态标记(即使是动态节点,也只diff动态的模块)减少了计算量
- 最长递增子序列(longest increasing subsequence)问题是指,在一个给定的数值序列中,找到一个子序列,使得这个子序列元素的数值依次递增,并且这个子序列的长度尽可能地大。最长递增子序列中的元素在原序列中不一定是连续的
- 如何理解Vue是一套渐进式的框架
- vue只提供了最核心的组件系统和双向数据绑定,像vuex、vue-router都属于围绕vue开发的库
- Vue的两个核心
- 数据驱动,也叫双向数据绑定
- 组件系统:template、data、props...
- Vue常用指令
- v-if: 根据条件真假判断是否渲染元素,在切换时元素及他的数据绑定/组件被销毁并重建
- v-show: 根据条件真假判断,切换元素的css中display的属性 none/block
- v-for: 循环指令
- v-bind: 动态绑定一个或多个特性,v-bind:name= ,简写 :name=
- v-on: 监听执行元素的事件,比如点击事件 v-on:name,简写 @name
- v-model: 实现表单输入和应用状态之间的双向绑定
- v-pre: 它用于告诉 Vue 编译器不要解析指定的元素和它的子元素,提高性能,减少不必要的解析和编译
- v-once: 只渲染元素和组件一次
- v-html: 更新元素的innerHTML
- v-text: 更新元素的textContent
- v-if和v-show的区别
- v-if和v-shoe都是可以动态显示DOM元素
- 编译过程:v-if是真正的条件渲染,会确保在切换过程中条件模块内的 事件监听器和子组件适当的销毁和重建,而v-show的元素始终会被渲染并保留在DOM中,因为v-show只是简单切换元素css的display属性
- 编译条件:v-if是惰性的,如果在初始渲染时条件为假,则什么也不做,直到条件第一次为真时,才开始渲染条件快,而v-show不管初始条件是什么,元素都会被渲染,只是会根据条件设置不同的display属性
- 性能消耗:v-if有更高的切换消耗,v-show则有更高的初始渲染消耗
- 应用场景:v-if适合条件改变次数少的时候使用,v-show适合频繁切换条件的场景
- vue常用修饰符
- v-on常用修饰符
- .stop - 调用event.stopPropagation() 禁止事件冒泡
- .prevent - 调用event.preventDefault() 阻止事件默认行为
- .capture - 添加事件侦听器时使用capture模式(即内部元素触发的事件先在此处理,然后才交由内部元素进行处理)
- .self - 当事件是从侦听器绑定的元素本身触发时才触发回调
- .{keyalias} 只有当事件是从特定按键触发时才触发的回调 如.enter
- .native - 监听组件根元素的原生事件
- .once - 只触发一次回调
- .left - 只当点击鼠标左键时触发
- .right- 鼠标右键时触发
- .middle - 鼠标中键时触发
- .passive - 以 {passive:true} 模式添加侦听器
- v-model常用指令
- .lazy - 用户每次修改输入内容,都会将内容和数据同步,使用lazy修饰符来进行限定。只有当用户的input中失去焦点或者用户点击回车按钮时,才会进行数据同步
- .number - 输入字符串转为数字
- .trim - 输入首尾空格过滤
- v-bind常用修饰符
- .prop - v-bind 默认绑定到 DOM 节点的 attribute 上,使用 .prop 修饰符后,会绑定到 property
- 使用 property 获取最新的值;
- attribute 设置的自定义属性会在渲染后的 HTML 标签里显示,property 不会。通过自定义属性存储变量,避免暴露数据 防止污染 HTML 结构
- .prop - v-bind 默认绑定到 DOM 节点的 attribute 上,使用 .prop 修饰符后,会绑定到 property
- vue中key的作用
- key 的特殊属性主要用在 Vue的虚拟DOM算法,在新旧nodes对比时辨识VNodes。如果不使用key,Vue会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用key,它会基于key的变化重新排列元素顺序,并且会移除key不存在的元素
- key用在组件上,当key变化时会重新渲染组件,以更新视图
- 组件复用的三个条件:同层节点、key相同、节点类型相同
- vue的异步更新队列
- Vue在观察到数据变化时并不是直接更新DOM,而是开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。所以同一个watcher被多次触发,只会添加到队列一次,因此可以去除重复数据可以避免不必要的计算和DOM操作
- Vue在内部对异步队列尝试使用原生的Promise.then 、 MutationObserver和setImmediate,如果以上都不支持,则采用setTimeout(fn,0)代替
- data为什么是个函数
- 因为一个组件是可以被多次使用的,为了保持它们的data是私有的,所以每个组件都要return一个新的data对象,返回一个唯一的对象,不要和其他组件共用一个对象
- keep-alive组件
- keep-alive 主要用于保留组件状态和避免重新渲染,常见就是列表页进入详情页,返回列表页时可以从缓存中快速渲染,而不是重新渲染
- keep-alive的属性
- include: 字符串或正则表达式,只有匹配的组件会被缓存
- exclude: 字符串或正则表达式,任何匹配的组件都不会被缓存
- exclude的优先级大于includes
- keep-alive的生命周期
- activated: 被 keep-alive 缓存的组件激活时调用。
- deactivated: 被 keep-alive 缓存的组件失活时调用。
- Vue等单页面应用的优缺点
- 单页面应用程序是加载单个HTML页面并在用户与应用程序交互时动态更新该页面的web应用程序
- 优点
- 更好的用户体验,具有桌面应用的即时性,网站的可移植性和可访问性
- 内容上更新不需要重新加载整个页面
- 没有页面之间的切换,所以切换页面不会出现加载白屏
- 对服务器压力小,只需要出数据
- 良好的前后端分离,提高开发效率
- 缺点
- 首次加载耗时多
- SEO问题,不利于搜索引擎收录
- 容易造成CSS命名冲突
- 计算属性的缓存和方法调用的有什么区别
- 计算属性必须返回结果
- 一个计算属性所依赖的数据发生变化时,它才会重新取值
- 计算属性是根据依赖自动执行的,methods需要事件调用
- methods和computed都可以对变量进行计算处理,但computed有缓存,如下
<div>{name} {name2()} {index}</div>
data(){
return : { index: 0, nameText: 'test' }
}
methods: {
name2() {
return this.nameText
}
}
computed: {
name() { return this.nameText }
}
/**
当index改变但nameText没变,medhods也是会重新执行,那么视图会重新渲染,
而computed因为有缓存,在nameText不变的情况下不会重新执行
*/
- computed 和 watch区别
- 计算属性computed:
- 支持缓存,只有依赖数据发生改变,才会重新进行计算
- 不支持异步,当computed内有异步操作时无效,无法监听数据的变化
- computed属性值默认走缓存,基于data中声明过或者父组件传递的props中数据通过计算得到的值
- 可以监听多个依赖数据变化去得到一个数据
- 侦听属性watch:
- 不支持缓存,数据改变则直接回触发相应的操作
- watch支持异步
- 监听的函数接受两个参数,(newValue,oldValue)
- watch参数 - immediate:组件加载立即触发回调函数执行、deep:深度监听,发现对象内部值的变化
- diff算法
- 两个树的完全的diff算法是一个时间复杂度为 O(n3),Vue进行了优化,转为了O(n)(只比较同级不考虑跨级问题)。因为在前端操作DOM的时候,不会把当前元素作为上一级或者下一级元素,很少会跨越层级地移动DOM元素,常见都是同级比较,所以vue只会对同一层级的元素进行比较
- 在数据发生变化时,Vue是先根据真实DOM生成一颗virtual DOM,当virtual DOM某个节点的数据改变后会生成一个新的VNode,然后新的Vnode和旧的Vnode作对比,发现不一样的地方就直接修改在真实的DOM上,实现更新节点
- 流程简述
- 先去同级比较,然后再去比较子节点
- 再判断一方有子节点一方没有子节点的情况
- 比较都有子节点的情况
- 递归比较子节点
- vue2中diff算法-双端比较的几种情况
- 首次渲染,直接cerateElement
- 旧节点存在,新节点不存在了:直接删除
- 无旧节点,新节点存在:新增节点
- 旧节点和新节点都在:同层比较时,依次比较:节点类型、key值、属性值、字节点
- 子节点对比步骤:
- 旧children首节点和新children首节点对比,头-头
- 旧children尾节点和新children尾节点对比,尾-尾
- 旧children首节点和新children尾节点对比,头-尾
- 旧children尾节点和新children首节点对比,尾-头
- 特殊情况:旧children中有,新children中无,删除;旧children中无,新children中有,新增
- vue和react异同点
- 相同点
- 都使用了虚拟DOM
- 都支持组件化开发
- 组件都是单向数据流(父子组件之间,不建议子修改父传下来的数据)
- 都支持服务器渲染
- 不同点
- react使用jsx,vue使用template
- 数据变化,react手动(setState),vue自动(初始化已做响应式处理,defineProperty)
- react单向绑定,vue双向绑定;react实现了Fiber架构,不vue2/3都没有引入Fiber架构
- vue3引入了Tree-shaking特性,旨在优化构建过程并减小最终生成的代码大小,把无用的模块去掉
- react中自己实现了虚拟dom的创建,vue则使用了snabbdom开源库来生成虚拟dom
- vue路由导航解析流程
- 导航被触发
- 在失活的组件里调用离开守卫
- 调用全局 beforeEach守卫
- 在重用的组件调用 beforRouteUpdate守卫
- 在路由配置里调用 beforEnter
- 解析异步路由组件
- 在被激活的组件里调用beforRouteEnter
- 调用全局的beforResole
- 导航被确认
- 调用全局的afterEach钩子
- 触发DOM更新
- 在创建好的实例调用beforRouteEnter守卫中传给next的回调函数
- $route和$router
- $route: 是路由信息对象,包括path, params, hash, query, fullPath, metched, name等路由信息参数
- $router: 是路由实例,包括路由的跳转方法,钩子函数等
- vue的运行机制
- 流程分析:
- 先进行初始化以及挂载: init以及mount
- 进行模板编译:compile,编译成渲染函数 render function
- 进行响应式收集 render function => getter、setter => watcher 进行 update => patch 的过程以及使用队列来异步更新的策略
- 依赖收集的同时生成 Virtual DOM: render function 被转换成VNode 节点
- 通过diff算法后进行patch更新视图
- new Vue - init - mount - compile - render - Vnode - patch(update) - Dom
- vue核心流程和响应式原理
- 核心流程
- 初始化全局方法如nextTick、set、delete、observable、util,合并option配置项,并绑定到实例上
- 通过mount函数初始化根节点dom模板元素,解析模板为ast抽象语法树,生成render函数,构建虚拟dom
- 依赖收集,生成Watcher观察者,数据变化时调用watcher的update方法通知组件通过patch函数diff对比虚拟dom,并更新视图
- 响应式原理
- 通过Object.defineProperty + observer(观察者) 实现
- definedProperty来实现对象响应式监听
- vue3宏函数
- defineProps()、defineExpose()、defineEmits()
- defineSlots() 约束slot插槽参数
- defineOptions() 定义 Options API 的选项,如:定义name 在seutp 语法糖模式发现name不好定义了有了defineOptions就可以随意定义name了
- 宏就是作用于编译时,也就是从vue文件编译为js文件这一过程。例如在编译时defineProps宏就会被转换为定义props相关的代码,当在浏览器运行时自然也就没有了defineProps宏相关的代码了。所以才说宏是在编译时执行的代码,而不是运行时执行的代码。
- withDefaults配合defineProps设置参数默认值
const props = withDefaults(defineProps<{
title:string,
data: {
list: any[]
}
}>(), {
title: 'title',
data:()=>{//引用数据类型必须用函数返回
return {
list: ['a','b']
}
}
})
- 动态获取资源路径的方式
// new URL(url [, base])创建一个URL对象,base 可选是一个表示基准 URL 的 DOMString,在 url 是相对 URL 时,它才会起效。如果未指定,则默认为 ''
// import.meta只能在模块内部使用,返回一个对象,该对象的各种属性就是当前运行的脚本的元信息
const uh = new URL('./profilePic/profile_pic_01.png', import.meta.url).href
- nuxt框架
- 基于node环境,首评加载时先在node中解析好html,再返回浏览器,后续就是单页面
- 内置工具类utils
- isOn: 判断是否是on开头的事件
- isModelListener: 判断onUpdate开头的字符串
- extend: 合并对象
- isSymbol: 判断是否是Symbol
- isObject: 判断是否是对象
- isPromise: 判断是否是Promise
- toRawType: 获取对象的类型
- isPlainObject: 判断是否是普通对象
- isBuiltInDirective: 判断是否是内置指令
- camelize: 将字符串转换为驼峰
- hyphenate: 将驼峰格式的字符串转换为以短横行为分隔符的连字符
- capitalize: 将字符串首字母大写
- toHandlerKey: 将字符串转换为事件处理的key
- looseToNumber: 将字符串转换为数字
- toNumber: 将字符串转换为数字
- getGlobalThis: 获取全局对象
推荐文章
-
2024-03-17 07:12:40 浏览量: 1015
-
2024-04-24 19:57:51 浏览量: 1117
-
2024-04-17 14:24:51 浏览量: 1010
-
2024-05-16 10:08:01 浏览量: 1012
-
2024-05-18 18:17:35 浏览量: 1009
-
2024-02-23 17:39:12 浏览量: 1011
-
2024-05-04 10:37:44 浏览量: 1013
-
2024-04-24 08:00:02 浏览量: 1017
-
2024-05-05 06:27:43 浏览量: 1016
-
2024-05-18 18:26:30 浏览量: 1004
-
2024-03-15 08:46:32 浏览量: 1016
-
2024-03-22 13:42:22 浏览量: 1020
-
2024-04-06 10:10:52 浏览量: 1025
-
2024-05-18 18:29:25 浏览量: 1012
-
2024-03-21 00:57:53 浏览量: 1010
-
2024-02-29 09:32:30 浏览量: 1009
-
2024-04-15 21:32:54 浏览量: 1007
-
2024-03-22 08:42:43 浏览量: 1010
-
2024-02-15 23:08:03 浏览量: 1002
-
2024-03-22 05:17:24 浏览量: 1007