vue3中的单文件组件<script setup>和setup函数区别 详解

news2025/1/16 2:50:25

文章目录

    • 简介
    • 基本语法
    • 变量和方法多的使用
    • 注册组件
    • 动态组件
    • 使用外部文件方法
    • 组件通信
      • props与defineProps、emit
      • defineEmits
      • defineExpose
    • 获取 attrs、slots 和useAttrs、useSlots 方法
    • 与普通的 < script > 一起使用
    • v-bind() CSS变量注入
    • style的新特性之global
    • 对await异步的支持
    • 没有 Src 导入

简介

setup函数

setup函数原理说明
由于setup 是在beforeCreate 和 create 生命周期阶段,组件还没有创建,即还没有进入 data 方法 阶段。
setup 返回的结果集 作为 (传统写法)data 和 method 的值,确切点说是绑定到 组件对象的属性。

< script setup> 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。当同时使用 SFC 与组合式 API 时该语法是默认推荐。相比于普通的 < script > 语法,具有以下特点:

  • 更少的样板内容,更简洁的代码。
  • 能够使用纯 TypeScript 声明 props 和自定义事件。
  • 更好的运行时性能 (其模板会被编译成同一作用域内的渲染函数,避免了渲染上下文代理对象)。
  • 更好的 IDE 类型推导性能 (减少了语言服务器从代码中抽取类型的工作)。
    简单来说<script setup> 就是 setup函数的一个语法糖,我们来看这个糖甜不甜…

基本语法

要启用该语法,需要在

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

这个脚本块将被预处理为组件的 setup() 函数,这意味着:每次组件实例被创建的时候执行。< script setup> 中的顶层绑定都将自动暴露给模板。

变量和方法多的使用

响应式状态需要明确使用响应式 API 来创建。和 setup() 函数的返回值一样,ref 在模板中使用的时候会自动解包

**使用setup函数**
<template>
  <div>{{ num }}</div>
</template>
    
<script>
import { ref } from "vue";
export default {
  name: "Home",
  setup() {
    const num = ref("setup函数形式");
    return { num };
  },
};
</script>
**使用<script setup>**
<template>
  <div>{{ num }}</div>
</template>
<script setup>
import { ref } from "vue";
const num = ref(10784512);
</script>

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

注册组件

使用setup函数形式
<template>
  <div>
    <Child></Child>
  </div>
</template>
    
<script>
import Child from "./Child.vue";
export default{
  components:{
    Child
  }
}
</script>
使用setup语法糖形式
<template>
  <div>
    <Child></Child>
  </div>
</template>
    
<script setup>
import Child from "./Child.vue";
</script>

当使用语法糖形式,不需要在component 在注册了,直接引入使用组件即可。强烈建议使用 PascalCase (驼峰式)格式以保持一致性。同时也有助于区分原生的自定义元素。

动态组件

<template>
  <component :is="someCondition ? Child : ToRef" />
</template>

<script setup>
import {ref} from 'vue'
import Child from "./Child.vue";
import ToRef from "./Toref.vue";
const someCondition=ref('1')
</script>

由于组件是通过变量引用而不是基于字符串组件名注册的,
在 < script setup> 中要使用动态组件的时候,应该使用*动态的 :is 来绑定

使用外部文件方法

setup函数形式
<template>
  <div class="home">
    <h1>使用了setup函数</h1>
    <h2> {{lowercase1(name)}}</h2>
  </div>
</template>
<script>
import { ref } from 'vue'
import { lowercase } from '@/utils/lowercase.js'
export default {
  setup () {
    const name = ref('MYNAME')
    const lowercase1 = lowercase
    return { name, lowercase1 }
  }
}
</script>
setup语法糖形式
<template>
  <div class="about">
    <h1>使用了script setup</h1>
    <h2>1.使用变量 {{lowercase(name)}}</h2>
  </div>
</template>
 
<script setup>
import { lowercase } from '@/utils/lowercase.js'
import { ref } from 'vue'
const name = ref('MYNAME')
</script>

不需要在定义成一个方法,script setup格式直接使用即可

组件通信

props与defineProps、emit

setup函数形式

在 Setup 函数会接收两个参数,第一个参数就是组件的 Props传递过来的参数。和标准的组件一致,Setup 函数的 Props 是响应式的,并且会在传入新的 Props 时同步更新。
第二个参数是 content中有四个参数:
1、attrs: 该参数接受的是父组件传值到子组件的时候,子组件中未在props中配置的值;
2、emit: 该参数作为子父组件传值使用,传递给父组件需要使用到该字段,;

<!-- 父组件 -->
<template>
  <div class="demo">
    我是script setup的父组件
    <hr />
    <Child :list="list" :msg="msg" @change="handleChange"></Child>
  </div>
</template>

<script>
import { ref, defineProps, reactive } from "vue";
import Child from "./Child.vue";
export default {
  components: { Child },
  setup() {
    let list = ref("张三");
    let msg = ref("123");
    const handleChange = (e) => {
      console.log(e);
    };
    return {
      list,
      msg,
      handleChange,
    };
  },
};
</script>
<!-- 子组件 -->

<template>
  <div>
    <h3>我是子级组件</h3>
    <h4>我接收到父组件的 数据 => {{ list }}</h4>
    <hr />
    <button @click="handleClick">子组件传值到父组件</button>
  </div>
</template>

<script>
import { onMounted } from 'vue';
export default {
  props: {
    // 注意:父组件传到子组件的字段必须要在这里定义
    list: String,
  },
  setup(props, context) {
    /**
    props:
		content中有四个参数:
			1、attrs: 该参数接受的是父组件传值到子组件的时候,子组件中未在props中配置的值;
			2、emit: 该参数作为子父组件传值使用,传递给父组件需要使用到该字段;
  */
    console.log( context.attrs, "12");  //打印attrs 查看其他未定义接收的变量
    const handleClick = () => {
      context.emit("change", "来自子组件的消息");   //子传父方法:emit(‘自定义事件名称’,'传递的参数')
    };
    return {
      props,
      handleClick,
    };
  },
};
</script>
setup语法糖

在这里插入图片描述

<!-- 父组件 -->
<template>
  <div class="demo">
    我是script setup的父组件
    <hr>
    <!-- 子组件的内容在父组件显示 -->
    <Child :list="list"></Child> 
  </div>
</template>

<script setup>
import {ref, onMounted, reactive } from 'vue';
import Child from "./Child.vue";
const list = reactive([{name: 'zl'}])  
</script>
<!-- 子组件 -->
<template>
  <div class="demo">
    <div>我是script setup子组件 :{{ props.list[0].name }}</div>
  </div>
</template>

<script setup>
import { onMounted } from "vue";
// 子组件中, 接收 Props 参数 Vue 提供了一个 新的 API 函数 defineProps()方法,就和我们在 Vue2 的子组件中 定义 Props 待接收参数配置一样。
// 必须要使用defineProps进行配置传入的属性,否则无法获取到传入的值.
const props = defineProps({
  list: {
    type: Array,
    required: true, //  是否必传
    default: "备用数据", //默认数据
  },
});
onMounted(() => {
  console.log(props.list, "123");
});
</script>

defineEmits

  <!-- 父组件 -->
<template>
  <div class="demo">
    我是script setup的父组件
    <hr>
 <Child @exposeData="getData"></Child> 
  </div>
</template>

<script setup>
import {ref, onMounted, reactive } from 'vue';
import Child from "./Child.vue";
const getData = (val)=>{
    console.log("接收子组件的值",val)
}
</script>
<template>
  <div class="demo">
    <h3>子组件</h3>
    <button @click="toValue">触发子组件数据</button>
  </div>
</template>

<script setup>
// setup 语法糖写法
//用defineEmits()来定义子组件要抛出的方法,语法defineEmits(['要抛出的方法','参数'])
const emit = defineEmits(['exposeData'])
const toValue = ()=>{
    emit('exposeData','张三 -- 18')
}
</script>

defineExpose

setup函数形式
<!-- 父组件 -->
<template>
  <!-- 方法一 -->
  <Child ref="childRef" />
  <!-- 方法二 -->
  <Child ref="childRefTwo" />
</template>

<script>
import { ref, onMounted, getCurrentInstance } from "vue";
import Child from "./Child.vue";
export default {
  components: { Child },
  setup() {
    const childRef = ref(null); // 当前变量必须要与子组件上绑定的ref对应起来,(不需要使用defineExpose将方法暴露出来,可以直接使用ref获取)
    const instance = getCurrentInstance(); //获取当前组件实例
    onMounted(() => {
      // 方法一
      childRef.value.open(); // 调用子组件中的open方法
      // 方法二
      instance.proxy.$refs.childRefTwo.open(); // 调用子组件中的open方法
    });
    return { childRef, instance };
  },
};
</script>

<!-- 子组件 -->
<!-- 子组件 -->
 <template>
  <div>
    <div @click="open">子组件传值到父组件</div>
  </div>
</template>

<script>
import { onMounted } from "vue";
export default {
  props: {
    list: String,
  },
  setup() {
    const open = () => {
      console.log("open点击了");
    };
    return { open };
    // setup函数定义的函数,不需要使用defineExpose将方法暴露出来,可以直接使用ref获取
  },
};
</script>

setup语法糖形式
<!-- 父组件 -->
<template>
  <Child ref="childRef" />
  <Child ref="childRefTwo" />
</template>

<script setup>
import { ref, onMounted, getCurrentInstance } from "vue";
import Child from "./Child.vue";
const childRef = ref(null);
const instance = getCurrentInstance();   //获取当前组件实例

// 扩展讲解
// 获取当前组件的上下文,下面两种方式都能获取到组件的上下文。
// 方式一,这种方式只能在开发环境下使用,生产环境下的ctx将访问不到
// const { ctx }  = getCurrentInstance();

// //  方式二,此方法在开发环境以及生产环境下都能放到组件上下文对象(推荐)
// const { proxy }  = getCurrentInstance();
// // ctx 中包含了组件中由ref和reactive创建的响应式数据对象,以及以下对象及方法;
// console.log(instance,'555');

onMounted(() => {
  // 方法一
  childRef.value.open(); // 调用子组件中的open方法
  // 方法二
  instance.proxy.$refs.childRefTwo.open(); // 调用子组件中的open方法
});
</script>
<!-- 子组件 -->
<template>
  <div>
    <div @click="open">子组件传值到父组件</div>
  </div>
</template>

<script setup>
import { onMounted,defineExpose } from "vue";
 
    const open = () => {
      console.log("open点击了");
    };
    defineExpose({ open }); // 必须要注册进来
    // vue3中,语法糖中定义的方法,默认是不会暴露给ref进行调用的,必须要注册到defineExpose里面,
    // ref才能正常访问,如果没有注册到defineExpose中,通过ref调用子组中的方法,会报错

</script>
  • defineProps 和 defineEmits 都是只在 < script setup>
    中才能使用的编译器宏。他们不需要导入且会随着< script setup> 处理过程一同被编译掉。
  • defineProps 接收与 props 选项相同的值,defineEmits也接收 emits选项相同的值。
  • defineProps 和 defineEmits 在选项传入后,会提供恰当的类型推断。
  • 传入到 defineProps 和 defineEmits 的选项会从 setup 中提升到模块的范围。因此,传入的选项不能引用在
    setup 范围中声明的局部变量。这样做会引起编译错误。但是,它可以引用导入的绑定,因为它们也在模块范围内

获取 attrs、slots 和useAttrs、useSlots 方法

在 < script setup> 使用 slots 和 attrs 的情况应该是很罕见的,因为可以在模板中通过 s l o t s 和 slots 和 slotsattrs 来访问它们。在你的确需要使用它们的罕见场景中,可以分别用 useSlots 和 useAttrs 两个辅助函数:

<script setup>
import { useSlots, useAttrs } from 'vue'

const slots = useSlots()
const attrs = useAttrs()
</script>

useSlots 和 useAttrs 是真实的运行时函数,它会返回与 setupContext.slots 和 setupContext.attrs 等价的值,同样也能在普通的组合式 API 中使用

与普通的 < script > 一起使用

< script setup >可以和普通的< script >一起使用。普通的< script >在有这些需要的情况下或许会被使用到:

  • 无法在< script setup>声明的选项,例如inheritAttrs【vue官网对于inheritAttrs的属性解释:默认情况下父作用域的不被认作 props 的 attribute 绑定 (attribute bindings) 将会“回退”且作为普通的 HTML attribute应用在子组件的根元素上。如果你不希望组件的根元素继承特性,你可以在组件的选项中设置 inheritAttrs:false】或通过插件启用的自定义的选项;
  • 声明命名导出,< script setup>定义的组件默认以组件文件的名称作为组件名;
  • 运行副作用或者创建只需要执行一次的对象。

在同一组件中将 < script setup> 与 < script > 结合使用的支持仅限于上述情况。具体来说:
不要为已经可以用 < script setup> 定义的选项使用单独的 < script > 部分,如 props 和 emits。
在 < script setup> 中创建的变量不会作为属性添加到组件实例中,这使得它们无法从选项式 API 中访问。我们强烈反对以这种方式混合 API。
如果你发现自己处于以上任一不被支持的场景中,那么你应该考虑切换到一个显式的 setup() 函数,而不是使用 < script setup>。

v-bind() CSS变量注入

 <template>
  <span>Jerry</span>
</template>
 <script setup>
import { ref, reactive } from "vue";
// prop接收样式
const props = defineProps({
  border: {
    type: String,
    default: "5px solid yellow",
  },
});

// 常量声明样式
const background = "red";

// 响应式数据声明样式
const color = ref("blue");
const style = reactive({
  opacity: "0.5",
});
</script>

<style scoped>
span {
  display: block;
  width: 50px;
  height: 50px;
  background: v-bind(background);

  /* 使用响应式数据声明的样式 */
  color: v-bind(color);
  opacity: v-bind("style.opacity");
  /* 使用prop接收的样式 */
  border: v-bind("props.border");
}
</style>

style的新特性之global

如果需要声明全局样式,可以使用一下方式

<template>
 <div>
  <p>1223465</p>
 </div>
</template>
<script setup>
import { defineProps } from "vue";


</script>
<style scoped >
:global(p){ 
  /* //声明了一个全局类型p */
  color: red;
}
</style>

对await异步的支持

setup函数的形式

使用suspense 包裹你的组件 需要在setup函数前面async声明。

<template>
 <suspense>
        <router-view></router-view>
</suspense>
</template>
 
export default {
  async setup() {
    // 在 `setup` 内部使用 `await` 需要非常小心
    // 因为大多数组合式 API 函数只会在
    // 第一个 `await` 之前工作
    const data = await loadData()
 
    // 它隐性地包裹在一个 Promise 内
    // 因为函数是 `async` 的
    return {
      // ...
    }
  }
setup语法糖形式

不必再配合 async 就可以直接使用 await 了,这种情况下,组件的 setup 会自动变成 async setup

<script setup>
  const post = await fetch('/api').then(() => {})
</script>

没有 Src 导入

由于模块执行语义的差异,< script setup > 中的代码依赖单文件组件的上下文。当将其移动到外部的 .js 或者 .ts 文件中的时候,对于开发者和工具来说都会感到混乱。因而

<template src="./template.html"></template>
<script src="./script.js"></script>
<style src="./style.css"></template>
//禁止这样混用
<script setup></script>

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

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

相关文章

行业认可,知道创宇入选安全牛第十版全景图30个细分领域

近日&#xff0c;国内网络安全领域专业媒体安全牛正式发布了第十版《中国网络安全行业全景图》&#xff08;以下简称“全景图”&#xff09;&#xff0c;知道创宇凭借过硬的技术实力及成熟的市场应用获得行业认可&#xff0c;入围10项一级安全分类共计30项二级细分领域&#xf…

ASEMI代理ADI亚德诺AD8130ARZ-REEL7车规级芯片

编辑-Z AD8130ARZ-REEL7芯片参数&#xff1a; 型号&#xff1a;AD8130ARZ-REEL7 −3dB带宽&#xff1a;250MHz 0.1 dB平坦度的带宽&#xff1a;25MHz 斜率&#xff1a;930V/μs 建立时间&#xff1a;20ns 上升和下降时间&#xff1a;1.5ns 输出超速恢复&#xff1a;30n…

访学案例分享|经济学老师获英国两高校邀请函

D老师所在国内高校鼓励教职员工通过各种渠道公派或者自筹经费出国访学进修。在考虑了学校要求及个人条件后&#xff0c;其决定用自费方式赴英国访学。我们分别获得了英国利兹贝克特大学和邓迪大学的邀请函&#xff0c;最终D老师顺利过签&#xff0c;如期出国。 D老师背景&#…

网络编程【UDP数据报套接字编程】

目录 1.网络编程基础 1.1 为什么需要网络编程&#xff1f; 1.2 什么是网络编程 1.3 网络编程中的基本概念 2.Socket套接字 2.1 分类 3.UDP数据报套接字编程 3.1 DatagramSocket API 3.2 DatagramPacket API 3.3 基于 UDP socket 写一个简单的回显客户端服务器程序&am…

设计模式 -- 桥梁模式

前言 月是一轮明镜,晶莹剔透,代表着一张白纸(啥也不懂) 央是一片海洋,海乃百川,代表着一块海绵(吸纳万物) 泽是一柄利剑,千锤百炼,代表着千百锤炼(输入输出) 月央泽,学习的一种过程,从白纸->吸收各种知识->不断输入输出变成自己的内容 希望大家一起坚持这个过程,也同…

自适应安全、主权云、超级自动化顶级政府技术趋势

根据分析公司 Gartner 的数据&#xff0c;自适应安全、主权云和超级自动化是 2023 年十大政府技术趋势之一。 确定了 2023 年的 10 大政府技术趋势&#xff0c;这些趋势可以指导公共部门领导者在为后数字化政府做准备和不懈地关注任务目标时加速转型。 当前的全球动荡和技术中…

9-2分布迭代次数的15个梯度

( A, B )---1*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有1个节点&#xff0c;AB训练各由11张二值化的图片组成&#xff0c;让A中有3个0&#xff0c;B中全是0&#xff0c;排列组合A的所有可能&#xff0c;统计迭代次数的顺序。 A-B 迭代次数 标准差 势能 标准差势能 11 …

30天学会《Streamlit》(6)

30学会《Streamlit》是一项编码挑战&#xff0c;旨在帮助您开始构建Streamlit应用程序。特别是&#xff0c;您将能够&#xff1a; 为构建Streamlit应用程序设置编码环境 构建您的第一个Streamlit应用程序 了解用于Streamlit应用程序的所有很棒的输入/输出小部件 第6天 - 使…

【案例教程】基于RWEQ模型的土壤风蚀模数估算及其变化归因分析实践技术

土壤风蚀是一个全球性的环境问题。中国是世界上受土壤风蚀危害最严重的国家之一&#xff0c;土壤风蚀是中国干旱、半干旱及部分湿润地区土地荒漠化的首要过程。中国风蚀荒漠化面积达160.74104km2&#xff0c;占国土总面积的16.7%&#xff0c;严重影响这些地区的资源开发和社会经…

什么是5G?关于5G你需要知道的知识

问&#xff1a;什么是5G&#xff1f; Answer&#xff1a; 5G是第五代移动网络。它是继1G、2G、3G、4G网络之后的新的全球无线标准。5G 支持一种新型网络&#xff0c;旨在将几乎所有人和所有事物连接在一起&#xff0c;包括机器、物体和设备。 5G 无线技术旨在为更多用户…

【MAVEN_Configuration】maven下载配置IDEA配置以及阿里云镜像配置

&#xff03;    下载 MAVNEDownLoad &#xff03; 配置 解压 指定文件夹 系统变量配置 在这里插入图片描述 check cmd 配置settings 本地仓库 阿里云镜像配置 mvn全局jdk <!-- java版本 --> <profile> <id>jdk-1.8</id> <activat…

JavaSE/内部类

前言 在学习Java的过程当中&#xff0c;不难发现Java全是由类与对象构成的&#xff0c;所以在一个类当中定义和使用一个另外一个类是我们学习过程中必须要学会使用的&#xff0c;而这种类&#xff0c;被称之为内部类。 一、实例内部类 class A{void a(){}class B{void a(){}} …

计算机图形学(5):OpenGL光照

参考 介绍 现实世界中的光照是极其复杂&#xff0c;难以计算的&#xff0c;因此OpenGL的光照使用的是简化的模型&#xff0c;其中一个模型被称为冯氏光照模型(Phong Lighting Model)。 冯氏光照模型的主要结构由三个分量组成&#xff1a; 环境(Ambient)光照 漫反射(Diffuse)…

【Docker学习三部曲】—— 入门篇

Docker 入门 Docker 概述 1️⃣ 什么是 docker &#xff1f; Docker 是一种运行应用程序的平台&#xff0c;它可以使应用程序在容器中不受环境差异的影响进行部署和运行。Docker 的流行度越来越高&#xff0c;是因为它可以帮助在不同的开发者和开发团队之间实现代码的共享和…

Linux centos搭建web服务器

文章目录 前言1. 本地搭建web站点2. 测试局域网访问3. 公开本地web网站3.1 安装cpolar内网穿透3.2 创建http隧道&#xff0c;指向本地80端口3.3 配置后台服务 4. 配置固定二级子域名5. 测试使用固定二级子域名访问本地web站点 前言 在web项目中,部署的web站点需要被外部访问,则…

动力节点Vue3课程笔记——四、Vue与AJAX

四、Vue与AJAX 4.1 回顾发送AJAX异步请求的方式 发送AJAX异步请求的常见方式包括&#xff1a; 原生方式&#xff0c;使用浏览器内置的JS对象XMLHttpRequest const xhr new XMLHttpRequest()xhr.onreadystatechange function(){}xhr.open()xhr.send() 原生方式&#xff0…

30天学会《Streamlit》(7)

30学会《Streamlit》是一项编码挑战&#xff0c;旨在帮助您开始构建Streamlit应用程序。特别是&#xff0c;您将能够&#xff1a; 为构建Streamlit应用程序设置编码环境 构建您的第一个Streamlit应用程序 了解用于Streamlit应用程序的所有很棒的输入/输出小部件 第7天 - st…

聚焦商会 | 活动彰显一个商会的战斗力与影响力

4月13日&#xff0c;北京厦航嘉年华酒店。 一个普通的日子&#xff0c;对北京茶业企业商会来说却是值得纪念的一天&#xff0c;可以浓笔重墨书写的一天。 一天成功举办了三场活动&#xff0c;得到社会各界的支持与肯定。 北京茶业企业商会是如何做到的&#xff1f;经过与商会领…

python批量下载怀俄明大学探空数据Wyoming soundings并处理

下载怀俄明大学的探空数据&#xff0c;之前用的是气象家园写的maltab脚本&#xff0c;但总是链接不上&#xff0c;而且有的站点需要用新网址&#xff0c;有的有需要用老网址&#xff0c;很麻烦&#xff0c;痛定思痛用决定终于用python了&#xff0c;主要有两种方式&#xff0c;…

nightingale-0-介绍单机二进制部署

(一) 夜莺介绍 Nightingale | 夜莺监控&#xff0c;一款先进的开源云原生监控分析系统&#xff0c;采用 All-In-One 的设计&#xff0c;集数据采集、可视化、监控告警、数据分析于一体&#xff0c;与云原生生态紧密集成&#xff0c;提供开箱即用的企业级监控分析和告警能力。于…