【vue3】12-Vue 3中的Composition Api(二)

setup中的函数

(1)computed函数使用

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

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

如何使用computed呢?

  • 方式一:接收一个getter函数,并为getter函数返回的值,返回一个不变的ref对象;
  • 方式二:接收一个具有get和set的对象,返回一个可变的(可读写) ref对象;

方式一示例:

<template>
    <div class="app">
        <h2>{{ fullNmae }}</h2>
    </div>
</template>
   
<script>
import { reactive, computed } from 'vue';
export default {
    setup() {
        // 1.定义数据
        const names = reactive({
            firstName: "kobe",
            lastName: "bryant"
        })

        const fullNmae = computed(() => {
            return names.firstName + " " + names.lastName

        })

        return {
            fullNmae,
        }
    }
}
</script>
   

方式二示例:

setup() {
  const name = reactive({
    firstName: "kobe",
    lastName: "Bryant"
  })

  // 既有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
    }
  })

  // 因为返回的是ref对象, 所以通过fullName.vlue设置fullName的值
  fullName.value = "aaa bbb"

  return {
    fullName
  }
}

(2)setup获取元素或组件

在setup中,禁用this,如何使用ref获取元素或组件呢?

ref在setup中的使用:

  • 只需要定义一个ref对象绑定到元素或者组件的ref属性上即可;

使用示例:

<template>
    <!-- 1.获取元素 -->
    <h2 ref="titleRef">我是标题</h2>
    <button ref="btnRef">按钮</button>
    <hr>

    <!-- 2.获取组件实例 -->
    <ShowInfo ref="showinfoRef"></ShowInfo>
</template>

<script>
import { onMounted, ref } from "vue";
import ShowInfo from './ShowInfo.vue'

export default {
    // 之前获取元素的做法
    // mounted(){
    //     console.log(this.$refs.title);
    //     console.log(this.$refs.button);
    // },

    components: {
        ShowInfo
    },
    setup() {
    	//定义ref对象并绑定元素或组件上的ref属性
        const titleRef = ref()
        const btnRef = ref()
        const showinfoRef = ref()

        // mounted的生命周期函数
        onMounted(() => {
            console.log(titleRef.value);
            console.log(btnRef.value);
            console.log(showinfoRef.value);
            showinfoRef.value.showinfoSum()
        })

        return {
            titleRef,
            btnRef,
            showinfoRef
        }
    }
}
</script>

(3)组件的生命周期函数

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

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

  • 可以使用直接导入的onX函数注册生命周期钩子;

以前的生命周期和composition API中的生命周期钩子对比图:

在这里插入图片描述
我们发现beforeCreat和created两个生命周期钩子在setup中没有对应的hook,官方给出的解释如下:

在这里插入图片描述

(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("chenjg")
    const age = ref(20)

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

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

inject可以传入两个参数:

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

  return {
    name,
    age
  }
}

(了解即可,在vue2中多使用vueX,vue3中使用pinia来进行复杂在数据管理)

(5)watch/watchEffect

在前面的Options API中,我们可以通过watch选项来侦听data或者props的数据变化,当数据变化时执行某一些操作。

在Composition APl中,我们可以使用watchEffect和watch来完成响应式数据的侦听;

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

watch的使用:

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

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

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

  function btnClick() {
    message.value = "oooooo"
  }

  return {
    message,
    btnClick
  }
}

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

setup() {
  let message = ref("hello world")
  const name = ref("kobe")

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

  function btnClick() {
    message.value = "oooo"
    name.value = "sevgilid"
  }

  return {
    message,
    btnClick,
    name
  }
}

额外补充:

在这里插入图片描述

watchEffect的使用

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

我们来看一个案例:

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

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

watchEffect的停止侦听:

当侦听某些响应式数据变化,我们希望执行某些操作时,比如停止侦听,这个时候我们可以获取watchEffect的返回值函数,调用该函数即可。

  • 比如在下面的案例中,我们counter达到10的时候就停止侦听:
    setup() {
        const counter = ref(0)
        // 当侦听某些响应式数据变化,我们希望执行某些操作时,这时候可以使用watchEffect
        //1. watcheffect传入的函数会立即执行一次,并且在执行过程中会收集依赖
        const stopWatch = watchEffect(() => {
            console.log("-------", counter.value);
        //2. 当依赖发生变化时,函数会再次执行
            // 判断counter.value>=10 停止监听
            if (counter.value >= 10) {
                stopWatch()
            }
        })
        return {
            counter
        }
    }

(6)script setup语法(重要)

基本使用:

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

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

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

在这里插入图片描述

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

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

顶层的绑定会被暴露给模板

当使用< script setup >的时候,任何在< script setup >声明的顶层的绑定(包括变量,函数声明,以及import引入的内容)都能在模板中直接使用:

<script setup>

// 1.所有编写在顶层的代码,都是默认暴露给template可以使用
import { onMounted, ref } from "vue";
import ShowInfo from "./ShowInfo.vue";

// 2.定义响应式数据
const message = ref("hello world")

// 3.定义函数
function changeMessage() {
    message.value = "message已被改变"
}

function infobtnClick(payload) {
    console.log("监听到showinfo内部的点击:", payload);
}

const ShowInfoRef = ref()
onMounted(() => {
    ShowInfoRef.value.foo()
})

</script>
    <!-- script放中间和顶部都可以:但放在上面可以使template和css编辑距离较近 -->

导入的组件直接使用

<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 >中可用:

(1) 如果父组件需要向子组件传递传递属性, 接收时需要用到defineProps()方法
(2)子组件发送事件就需要defineEmits()方法

代码示例:

<template>

<div>showinfo:{{ name }} - {{ age }}</div>
<button @click="showInfoBtnClick">showinfoButton</button>
</template>

<script setup>
    // 不使用语法糖的scrip标签里接收父组件传参时使用props{}
    // 使用语法糖时,定义props时使用defineProps()函数
    defineProps({
        name:{
            type:String,
            default:"无名氏"
        },
        age:{
            type:Number,
            default:0
        }
    })

    // 发送事件
    // 以前:emmits:[""]
    const emits = defineEmits(["infoClick"])
    function showInfoBtnClick(){
        emits("infoClick","showinfo内部发生了点击")
    }

</script>

defineExpose()

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

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

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

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值