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

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

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

父组件要想通过ref获取子组件的变量或函数,子组件须使用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 setup> 中的顶层绑定都将自动暴露给模板。
<script>
// 普通 <script>, 在模块范围下执行(只执行一次)
runSideEffectOnce()
// 声明额外的选项
export default {
  name: 'ComponentName',    // 组件重命名
  inheritAttrs: false,
  customOptions: {}
}
</script>

在同一组件中将 < script setup> 与 < script > 结合使用的支持仅限于上述情况。具体来说:

不要为已经可以用 < script setup> 定义的选项使用单独的 < script > 部分,如 props 和 emits。

在 < script setup> 中创建的变量不会作为属性添加到组件实例中,这使得它们无法从选项式 API 中访问。我们强烈反对以这种方式混合 API。

如果你发现自己处于以上任一不被支持的场景中,那么你应该考虑切换到一个显式的 setup() 函数,而不是使用 < script setup>。

style的新特性之 v-bind() CSS变量注入

v-bind:属性 = “(在vue中要用的变量名字)”

<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>

实际的值会被编译成哈希化的 CSS 自定义属性,因此 CSS 本身仍然是静态的。自定义属性会通过内联样式的方式应用到组件的根元素上,并且在源值变更的时候响应式地更新

style的新特性之global

如果想让其中一个样式规则应用到全局,比起另外创建一个 < style>,可以使用 :global 伪类来实现

<template>
 <div>
  <p>1223465</p>
 </div>
</template>
<script setup>
import { defineProps } from "vue";
</script>
<style scoped >
:global(p){ 
  /* //声明了一个全局类型p */
  color: red;
}
</style>

深度选择器

处于 scoped 样式中的选择器如果想要做更“深度”的选择,也即:影响到子组件,可以使用 :deep() 这个伪类:

<style scoped>
.a :deep(.b) {
  /*样式内容 */
}
</style>

对await异步的支持

setup函数的形式
在模板中使用需要< Suspense > 内置组件进行包裹。

< Suspense > 是一个内置组件,用来在组件树中协调对异步依赖的处理。它让我们可以在组件树上层等待下层的多个嵌套异步依赖项解析完成,并可以在等待时渲染一个加载状态

<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>
相关文章
|
2月前
|
缓存 JavaScript UED
Vue3中v-model在处理自定义组件双向数据绑定时有哪些注意事项?
在使用`v-model`处理自定义组件双向数据绑定时,要仔细考虑各种因素,确保数据的准确传递和更新,同时提供良好的用户体验和代码可维护性。通过合理的设计和注意事项的遵循,能够更好地发挥`v-model`的优势,实现高效的双向数据绑定效果。
141 64
|
2月前
|
前端开发 JavaScript 测试技术
Vue3中v-model在处理自定义组件双向数据绑定时,如何避免循环引用?
Web 组件化是一种有效的开发方法,可以提高项目的质量、效率和可维护性。在实际项目中,要结合项目的具体情况,合理应用 Web 组件化的理念和技术,实现项目的成功实施和交付。通过不断地探索和实践,将 Web 组件化的优势充分发挥出来,为前端开发领域的发展做出贡献。
39 8
|
2月前
|
JavaScript
在 Vue 3 中,如何使用 v-model 来处理自定义组件的双向数据绑定?
需要注意的是,在实际开发中,根据具体的业务需求和组件设计,可能需要对上述步骤进行适当的调整和优化,以确保双向数据绑定的正确性和稳定性。同时,深入理解 Vue 3 的响应式机制和组件通信原理,将有助于更好地运用 `v-model` 实现自定义组件的双向数据绑定。
|
3天前
|
JavaScript
vue使用iconfont图标
vue使用iconfont图标
35 1
|
14天前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。
|
2月前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱前端的大一学生,专注于JavaScript与Vue,正向全栈进发。博客分享Vue学习心得、命令式与声明式编程对比、列表展示及计数器案例等。关注我,持续更新中!🎉🎉🎉
45 1
vue学习第一章
|
2月前
|
JavaScript 前端开发 索引
vue学习第三章
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中的v-bind指令,包括基本使用、动态绑定class及style等,希望能为你的前端学习之路提供帮助。持续关注,更多精彩内容即将呈现!🎉🎉🎉
32 1
|
2月前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
39 1
vue学习第四章
|
2月前
|
JavaScript 前端开发 算法
vue学习第7章(循环)
欢迎来到瑞雨溪的博客,一名热爱JavaScript和Vue的大一学生。本文介绍了Vue中的v-for指令,包括遍历数组和对象、使用key以及数组的响应式方法等内容,并附有综合练习实例。关注我,将持续更新更多优质文章!🎉🎉🎉
30 1
vue学习第7章(循环)
|
2月前
|
JavaScript 前端开发
vue学习第九章(v-model)
欢迎来到我的博客,我是瑞雨溪,一名热爱JavaScript与Vue的大一学生,自学前端2年半,正向全栈进发。此篇介绍v-model在不同表单元素中的应用及修饰符的使用,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉
33 1
vue学习第九章(v-model)

热门文章

最新文章