改变——this,data,computed,components,周期函数,$refs,props,provide/inject,$watch,$wathcEffect,$nextTick

在setup里,this不能再用了

为什么不能使用this?官方是这样说的:

在 setup() 内部,this 不会是该活跃实例的引用,因为 setup() 是在解析其它组件选项之前被调用的,
所以 setup() 内部的 this 的行为与其它选项中的 this 完全不同。这在和其它选项式 API 一起使用 setup() 时可能会导致混淆。
我们可以理解为:
this 未指向当前的组件实例,在setup被调用之前,data,methods,computed等都没有被解析,但是组件实例确实在执行setup函数之前就已经被创建好了
作者:忘魂儿 https://www.bilibili.com/read/cv12456516 出处:bilibili

替代方法,但是不推荐在组合式中使用以下方法,(即组合式中不推荐用this,"不纯洁..等原因")
import { getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance();  //此处一定是proxy(官网也是),网上有很多用ctx,但是ctx是获取不到的

选项式中的data换做ref,reactive定义数据

1. ref适用于定义基础数据类型的,比如string,number,boolen;在方法中使用时要通过.value获取,在html中则不需要
2. reactive适合用于定义复杂类型的数据,比如object,array;只能接收对象
3. ref也可以用于定义复杂数据,但其实对于复杂的对象,ref还是求助于reactive处理

简言之:看起来ref比reactive有更多功能,缺点就是要.value

computed选项换做函数

import { computed } from 'vue'
const doSomething = computed(() => {
  do something...
})

在组合式里不用components,直接引入就可以用了

<script setup>
import TodoItem from './ToduItem.vue'
</script>
<TodoItem />

周期函数

1. 取消掉了beforeCreate, created,setup在它俩之前执行,也因此有的数据要在onMounted里取才行(当时具体情况我忘了,但是我确实遇到过)
2. 在vue2中vue3的代码是以补丁的形式加上去的,所以vue2的周期函数会比vue3先执行
3. 在vue3中vue3的先执行

选项式里获取节点的$refs在组合式

<div ref="myDiv"></div>

<script setup>
import { ref } from 'vue'
const myDiv = ref()
console.log(myDiv)    //这就取到了
</script>

props在组合式通过defineProps获取

import { defineProps } from 'vue'

let props = defineProps({
  msg1: { type: String, required: true },  //或者
  msg2: String
})
//还可以做ts校验
interface Props{
  msg1: String
  msg: String
}
let props = defineProps<Props>()

provide/inject

组件间数据传输的api
和prop的不同之处:

  1. 父亲props要传递数据给孙子,那需要父传子,子传孙。而provide不同,一个组件provide数据后,该组件的所有子组件都可以通过inject获取到该数据
  2. props是单向的,父组件改数据子组件会改,但是子组件改props里的数据不会影响父组件。provide/inject不同,如果传递的是ref或者reactive类型的数据,父子组件都可以改数据,而且还实时的渲染修改后的数据
  3. 最好是在组合式api里用,在选项式里provide的数据好像不能实时渲染(inject的可以)。用法:
    father.vue
<script setup>
import {provide} from 'vue'

let firstname = ref("李")
provide("姓", firstname)  //注意此处不带.value
</script>

son.vue

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

let firstname = inject("姓")
</script>

grandSon.vue

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

let firstname = inject("姓")
</script>

watch

watch需要监听指定的ref或者reactive对象。
如果监听的值一次都没有改变,那我一次都不触发。不像watchEffect要触发一次
如果监听整个reactive对象的话,并不能打印出正确的oldvalue,而是old value也和new value一样

触发两次setName()之后发现,oldvalue 和 newvalue一样

要监听具体的属性/变量,才会打印出正确的oldvalue,newvalue

watchEffect

不需要指定监听对象,在watchEffect参数函数里用到的ref,reactive类型变量都会被自动监听
不论改变与否,我都会触发一次,如果有改变会继续触发,如果没有,就从此不触发
userinfo.age改变了,但是watchEffect里只有用到userinfo,没有用到userinfo.age则不会监听到

nextTick

在组合式中不像选项式那样有this,随时帮忙“看着”,在这里就需要把nextTick放在每一个会导致dom重新渲染的事件里
nextTick和watch不同,watch监听的是数据改变,nextTick监听的是被改的数据重新渲染到dom(在watch之后)
<script setup>
import { ref, nextTick } from 'vue'
const par = ref()
function changeMsg() {
    msg.value += '~,'
    console.log("before render: ", par.value.innerHTML);
    nextTick(() => {
        console.log("be rendered: ", par.value.innerHTML);
    })
}
</script>
<p ref="par" @click="changeMsg">{{ msg }}</p>

//除了这种用法还可以同步使用:
async function changeMsg(){
  msg.value += '~,'
  console.log("before render: ", par.value.innerHTML);
  await nextTick()
  console.log("be rendered: ", par.value.innerHTML);
}

posted on 2022-03-07 12:26  In-6026  阅读(99)  评论(0)    收藏  举报

导航