Vue3-拉开序幕的setup

news2024/11/27 5:40:47

Vue3 中的 setup 是一个新的配置项,值是一个函数。

export default {
  name: 'App',
  setup: function () {
    
  }
}
</script>

和 Vue2 中的 data 一样,我也可以将 setup 简写成为

export default {
  name: 'App',
  setup() {
    
  }
}

setup函数的使用

与 Vue2 不一样的是,setup 中包含了 data 数据,methods方法,computed计算属性,watch监听器等等一系列的属性,也就是说,在 Vue3 中,我们不会显式的把这些属性配置到 setup 中,而是直接将属性内部的数据或方法直接暴露在 setup 中

ps:本章所讲内容,不涉及响应式,也就是说 在 setup 中定义的数据,不是响应式的,如何转为响应式数据,下一章节 ref 会讲到。但是 props 传递的数据是响应式的。

setup() {
    // 类似于data属性中的数据,不过不用显式的声明data,而是直接设置变量
    let name = 'al'
    let age = 18

    // 类似于methods属性中的方法
    function hello() {
      // 因为这是直接在 setup 函数中访问变量,直接访问就行,不用 this
      alert(`我的名字是${name},我的年龄是${age}`) 
    }
  }

 setup 的参数

 setup 函数接收两个参数,分别是 props上下文 context

props 是响应式的数据,且在传入新的 props 时,会同步更新现有的 props。例如

export default {
  // 如果这里接收到的 props 改变了
  props: {
    title: String
  },

  // 那么这里的接使用的props也会同步改变
  setup(props) {
    console.log(props.title)
  }
}

同时需要注意的是,在使用props传递的数据时时,尽量采取 props.xxx的方式进行。

对于传递的 props尽量不要解构,因为解构得出的变量将会丢失响应式。如果确实需要解构,或者将 props中的某一项数据传递的同时保持响应式,可以采用 torefs 和 toref 来进行转化。

import { toRefs, toRef } from 'vue'

export default {
  setup(props) {
    // 将 `props` 转为一个其中全是 ref 的对象,然后解构
    const { title } = toRefs(props)
    // `title` 是一个追踪着 `props.title` 的 ref
    console.log(title.value)

    // 或者,将 `props` 的单个属性转为一个 ref
    const title = toRef(props, 'title')
  }
}

第二个参数则是上下文 context ,其中暴露了一些在setup 中可能会用到的值,例如:

export default {
  setup(props, context) {
    // 透传 Attributes(非响应式的对象,等价于 $attrs)
    console.log(context.attrs)

    // 插槽(非响应式的对象,等价于 $slots)
    console.log(context.slots)

    // 触发事件(函数,等价于 $emit)
    console.log(context.emit)

    // 暴露公共属性(函数)
    console.log(context.expose)
  }
}

这个 context 不是响应式的,可以直接解构,

export default {
  setup(props, { attrs, slots, emit, expose }) {
    ...
  }
}

其中 attrs 和 slots 都是有状态的对象,会随着组件自身更新而更新,但是二者都不是响应式数据,所以在使用时,同样避免解构,而是尽量通过 attrs.x 或 slots.x 方式。如果想要基于 attrs 或 slots的改变来执行副作用,那么可以在 onBeforeUpdate 声明周期中编写逻辑。

emit则是用来触发函数,和 Vue2 中作用一致。

expose 的作用则是显式的限制向外暴露的属性。当父组件引用子组件时,只能访问到通过可 expose 暴露特定的方法。当 expose 不传递参数时,代表不暴露任何东西,当传递对象时,则有选择的暴露局部状态。

import { h, ref } from 'vue'

export default {
  setup(props, { expose }) {
    const count = 0
    const increment = () => ++count.value

    expose({
      increment
    })

    return () => h('div', count.value)
  }
}

setup 的返回值

setup 存在两种返回值:

  1. 返回一个同步对象,对象中的属性、方法在模板中均可直接使用,例如
    export default {
      name: 'App',
      setup() {
        // 类似于data属性中的数据,不过不用显式的声明data,而是直接设置变量
        let name = 'al'
        let age = 18
    
        // 类似于methods属性中的方法
        function hello() {
          alert(`我的名字是${name},我的年龄是${age}`) 
        }
    
        return {
          name,
          age,
          hello
        }
      }
    }
    <template>
      <h1>我是app组件</h1>
      <p>姓名:{{ name }}</p>
      <p>年龄:{{ age }}</p>
      <button @click="hello()">个人信息</button>
    </template>

  2. 返回一个渲染函数 ,可以自定义渲染内容(
    <script>
    import { h } from 'vue'
    export default {
      name: 'App',
      setup() {
        // 类似于data属性中的数据,不过不用显式的声明data,而是直接设置变量
        let name = 'al'
        let age = 18
    
    
        // Vue2 中的 main.js 中,在使用 render 函数时,就使用了 h 这个方法,
        // 第一个参数是节点,第二个参数是渲染内容
        // 当使用 返回 render 函数之后,html 模板中的内容都会被忽略,只会执行 h 函数的渲染内容
        return () => h('div','我改名字了')
      }
    }
    </script>

ps:返回一个渲染函数将会阻止我们返回其他东西。对于组件内部来说,这样没有问题,但如果我们想通过模板引用将这个组件的方法暴露给父组件,那就有问题了。因为此时除了渲染函数之外,暴露不了别的数据和方法了,为了解决这一问题,Vue3采用了 expose 来暴露方法或属性,然后返回渲染函数 

setup(props,{ expose }) {
  // 类似于data属性中的数据,不过不用显式的声明data,而是直接设置变量
  let name = 'al'
  let age = 18

  // 类似于methods属性中的方法
  function hello() {
    alert(`我的名字是${name},我的年龄是${age}`) 
  }

  // 通过 expose 暴露方法或属性
  expose({
    name,
    hello
  })

  // Vue2 中的 main.js 中,在使用 render 函数时,就使用了 h 这个方法,
  // 第一个参数是节点,第二个参数是渲染内容
  // 当使用 返回 render 函数之后,html 模板中的内容都会被忽略,只会执行 h 函数的渲染内容
  return () => h('div','我改名字了')
}
}

 注意事项

1、Vue2 和 Vue3 不要混用。Vue3 是向下兼容的,所以即使是在 Vue3 项目中,也可以使用 Vue2 的语法,但是也会带来一些问题。

  1. 兼容性:在 Vue3 项目中也可以使用 Vue2 的写法
    <template>
      <p>在Vue3中访问 Vue2 写法下的属性或方法</p>
      <p>姓名:{{ newName }}</p>
      <p>年龄:{{ newAge }}</p>
      <button @click="getVue3Data">点击获取Vue2写法中的数据</button>
    </template>
    
    
    <script>
    export default {
      name: 'App',
      data() {
        return {
          newName: '汤圆',
          newAge:1
        }
      },
      methods: { 
        testVue2(){
          alert(`我的名字是${this.newName},我的年龄是${this.newAge}`)
        }
      },
    }
    </script>
    

2、Vue2 的配置项( data、methods、computed... )中可以访问 Vue3 中 setup 中的属性、方法

<button @click="testVue3">点击后再Vue2写法中获取Vue3写法中setup的数据</button>

<script>
export default {
  name: 'App',
  methods: { 
    testVue3() {
      console.log(this.name);
      console.log(this.age);
      console.log(this.hello);
    }
  },
  setup() {
      // 类似于data属性中的数据,不过不用显式的声明data,而是直接设置变量
      let name = 'al'
      let age = 18

      // 类似于methods属性中的方法
      function hello() {
        alert(`我的名字是${name},我的年龄是${age}`) 
      }

      return {
        name,
        age,
        hello
      }
    }
}
</script>

点击按钮之后,控制台上打印出了 Vue3 setup 中定义的变量和方法。

3、但是在 Vue3 中的setup 中调用 Vue2 声明的变量或方法时,会无法找到

setup() {
  // 类似于data属性中的数据,不过不用显式的声明data,而是直接设置变量
  let name = 'al'
  let age = 18

  // 类似于methods属性中的方法
  function hello() {
    alert(`我的名字是${name},我的年龄是${age}`) 
  }

  function testVue4() {
    console.log(name);
    console.log(age);
    console.log(hello);

    // 因为这些属性或方法不是在 setup 内部定义的,而是按照Vue2 的配置语法定义的,所以按照Vue2的访问模式 通过 this.xxx 访问
    console.log(this.newName);
    console.log(this.newAge);
    console.log(this.testVue2);
  }
  return {
    name,
    age,
    hello,
    testVue4
  }
}

从这里可以看到,在 Vue3 的 setup 中访问 Vue2 中的方法或属性时,得到的是undefined,这是因为  setup() 自身并不含对组件实例的访问权,即在 setup() 中访问 this 会是 undefined。你可以在选项式 API 中访问组合式 API 暴露的值(在 Vue2 中访问 Vue3的属性或方法),但反过来则不行。

但是但是这里其实还存在一个问题,如果我直接在 setup 中访问 this,得到的是undefined,但是如果我是在 setup 中定义的函数中访问 this,得到的是一个 Proxy 代理对象

setup() {
  console.log(this, 'this111');

  function testVue4() {
    console.log(this,'this');
    console.log(this.newName);
    console.log(this.newAge);
    console.log(this.testVue2);
  }
  return {
    testVue4
  }
}

 首先说 直接在 setup 中访问 this,问什么会是undefined?这是因为setup函数执行时,不依赖于Vue实例,换句话说就是 setup 函数在Vue实例化之前就执行了,所以无法直接访问到this。

然后再说为什么setup 中的方法作为组件模板内容使用时(例如作为事件处理函数被调用时),那么Vue会将这个方法绑定到Vue实例上。当该函数被调用时,this指向的就是Vue组件实例。

也就是说 Vue3中无法在 setup 内部直接访问到 this,但是通过 return 出去的函数 或者绑定到模板的数据时可以访问到this。

4、如果 Vue2 和 Vue3 混用时,数据或方法出现重名情况,以 setup 中的数据优先

<template>
  <p>{{ name }}</p>
  <button @click="hello">点击查看</button>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      name: "aha",
    };
  },
  methods: {
    hello() {
      alert(`我的名字是${this.name}`);
    },
  },
  setup() {
    let name = "al";

    // 类似于methods属性中的方法
    function hello() {
      alert(`我的名字是${name}`) 
    }

    return {
      // eslint-disable-next-line vue/no-dupe-keys
      hello,
      // eslint-disable-next-line vue/no-dupe-keys
      name,
    };
  },
};
</script>

5、setup() 应该同步地返回一个对象。唯一可以使用 async setup() 的情况是,该组件是 Suspense 组件的后裔。

具体理解就是 setup 在一般情况下,不能使用  async 包裹,因为被 async 包裹之后,即使你返回的还是原来的对象,但是 async 会对象外部包裹一层 Promise,如果想要拿取数据的话,还需要通过.then() 来获取 ,模板中时无法直接看到并且使用 return 对象中的属性或方法的。而 Vue 是不会自动帮你做这件事的。

但是 也存在一直特殊情况,那就是  该组件是 Suspense 组件的后裔( 这个后在讲,我现在也没研究到这里来 )。

总结 

 1、Vue2 和 Vue3 的配置尽量不要混用

2、如果混用了,

  • Vue2 中的配置 (例如:data、methods、compute、watch等)可以访问到 setup 中的属性和方法
  • Vue3 中的setup 不能访问到 Vue2 中的配置项
  • 存在重名情况,以 Vue3 setup 中优先

3、setup 一般不用  async,因为 setup 需要同步的返回一个对象,以此来保证 模板中数据或方法正常绑定,如果用了 async 那么返回的数据对象 会被 Promise 包裹,模板中无法看到对象中的属性,无法绑定。但是 当该组件是 Suspense 组件的后裔时,可以使用  async setup()

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1952281.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

刷题计划 day4 【双指针、快慢指针、环形链表】链表下

⚡刷题计划day4继续&#xff0c;可以点个免费的赞哦~ 下一期将会开启哈希表刷题专题&#xff0c;往期可看专栏&#xff0c;关注不迷路&#xff0c; 您的支持是我的最大动力&#x1f339;~ 目录 ⚡刷题计划day4继续&#xff0c;可以点个免费的赞哦~ 下一期将会开启哈希表刷题…

十一、【Python】基础教程-【Python全掌握】六大基础数据类型:布尔类型的终极指南

目录 一、基础类型“布尔型”处理方法 1. 直接赋值和使用 2. 布尔值的逻辑运算 3. 条件语句中的布尔值 4. 布尔值转换 5. 短路逻辑 6. 在循环和迭代中的使用 一、基础类型“布尔型”处理方法 在Python中&#xff0c;布尔类型是一种基本的数据类型&#xff0c;用于表示逻…

MySQL 索引相关基本概念

文章目录 前言一. B Tree 索引1. 概念2. 聚集索引/聚簇索引3. 辅助索引/二级索引4. 回表5. 联合索引/复合索引6. 覆盖索引 二. 哈希索引三. 全文索引 前言 InnoDB存储引擎支持以下几种常见索引&#xff1a;BTree索引&#xff0c;哈希索引&#xff0c;全文索引 一. B Tree 索引…

1、hadoop环境搭建

1、环境配置 ip(/etc/sysconfig/network-scripts) # 网卡1 DEVICEeht0 TYPEEthernet ONBOOTyes NM_CONTROLLEDyes BOOTPROTOstatic IPADDR192.168.59.11 GATEWAY192.168.59.1 NETMASK 255.255.255.0 # 网卡2 DEVICEeht0 TYPEEthernet ONBOOTyes NM_CONTROLLEDyes BOOTPROTOdh…

均匀圆形阵列原理及MATLAB仿真

均匀圆形阵列原理及MATLAB仿真 目录 前言 一、均匀圆阵原理 二、圆心不存在阵元方向图仿真 三、圆心存在阵元方向图仿真 四、MATLAB仿真代码 总结 前言 本文详细推导了均匀圆形阵列的方向图函数&#xff0c;对圆心不放置阵元和圆心放置阵元的均匀圆形阵列方向图都进行了仿…

前端JS特效第57波:响应式博客网站图文幻灯片

响应式博客网站图文幻灯片&#xff0c;先来看看效果&#xff1a; 部分核心的代码如下&#xff1a; <!DOCTYPE html> <html lang"zh-CN"><head> <meta charset"utf-8"> <title>响应式博客幻灯片演示</title><link …

pyuic5将ui文件转换为py文件报错:one input ui-file must be specified;no element found;

ERROR 1 文件命名不规范Solution 1:文件命名不能有空格 ERROR 2未选中ui文件 Solution 2:选中要转换成py 的文件

深入解析:百数平台图表联动功能设置与实战应用

在当今数据驱动的时代&#xff0c;图表的联动功能已成为数据分析的得力助手。通过深度整合各类图表&#xff0c;如柱形图、折线图、饼图、雷达图、条形图、透视图、面积图、双轴图、地图以及漏斗图等&#xff0c;我们实现了图表之间的无缝衔接&#xff0c;使得数据的呈现与探索…

基于FFmpeg和SDL的音视频解码播放的实现过程与相关细节

目录 1、视频播放器原理 2、FFMPEG解码 2.1 FFMPEG库 2.2、数据类型 2.3、解码 2.3.1、接口函数 2.3.2、解码流程 3、SDL播放 3.1、接口函数 3.2、视频播放 3.3、音频播放 4、音视频的同步 4.1、获取音频的播放时间戳 4.2、获取当前视频帧时间戳 4.3、获取视…

RFID标签打印机助力服装厂实现智能化管理

随着服装行业的快速发展&#xff0c;传统的管理模式已无法满足现代化生产的需求。RFID技术作为一种先进的自动识别技术&#xff0c;正在改变服装厂的管理方式。常达智能物联致力于为客户提供高效的RFID解决方案&#xff0c;其中RFID标签打印机在服装厂的应用尤为重要。本文将探…

IDEA-安装插件 驼峰下划线转换

第一步&#xff1a;安装 file-settings-plugins-在marketplace搜索“CamelCase”-点击安装 第二步&#xff1a;设置 file-settings-editor-camel_case 第三步&#xff1a;使用 选中想转换的遍历 使用快捷键 Alt Shift U

【算法专题】双指针算法之LCR 179. 查找总价格为目标值的两个商品(力扣)

欢迎来到 CILMY23的博客 &#x1f3c6;本篇主题为&#xff1a;双指针算法之LCR 179. 查找总价格为目标值的两个商品&#xff08;力扣&#xff09; &#x1f3c6;个人主页&#xff1a;CILMY23-CSDN博客 &#x1f3c6;系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法…

C++学习笔记——模板

学习视频 文章目录 模板的概念函数模板函数模板语法函数模板注意事项函数模板案例普通函数与函数模板的区别普通函数与函数模板的调用规则模板的局限性 类模板类模板与函数模板区别类模板中成员函数创建时机类模板对象做函数参数类模板与继承类模板成员函数类外实现类模板分文件…

2024年钉钉杯大数据竞赛A题超详细解题思路+python代码手把手保姆级运行讲解视频+问题一代码分享

初赛A&#xff1a;烟草营销案例数据分析 AB题综合难度不大&#xff0c;难度可以视作0.4个国赛&#xff0c;题量可以看作0.35个国赛题量。适合于国赛前队伍练手&#xff0c;队伍内磨合。竞赛获奖率50%&#xff0c;八月底出成绩&#xff0c;参赛人数3000队左右。本文将为大家进行…

docker安装部署elasticsearch7.15.2

docker安装部署elasticsearch7.15.2 1.拉取es镜像 docker pull docker.elastic.co/elasticsearch/elasticsearch:7.15.2如果不想下载或者镜像拉去太慢可以直接下载文章上面的镜像压缩包 使用镜像解压命令 docker load -i elasticsearch-7-15-2.tar如下图所示就表示镜像解压成…

基于GitHub page和Hexo主题搭建个人博客(win)

1.安装git git官网下载地址&#xff1a;Git - Downloads (git-scm.com) (1)下载&#xff1a;进入官网&#xff0c;选择对应版本下载&#xff0c;得到.exe文件 (2)安装&#xff1a;打开.exe文件&#xff0c;进行如下操作 (3)安装好后&#xff0c;右击鼠标&#xff0c;点击显示…

大数据学习之Flink基础

Flink基础 1、系统时间与时间时间 系统时间&#xff08;处理时间&#xff09; 在Sparksreaming的任务计算时&#xff0c;使用的是系统时间。 假设所用窗口为滚动窗口&#xff0c;大小为5分钟。那么每五分钟&#xff0c;都会对接收的数据进行提交任务. 但是&#xff0c;这里有…

深度学习的前沿主题:GANs、自监督学习和Transformer模型

&#x1f48e; 欢迎大家互三&#xff1a;2的n次方_ &#x1f48e;1. 介绍 深度学习在人工智能领域中占据了重要地位&#xff0c;特别是生成对抗网络&#xff08;GANs&#xff09;、自监督学习和Transformer模型的出现&#xff0c;推动了图像生成、自然语言处理等多个领域的创…

AI跟踪报道第49期-新加坡内哥谈技术-本周AI新闻: 开源AI王者归来的一周

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

杭州社保卡办理-农业银行版本

step 1、杭州滨江高新支行 被告知只能工作日办理&#xff08;由于工作时间冲突&#xff0c;办理不了&#xff09; 询问哪个支行可以办&#xff0c;回答说不知道&#xff0c;让我自己去问。银行服务态度较差。 step 2、杭州滨江江南支行 市民卡显示这家&#xff0c;周六可以…