带你了解 vue-next(Vue 3.0)之 小试牛刀

本文详细介绍了Vue 3.0的setup()函数,包括执行时机、state管理和响应式数据。还探讨了ref、reactive、toRefs、computed、watch等核心概念,并通过实例解析了模板引用和组件间的通信。通过学习,读者将能掌握Vue 3.0的新特性和Composition API的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

看完上一章 初入茅庐之后,相信大家已经对vue-next(Vue 3.0)有所了解了。本章带你掌握 vue-next 函数式的API,了解这些的话,无论是对于源码的阅读,还是当正式版发布时开始学习,应该都会有起到一定的辅助作用。

基本例子

直接拷贝下面代码,去运行看效果吧。推荐使用高版本的chrome浏览器,记得打开F12调试工具哦!

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<script src="https://s1.zhuanstatic.com/common/js/vue-next-3.0.0-alpha.0.js"></script>
<div id="app"></div>
<script>
  const { ref, reactive, createApp, watch, effect } = Vue
  function useMouse() {
    const x = ref(0)
    const y = ref(0)
    const update = e => {
      x.value = e.pageX
      y.value = e.pageY
    }
    Vue.onMounted(() => {
      window.addEventListener('mousemove', update)
    })
    Vue.onUnmounted(() => {
      window.removeEventListener('mousemove', update)
    })
    return { x, y }
  }
  const App = {
    props: {
      age: Number
    },
    // Composition API 使用的入口
    setup(props, context){
      console.log('props.age', props.age)
      // 定义响应数据
      const state  = reactive({name:'zhuanzhuan'});
      // 使用公共逻辑
      const {x,y} = useMouse();
      Vue.onMounted(()=>{
        console.log('当组挂载完成')
      });
      Vue.onUpdated(()=>{
        console.log('数据发生更新')
      });
      Vue.onUnmounted(()=>{
        console.log('组件将要卸载')
      })
      function changeName(){
        state.name = '转转';
      }
      // 创建监视,并得到 停止函数
      const stop = watch(() => console.log(`watch state.name:`, state.name))
      // 调用停止函数,清除对应的监视
      // stop()
      // 观察包装对象
      watch(() => state.name, (value, oldValue) => console.log(`watch state.name value:${value} oldValue:${oldValue}`))
      effect(() => {
        console.log(`effect 触发了! 名字是:${state.name},年龄:${props.age}`)
      })
      // 返回上下文,可以在模板中使用
      return {
        // state: Vue.toRefs(state), // 也可以这样写,将 state 上的每个属性,都转化为 ref 形式的响应式数据
        state,
        x,
        y,
        changeName,
      }
    },
    template:`<button @click="changeName">名字是:{
   {state.name}} 鼠标x: {
   {x}} 鼠标: {
   {y}}</button>`
  }
  createApp().mount(App, '#app', {age: 123});
</script>
</body>
</html>

设计动机

逻辑组合与复用

组件 API 设计所面对的核心问题之一就是如何组织逻辑,以及如何在多个组件之间抽取和复用逻辑。基于 Vue 2.x 目前的 API 有一些常见的逻辑复用模式,但都或多或少存在一些问题。这些模式包括:

  • Mixins

  • 高阶组件 (Higher-order Components, aka HOCs)

  • Renderless Components (基于 scoped slots / 作用域插槽封装逻辑的组件)

网络上关于这些模式的介绍很多,这里就不再赘述细节。总体来说,以上这些模式存在以下问题:

  • 模版中的数据来源不清晰。举例来说,当一个组件中使用了多个 mixin 的时候,光看模版会很难分清一个属性到底是来自哪一个 mixin。 HOC 也有类似的问题。

  • 命名空间冲突。由不同开发者开发的 mixin 无法保证不会正好用到一样的属性或是方法名。 HOC 在注入的 props 中也存在类似问题。

  • 性能。 HOC 和 RenderlessComponents 都需要额外的组件实例嵌套来封装逻辑,导致无谓的性能开销。

从以上 useMouse例子中可以看到:

  • 暴露给模版的属性来源清晰(从函数返回);

  • 返回值可以被任意重命名,所以不存在命名空间冲突;

  • 没有创建额外的组件实例所带来的性能损耗。

类型推导

vue-next 的一个主要设计目标是增强对 TypeScript 的支持。原本期望通过 ClassAPI 来达成这个目标,但是经过讨论和原型开发,认为 Class 并不是解决这个问题的正确路线,基于 Class 的 API 依然存在类型问题。

基于函数的 API 天然对类型推导很友好,因为 TS 对函数的参数、返回值和泛型的支持已经非常完备。更值得一提的是基于函数的 API 在使用 TS 或是原生 JS 时写出来的代码几乎是完全一样的。

setup() 函数

我们将会引入一个新的组件选项, setup()。顾名思义,这个函数将会是我们 setup 我们组件逻辑的地方,它会在一个组件实例被创建时,初始化了 props 之后调用。它为我们使用 vue-next 的 CompositionAPI 新特性提供了统一的入口。

执行时机

setup 函数会在 beforeCreate 之后、 created 之前执行。

state

声明 state 主要有以下几种类型。

基础类型

基础类型可以通过 ref 这个 api 来声明,如下:

const App = {
    setup(props, context){
        const msg = ref('hello')
        function appendName(){
            msg.value = `hello ${props.name}`
        }
        return {appendName, msg}
    },
    template:`<div @click="appendName">{
   { msg }}</div>`
}

我们知道在 JavaScript 中,原始值类型如 string 和 number 是只有值,没有引用的。如果在一个函数中返回一个字符串变量,接收到这个字符串的代码只会获得一个值,是无法追踪原始变量后续的变化的。

因此,包装对象的意义就在于提供一个让我们能够在函数之间以引用的方式传递任意类型值的容器。这有点像 ReactHooks 中的 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值