关于vue3的一些前端面试题

发布于:2024-07-04 ⋅ 阅读:(18) ⋅ 点赞:(0)

1.ref()

  • 响应式对象
  • 顶级响应式对象,可以在模板中直接使用不用添加 .value,可以直接使用
  • ref() 对像更新,Vue会自动检测更新,然后更新Dom
  • 深层次的对象也可以是响应式,也会被追踪
  • shallowRef() 是ref的浅层次表现,深层次的浅套不起作用
  • triggerRef() 强制触发依赖于一个浅层 ref 的副作用,这通常在对浅引用的内部值进行深度变更后使用。
  • toRef() 复制reactive()内的对象变成 ref
  • toRefs() 复制reactive()内的对象变成 ref`
  const obj = reactive({
    name: 'wangxuan',
    age: 18
  })

  const rName = toRef(obj, 'name')
  // rName.value = 'wangxuan'

  const rObj = toRefs(obj)
  // rObj.name.value = 'wangxuan'
  // rObj.age.value = 18

2.reactive()

  • reactive()本身具有响应式,不用添加 .value
  • 深层次的对象也可以是响应式,也会被追踪
  • 深层次的对象,如果只修改了内部属性,不会触发更新,需要使用 shallowReactive(),推出深层次
  • reactive()有局限性,所以推荐使用 ref()

    • 只对对象、数组、Set、Map等具有深层次的响应,不能对 stringnumberboolean等基本类型进行响应式
    • 不能替换整个对象,整个替换会失去响应式
    • 对解构操作不友好。要想结构出到本地对象还是响应式,可以用ref() 对象包裹,例子:
    const state = reactive({
      count: 0
    })
    // 结构出来的count就失去了响应式
    const { count } = state
    
    // 需要这样
    const state = reactive({
      count: ref(0)
    })
    // 结构出来的count是响应式
    const { count } = state

3.computed

  • 计算属性的返回值也是一个ref()对象,具有响应式。
  • 计算属性会缓存,只有当依赖的响应式发生变化时才会重新计算。
  • 计算属里 不要改变其他状态、在 getter 中做异步请求或者更改 DOM,这些操作可以在watch()中完成
  • 计算属性最好只作为一个只读的属性,官方推荐。
  • 想要更改计算属性的返回值,需要重新写计算属性的getter()setter()方法,一下例子:
  const state = ref('已读')
  const state1 = ref('回复')
  // 更改计算属性的返回值
  const countRef = computed({
    get: () => {
      return state.value + ' ' + state1.value
    },
    set: (val) => {
      [state.value, state1.value] = val.split(' ')
    }
  })
  countRef.value = '已读 乱回'
  console.log(state.value) // 已读
  console.log(state1.value) // 乱回

4.watch

-浅层监听

  // 监听单个属性
  watch(state, (newVal, oldVal) => {
    console.log(newVal, oldVal)
  })
  // 监听多个属性,多个属性的监听,newValue是一个位置与监听源一致的数组
  watch([state, state1], (newVal, oldVal) => {
    console.log(newVal, oldVal)
  })
  // 监听reactive对象, satae对象的任意属性都会被监听
  // 监听响应式对象的单个属性值的时候需要用getter函数的形式监听
  watch(()=> state.value, (newVal, oldVal) => {
    console.log(newVal, oldVal)
  })
  // 监听整个响应式对象
  watch(state, (newVal, oldVal) => {
    console.log(newVal, oldVal)
  })
  // 监听getter函数,函数被调用就会执行
  watch(()=> sate.value + state1.value, (newVal, oldVal) => {
    console.log(newVal, oldVal)
  })

-深层监听添加{deep: true}属性,一般不使用渐层监听其实已经带了,添加{deep: true}会遍历整个监听对象,降低性能没有必要的时候避免使用
-{immediate:true}属性可以在创建监听起的时候就触发监听器
-{once:true}属性只监听一次
-{flush:'pre'}属性在DOM更新前执行监听器
-{flush:'post'}属性在DOM更新后执行监听器
-{flush:'sync'}属性在DOM更新前执行监听器

5.watchEffect

  • 不需要指定监听源,在回调里被用到的响应式属性都会被监听
  • 想要监听的对象,在回调中多个属性被用到都会触发监听
  • watch的区别就在于不需要指定监听源,watchEffect会更高效,写法也会更简洁
  • 在异步回调中使用监听器需要手动停止监听,返回一个停止函数,调用停止函数即可停止监听
const stop = watchEffect(() => {
  console.log(state.value)
})
stop() // 手动停止监听

6.组件传值

  • 模版引用可以 <ChildComponent ref="childRef" />childRef就是子组件的引用,可以访问自组件所有属性, 子组件要通过defineExpose先暴露属性值
  • 保持单项数据流
  • 双向绑定,子组件使用defineModel()声明,父组件使用v-model绑定,子组件发生改变,父组件也会变化
  • 父组件通过props属性传递数据给子组件
// 父组件 -> 子组件
<ChildComponent :name="name" :age="age" />
// 子组件接收
const props = defineProps({
  name: String,
  age: Number,
  text: String,
  // 参数校验,必填与默认值
  text1: {
    type: String,
    default: 'hello',
    required: true
  }
})

// 子组件 -> 父组件
const emit = defineEmits({
  'change': null,
  // 事件校验
  'click': ()=> {
    return true
  }
  })
emit('change', 'hello')

// 子组件 -> 父组件
const emit = defineEmits(['change'])
emit('change', {
  name: 'hello',
  age: 18
})

7.provide/inject

  • 父组件通过provide传递数据,子组件通过inject接收数据
  • 子组件可以接收父组件传递的数据,也可以接收祖先组件传递的数据
  • 保证数据流是单向的,也可以提供更改父组件数据的方法,在子组件中调用
// 父组件
const state = reactive({
  name: 'hello',
  age: 18
})
provide('state', state)

// 子组件
const state = inject('state')

8.v-if vs v-for

  • v-if 优先级更高,如果同时使用,v-if先执行
  • 不推荐同时使用

9.v-for 也可以使用 of替代in这样写更接近js的迭代器的语法

作为开发者,我们需要保持好奇心和学习热情,不断探索新的技术,只有这样,我们才能在这个快速发展的时代中立于不败之地。介绍一款程序员都应该知道的软件JNPF快速开发平台,很多人都尝试用过它,它是功能的集大成者,任何信息化系统都可以基于它开发出来。

JNPF可以实现应用从创建、配置、开发、测试到发布、运维、升级等完整生命周期的管理。减少了传统应用程序的代码编写量,通过图形化、可视化的界面,以拖放组件的方式,即可快速生成应用程序的产品,大幅降低了开发企业管理类软件的难度。

当然,我更建议大家成为一个全栈,不要把自己的定位局限于前端。

感谢阅读本文

如果有什么建议,请在评论中让我知道。我很乐意改进。


网站公告

今日签到

点亮在社区的每一天
去签到