Vue3中Compositions API的使用(二)

导读:本篇文章讲解 Vue3中Compositions API的使用(二),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

setup中的函数

上一篇讲解了setup的基本使用以及setup函数中的ref和reactive函数实现响应式数据

setup函数中还有其他的函数, 比如: computed, Provide, Inject, watch等等

接下来我们会讲解setup中的其他函数的使用

1.computed函数

在前面我们讲解过计算属性computed:当我们的某些属性是依赖其他状态时,我们可以使用计算属性来处理

  • 在前面的Options API中,我们是使用computed选项来完成的;
  • 在Composition API中,我们可以在 setup 函数中使用 computed 方法来编写一个计算属性

如何使用computed呢?

  • 方式一:只接收一个getter函数,并为 getter 函数返回的值,返回一个不变的 ref 对象;
setup() {
  const name = reactive({
    firstName: "chen",
    lastName: "yq"
  })

  // 只接收一个getter函数作为参数, 返回的是一个固定的ref对象
  const fullName = computed(() => {
    return name.firstName + " " + name.lastName
  })

  return {
    fullName
  }
}
  • 方式二:接收一个具有 get 和 set 的对象,返回一个可变的(可读写)ref 对象;
setup() {
  const name = reactive({
    firstName: "chen",
    lastName: "yq"
  })

  // 既有getter函数又有setter函数, 需要传入一个对象作为参数
  const fullName = computed({
    // set函数 会返回一个可变的ref对象
    set: newValue => {
      const names = newValue.split(" ")
      name.firstName = names[0]
      name.lastName = names[1]
    },
    get: () => {
      return name.firstName + " " + name.lastName
    }
  })

  // 因为返回对象, 索引fullName.vlue设置fullName的值
  fullName.value = "aaa bbb"

  return {
    fullName
  }
}

2.setup中获取元素

在setup中如何使用ref获取元素或者组件?

  • 其实非常简单,我们只需要定义一个ref对象,绑定到元素或者组件的ref属性上即可;
<template>
  <div>
    <h2 ref="h2Ref">1111</h2>
  </div>
</template>

<script>
  import { ref, onMounted } from 'vue'

  export default {
    setup() {
      const h2Ref = ref()

      onMounted(() => {
        console.log(h2Ref.value) 
      })

      return {
        h2Ref
      }
    }
  }
</script>

3.setup中生命周期

我们前面说过 setup 可以用来替代 data 、 methods 、 computed 等等这些选项,也可以替代 生命周期钩子

那么setup中如何使用生命周期函数呢?

  • 可以使用import直接导入的 onX 函数注册生命周期钩子;
  • 在setup函数中, 使用onX调用生命周期钩子即可
![Snipaste_2022-07-21_20-03-17](img/Snipaste_2022-07-21_20-03-17.png)// 引入注册生命周期的函数
import { onBeforeMount, onMounted } from 'vue'
export default {
  // 向注册函数中传入生命周期函数
  setup() {
    onBeforeMount(() => {
      console.log("onBeforeMounted")
    })

    onMounted(() => {
      console.log("onMounted")
    })
  }
}

以前的生命周期钩子对应的setup中关系如下图 :

在这里插入图片描述

我们发现, created和beforeCreate两个函数是没有对应的注册生命周期函数的, 官方给出的解释如下 :

在这里插入图片描述

4.Provide-Inject函数

事实上我们之前还学习过Provide和Inject,Composition API也可以替代之前的 Provide 和 Inject 的选项

我们可以通过 provide来提供数据

  • 可以通过 provide 方法来定义每个 Property;

provide可以传入两个参数

  • name:提供的属性名称;
  • value:提供的属性值;
import { provide } from 'vue'

export default {
  setup() {
    // 将导出数据设置为响应式
    const name = ref("chenyq")
    const age = ref(18)

    provide("name", name)
    provide("age", age)
  }
}

在后代组件中可以通过 inject 来注入需要的属性和对应的值

  • 可以通过 inject 来注入需要的内容;

inject可以传入两个参数

  • 要 inject 的 property 的 name;
  • 默认值;
setup() {
  const name = inject("name", "默认值")
  const age = inject("age")

  return {
    name,
    age
  }
}

5.侦听数据变化函数

在前面的Options API中,我们可以通过watch选项来侦听data或者props的数据变化,当数据变化时执行某一些操作
在Composition API中,我们可以使用watchEffectwatch来完成响应式数据的侦听

  • watchEffect:用于自动收集响应式数据的依赖;
  • watch:需要手动指定侦听的数据源;

watch使用

watch的API完全等同于组件watch选项的Property

  • watch需要侦听特定的数据源,并且执行其回调函数;
  • 默认情况下它是惰性的,只有当被侦听的源发生变化时才会执行回调;
setup() {
  let message = ref("hello vue3 setup")

  watch(message, (oldValue, newValue) => {
    console.log(oldValue, newValue)
  })

  function btnClick() {
    message.value = "你好 vue3 setup"
  }

  return {
    message,
    btnClick
  }
}

侦听器还可以使用数组同时侦听多个源

setup() {
  let message = ref("hello vue3 setup")
  const name = ref("chenyq")

  watch([message, name], (oldValue, newValue) => {
    console.log(oldValue, newValue)
  })

  function btnClick() {
    message.value = "你好 vue3 setup"
    name.value = "kaisa"
  }

  return {
    message,
    btnClick,
    name
  }
}

watch选项

  • 如果我们希望侦听一个深层的侦听,那么依然需要设置 deep 为true:
  • 也可以传入 immediate 立即执行;
watch([message, name], (oldValue, newValue) => {
  console.log(oldValue, newValue)
}, {
  // 设置首次进行监听
  immediate: true,
  // 设置深度监听
  deep: true
})

watchEffect使用

当侦听到某些响应式数据变化时,我们希望执行某些操作,这个时候可以使用 watchEffect

  • 首先,watchEffect传入的函数会被立即执行一次,并且在执行的过程中会收集依赖;
  • 其次,只有收集的依赖发生变化时,watchEffect传入的函数才会再次执行
setup() {
  let message = ref("hello vue3 setup")
  const name = ref("chenyq")

  watchEffect(() => {
    console.log("wactchEffect执行", message.value, name.value)
  })
}

如果在发生某些情况下,我们希望停止侦听,这个时候我们可以获取watchEffect的返回值函数,调用该函数即可

  • 比如在下面的案例中,我们counter达到20的时候就停止侦听:
setup() {
  let message = ref("hello vue3 setup")
  const name = ref("chenyq")
  let counter = ref(1)

  const stopWatch = watchEffect(() => {
		// 大于20调用watchEffect的返回值函数
    if (counter.value >= 20) stopWatch()
    console.log("wactchEffect执行", counter.value)
  })
}

6.script setup语法

<script setup> 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖,当同时使用 SFC 与组合式 API 时则推荐该语法

  • 更少的样板内容,更简洁的代码;
  • 能够使用纯 Typescript 声明 prop 和抛出事件;
  • 更好的运行时性能 ;
  • 更好的 IDE 类型推断性能 ;

使用这个语法,需要将 setup attribute 添加到 <script> 代码块上

<script setup>
  console.log("hello setup")
</script>

里面的代码会被编译成组件 setup() 函数的内容

  • 这意味着与普通的 <script> 只在组件被首次引入的时候执行一次不同;
  • <script setup> 中的代码会在每次组件实例被创建的时候都会执行一次。

顶层绑定会暴露给模板 :

  • 当使用 <script setup> 的时候,任何在 <script setup> 声明的顶层绑定 (包括变量,函数声明,以及 import 引入的内容) 都能在模板中直接使用
<template>
  <div class="app">
		<!-- 无需返回值, 可以直接使用 -->
    <h2>{{ message }}</h2>
    <button @click="btnClick">按钮</button>
  </div>
</template>

<script setup>
  import { ref } from "vue"

  // 定义响应式数据
  let message = ref("hello setup")

  // 定义函数
  function btnClick() {
    message.value = "您好 组合式API"
  }
</script>

导入的组件直接使用 :

  • <script setup> 范围里的值也能被直接作为自定义组件的标签名使用
<template>
  <div class="app">
    <!-- 引入子组件同样直接使用 -->
    <show-info />
  </div>
</template>

<script setup>
  // 引入子组件, 无需注册, 引入即可使用
  import ShowInfo from "./ShowInfo.vue"
  }
</script>

组件传递defineProps() 和 defineEmits()

为了在声明 props 和 emits 选项时获得完整的类型推断支持,我们可以使用 defineProps 和 defineEmits API,它们将自动地在 <script setup> 中可用

  • 如果父组件需要向子组件传递传递属性, 需要用到defineProps()方法
<template>
  <div>
    <!-- 接收过来的参数同样可以直接使用 -->
    <h2>{{ name }} - {{ age }} - {{ height }}</h2>
  </div>
</template>

<script setup>
  // defineProps接收传递过来的参数
  const props = defineProps({
    name: {
      type: String,
      default: "aaa"
    },
    age: {
      type: Number,
      default: 0
    },
    height: {
      type: Number,
      default: 1.99
    }
  })
</script>
  • 子组件发送事件就需要defineEmits()方法
<template>
  <div>
    <button @click="showInfoClick">发出事件</button>
  </div>
</template>

<script setup>
  // 绑定函数, 并发出ShowInfoClick事件
  const emits = defineEmits()
  function showInfoClick() {
    emits("showInfoClick", "showIndo传递的参数")
  }
</script>

defineExpose()

使用 <script setup> 的组件是默认关闭的

  • 通过模板 ref 或者 $parent 链获取到的组件的公开实例,不会暴露任何在 <script setup> 中声明的绑定;

通过 defineExpose 编译器宏来显式指定在 <script setup> 组件中要暴露出去的 property

// 例如将foo暴露出去
defineExpose({
	foo
})

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/120079.html

(0)
seven_的头像seven_bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!