前端面试题[Vue3]

1. v2和v3的区别

  1. api
  • v2: options API(选项式API):优点:对于新手容易,按照固定选项实现功能缺点: 对于代码的阅读\维护\复用(逻辑)不是很友好,v2中也可以通过Mixins实现逻辑的复用
  • v3: composition API(组合式API)优点: 功能代码组合在一起
  1. 使用
  • v2: 配合vuex,对与ts的支持不是很好,不允许使用多个根节点
  • v3: 也可以使用vuex,推荐配合pina,底层就使用ts重构的,对ts支持很好,多个根节点
  1. 性能
  • v3的性能会比v2快1.2_2倍:
  • 虚拟dom的创建:v2中,数据发生变化,会将模板进行重编译,生成所有的虚拟dom,v3中数据发生变化,看该虚拟dom是否参与更新,如果参与更新,创建新的虚拟dom,如果不参与更新,直接复用上一次的虚拟dom
  • v3采用了静态标记,给静态节点打上标记,diff的过程只对比动态节点,忽略静态节点
  • 事件函数的缓存: 事件函数每次在模板编译的时候会进行缓存
  • v3的tree shaking:实际情况中,虽然依赖了某个模块,但其实只使用其中的某些功能。通过 tree-shaking,将没有使用的模块摇掉,这样来达到删除无用代码的目的,v3的打包比v2的小
  1. 数据劫持:AOP:切面编程
  • v2:Object.defineProperty
  • v3: Proxy

2. vite和webpack的区别

  • vite: 工程化工具
  • vite原理: 启动项目不会对项目进行完全打包,启动服务,将资源通过服务进行托管,项目加载而是通过浏览器利用esm(es module)的方式加载资源,使用到资源才会加载才会处理,这实际上是让浏览器接管了打包程序的部分工作。
  • webpack 真正的打包: 先读取配置文件,根据配置文件的规则进行打包,读打包的入口文件,根据入口文件的依赖进行打包,js转低级语法:babel,三方文件:loader,html:html-webpack-plugin,css文件的抽离:mini-css-extract-plugin,启动浏览器,浏览器加载资源,直接加载不会再次处理

3. vue3 如何定义响应式数据

  1. ref: 将简单数据类型或复杂数据类型处理为响应式

模板中使用自动解套value,在js中使用需要通过value访问到数据

  1. reactive: 只能将复杂数据类型处理为响应式,直接用数据不需要value

推荐的使用方式:

  • 语法层面: 简单数据类型推荐使用ref, 复杂数据类型推荐使用reactive
  • 性能: 更推荐全部使用ref, ref的性能在vue3.2之后比reactive高260%

4. script setup语法

  1. 语法: 在script标签上定义setup属性
  2. 特性:
  • vue3.2版本更新
  • setup函数的语法糖,可以直接在script中定义数据和方法,默认可以直接在模板中使用
  • 不需要export default 对象
  • 使用script setup语法后,无法给组件添加name属性进行命名,解决方案,使用vite-plugin-vue-setup-extend,则可以给script属性添加name进行组件命名

5. computed计算属性

  1. computed: 计算属性, 就是vue提供的一个函数.所以需要通过引入vue得到
  2. 语法: 调用computed函数, 传递一个回调函数,在回调函数内部进行计算,将计算好的数据return出
  3. 特性: 具有缓存, 多次调用多次定义, 除了可以传递函数,还可以传递对象, 包含get和set函数

6. watch监视

  1. 概念: 监听数据变化, 也是vue提供的一个函数, 所以需要通过引入vue得到
  2. 语法:
  • 参数1: 监视的数据
    • 监视单个数据: 直接写数据
    • 监视多个数据: 写数组,数组内放数据
    • 监视reactive对象中的某一个属性: 函数返回属性
  • 参数2: 处理函数, 两个参数
    • 参数1: 新值, 如果监视的是数组,参数1还是新值,以数组的方式体现
    • 参数2: 旧值, 如果监视的是数组,参数1还是新值,以数组的方式体现
  • 参数3: 配置对象
    • 深度监听: deep: true, 监视的是ref的对象需要开启深度监听,监视的是reactive定义的对象不需要开启深度监听
    • 首次监听: immediate: true, 开启首次监听

7. 生命周期函数

vue3中的生命周期函数来自vue,所以需要通过vue按需引入,生命周期函数可以多次调用

  1. 创建阶段
  • vue2: beforeCreate/created
  • vue3: setup
  1. 挂载阶段
  • vue2: beforeMount/mounted
  • vue3: onBeforeMount/onMounted
  1. 更新阶段
  • vue2: beforeUpdate/updated
  • vue3: onBeforeUpdate/onUpdated
  1. 销毁阶段
  • vue2: beforeDestory/destoryde
  • vue3: onBeforeUnMounte/onUnMounted

8. 组件通信

8.1. 父传子
  1. 父组件通过属性绑定传递
<script setup lang='ts'>
  import { ref } from 'vue'
  import Child from './components/Child.vue'

  const money = ref(10000000)
</script>
<template>
  <h1>
    这是App组件: {{ money }}
  </h1>
  <div>------------------------</div>
  <!-- 1. 父组件通过属性绑定去传 -->
  <Child :money="money" />
</template>
<style></style>
  1. 子组件通过defineProps接收, 子组件接收的数据在模板中可以直接使用在js中,通过defineProps的返回值使用
<script setup lang='ts'>
  const props = defineProps({
    money: {
      type: Number,
      required: true
    }
  })
</script>
<template>
  <h2>这是子组件: {{ money }}</h2>
</template>
<style></style>
8.2. 子传父
  1. 子组件获取emit对象
const emit = defineEmits(['buy-car'])
  1. 通过emit触发自定义事件,并传递数据
const buyCar = () => {
  // console.log('买车', 1000000)
  // 2. 通过emit对象触发一个自定义事件, 并且
  emit('buy-car', 1000000)
}
  1. 父组件定义自定义事件和事件函数
<script setup lang='ts'>
  import { ref } from 'vue'
  import Child from './components/Child.vue'
  const money = ref(10000000)

  // 4. 定义事件函数,内部修改money数据
  const setMoney = (val) => {
    money.value = money.value - val
  }
</script>
<template>
  <!-- 3. 定义自定义事件 -->
  <Child @buy-car="setMoney" />
</template>
<style></style>
8.3. 跨组件向下传值
  1. 父级组件通过provide提供数据
const money = ref(100000000)
provide('money', money)
  1. 后代组件通过inject注入数据
import { ref, inject } from 'vue'
const money = inject('money')
8.4. 跨组件向上传值
  1. 父组件通过provide传递函数
  2. 后代组件通过inject注入函数
  3. 调用函数将数据通过参数的方式传给父级组件
8.5. ref获取组件
  1. 创建空的ref
  2. 给组件绑定ref属性值是空的ref的名字
  3. 组件和空ref的value绑定在一起
  4. 利用ref.value获取子组件
<script setup lang='ts'>
import { ref } from 'vue'
import ComA from './components/ComA.vue'
// 1. 定义空ref
const comARef = ref(null)

const getComA = () => {
  // 3. 利用ref的value获取组件
  console.log(comARef.value?.updateMoney)
}
</script>
<template>
  <!--   2. 空的ref的value绑定为组件 -->
  <ComA ref="comARef" />
  <button @click="getComA">获取coma组件</button>
</template>
<style></style>
  1. 子组件通过defineExpose向外暴漏数据
<script setup lang='ts'>
import { ref } from 'vue'

const money = ref(1000)

const updateMoney = () => {

}

defineExpose({
  money,
  updateMoney
})

</script>
<template>
  <h2>这是comA组件</h2>
</template>
<style></style>

9. 过滤器

  1. v3废除了过滤器
  2. 想过滤数据: 定义函数

10. toRefs的使用

作用: 保证解构的数据还是响应式

原理: 将解构的数据变为ref处理

11. 路由

vue3的路由结合vue-router@4.x版本

  1. 创建路由实例, 通过createRouter进行创建,createRouter就是一个函数,来自于vue-router的按需引入
  2. 配置路由模式,通过createWebHashHistory(hash路由模式)、createWebHistory创建history路由模式
import { createRouter, createWebHashHistory as createRouterMode } from 'vue-router'
// 可以创建路由实例
// 通过参数对象进行配置
const router = createRouter({
  // createWebHashHistory 创建hash模式
  // createWebHistory 创建history模式
  history: createRouterMode(),
  // 路由规则
  routes: [
    {
      path: '/home',
      component: () => import('../views/Home/index.vue')
    },
    {
      path: '/about/:id',
      component: () => import('../views/About/index.vue')
    }
  ]
})

export default router
  1. 获取路由实例, 通过useRouter, useRouter函数来自于vue-router, 调用useRouter获取到router实例
import { ref } from 'vue'
// 引入useRouter
import { useRouter } from 'vue-router'
// 创建router实例
const router = useRouter()
const goAbout = () => {
  router.push('/about/1')
}
  1. 获取当前的路由信息, 通过useRoute, useRoute函数来自于vue-router, 调用useRoute获取到route
import { ref } from 'vue'
// 引入useRoute
import { useRoute } from 'vue-router'
// 创建route
const route = useRoute()

12. pinia

12.1. pinia相比较vuex的优势
  • 比vuex对vue3的兼容会更好
  • pinia对ts的支持更好
  • pinia和vuex5的提案很像
  • pinia的使用比vuex使用更简单方便
12.2. pinia如何使用
  • main.js中进行createPinia的引入,通过createPinia创建pinia实例,并进行挂载
// 引入创建pinia实例
import { createPinia } from 'pinia'
const pinia = createPinia()

const app = createApp(App)
// 挂载pinia
app.use(pinia)
  • 创建pinia模块, 在js文件中通过defineStore(来自于pinia),创建一个模块数据管理
    • 参数1: 模块标识
    • 参数2:配置对象(state,actions, getters)
    • 返回值: 函数
import { defineStore } from 'pinia'
// 参数1: 模块标识
// 参数2: 配置对象
// 返回值: 函数
const cartStore = defineStore('cart', {
  state: () => {
    return {
      total: '111.00'
    }
  },
  actions: {},
  getters: {}
})

export default cartStore
  • 使用模块的数据或方法, 导入模块, 直接调用模块的属性(state,getters)或方法(actions)
  • 如果想对模块的数据进行解构,通过storeToRefs处理后解构的数据变为响应式了
  • 模块肯定进行统一整合
12.3. pinia有哪些属性
  • state: 定义数据
  • actions: 定义方法, 同步和异步都可以处理
  • getters: 定义派生数据

13. v3的setup函数

  1. 作用

是compositionApi的入口函数,所以在setup函数中可以使用compositionAPI

  1. 执行时机

在beforeCreated之前,组件实例还未创建,没有this,在setup函数中无法使用this获取当前组件

  1. script setup

在vue3.2之后推出script setup,在script标签上添加setu属性,内部就相当于是setup函数

不需要return数据和方法,定义后即可使用

  1. 使用script setup后组件名字处理

安装 vite-plugin-vue-setup-extend,在vite.config.js中进行配置使用,可以在script标签上添加name属性从而给组件添加名字,name名字如果想生效,script标签内部还需要写代码

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值