从Vue2切换Vue3的一些记录

277 阅读1分钟

基于"vue": "^3.2.38"

watchEffect和watchPostEffect

watchEffect简单理解就是一个立即执行函数,这个函数里面所有用到的变量都会被监听,一但改变,会再次触发这个立即函数。 函数的形参自带一个回调函数,在每次监听到数据改变或者组件销毁的时候都会触发。watchEffect里面定义的计时器在组件销毁并不会停止,可以用这个回调去清掉这个计时器。
watchPostEffect如果想在侦听器回调中能访问被 Vue 更新之后的DOM,其它和watchEffect一样

<script setup>
import { ref, watchEffect } from 'vue'
let num = ref(0);
watchEffect((callback)=>{
  let timer = setInterval(() => {
    num.value++
    console.log(num.value)
  }, 1000);
  callback(()=>{clearInterval(timer)})
})
</script>

watchEffect可以监听到嵌套对象的具体值改变,如果只监听外层对象obj.value是监听不到里面值变化的

<script setup>
import { ref, watchEffect } from 'vue'
let obj = ref({
  name:{
    name1:{
      name2:"秃然"
    }
  }
});
watchEffect((callback)=>{
  // 可以监听到嵌套对象的具体值改变,只监听obj.value,是不行的
  console.log("监听到",obj.value.name.name1.name2)
})
const reset = ()=>{
  obj.value.name.name1.name2 = "就很秃然";
}
</script>
<template>
  <button @click="reset">修改num</button>
  <input type="text" v-model="obj.name.name1.name2">
</template>

watch

// 监听多个数据源
const x = ref(0)
const y = ref(0)
watch([x, y], ([newX, newY],[oldX,oldY]) => {
  console.log(`x is ${newX} and y is ${newY}`)
  console.log("旧值",oldX,oldY);
})

watchEffect和watch有什么区别?

watch监听具体值,并不会直接触发,等监听的值发生改变才会触发。
watchEffect监听这个函数里面使用到的所有响应式值,并且他是个立即执行函数,组件加载就会立刻触发一次。

父子组件事件通信和传值

$emit可以在行内直接触发父组件事件
defineEmits 可以通过事件触发父组件事件
defineProps 接收props

父组件

<script setup>
import { ref } from 'vue'
import HelloWorld from './components/HelloWorld.vue'
const postFontSize = ref(0)
const test = (e) => {
  console.log(e)
  postFontSize.value++;
}
</script>

<template>
  {{postFontSize}}
  <div>
    <HelloWorld @enlarge-text="test" title="我是title" name="我是name"></HelloWorld>  
  </div>
</template>

子组件

<script setup>
import { ref, onMounted, watchEffect } from 'vue'
const props = defineProps(["title", "name"]);
// 想通过事件去触发,需要定义 defineEmits
const emit = defineEmits(['enlarge-text'])
const submit = ()=>{
  emit('enlarge-text',111)
}
</script>

<template>
  <div>
    <div>
      {{ title }}
    </div>
    <div>
      {{ name }}
    </div>
    <button @click="submit">想通过事件去触发--传值按钮</button>
    <button @click="$emit('enlarge-text',222)">直接传值按钮2</button>
  </div>
</template>

新的传值方式provideInjectreadonly

简单父子组件场景使用props足够,但子组件套子组件,层次较多,使用它更方便

父组件用 provide 定义变量, 它的值可以被子组件修改,不想被子组件修改加上readonly

<script setup>
import { ref, provide } from 'vue'
import Child from './Child.vue'
const message = ref('hello')
provide('message', message) //定义的值可被子组件修改
// provide('message', readonly(count)) readonly可以防止被子组件修改
</script>

<template>
  <input v-model="message">
  <Child />
</template>

子类用inject接收变量

<script setup>
import { inject } from 'vue'

const message = inject('message')
</script>

<template>
  <p>
    Message to grand child: {{ message }}
  </p>
</template>

先到这,我看到什么需要注意的再补进去