0

0

Vue3怎么使用setup语法糖拒绝写return

王林

王林

发布时间:2023-05-12 18:34:23

|

1090人浏览过

|

来源于亿速云

转载

    vue3.2 setup语法糖

    <script setup></script> 是在单文件组件 (sfc) 中使用组合式 api 的编译时语法糖

    解决Vue3.0中setup需要繁琐将声明的变量、函数以及 import 引入的内容通过return向外暴露,才能在<template></template>使用的问题

    1.<script setup>在<template/>使用</script>

    <script setup></script>中无需return 声明的变量、函数以及import引入的内容,即可在<template></template>使用

    <script setup></script>语法糖

    <script setup>
    //import引入的内容
    import { getToday } from './utils'  
    // 变量
    const msg = 'Hello!'
    // 函数
    function log() {
      console.log(msg)
    }
    </script>
    
    //在template中直接使用声明的变量、函数以及import引入的内容
    <template>
      <div @click="log">{{ msg }}</div>
       <p>{{getToday()}}</p><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p>
    </template>

    标准组件<script></script> 需要写setup函数并繁琐retrun

    <script>
    //import引入的内容
    import { getToday } from './utils'  
    export default{
     setup(){
        // 变量
        const msg = 'Hello!'
        // 函数
        function log() {
          console.log(msg)
        }
        //想在tempate里面使用需要在setup内return暴露出来
        return{
           msg,
           log,
           getToday 
        }
     }
    }
    </script>
    
    <template>
      <div @click="log">{{ msg }}</div>
       <p>{{getToday()}}</p><p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p>
    </template>

    小结:<script setup></script>语法糖里面的代码会被编译成组件 setup() 函数的内容,不需要通过return暴露 声明的变量、函数以及import引入的内容,即可在<template></template>使用,并且不需要写export default{}

    <script setup></script>语法糖里面的代码会被编译成组件 setup() 函数的内容。这意味着与普通的 <script></script> 只在组件被首次引入的时候执行一次不同,<script setup></script> 中的代码会在每次组件实例被创建的时候执行

      <script>
      console.log('script');//多次实例组件,只触发一次
      export default {
          setup() {
              console.log('setupFn');//每次实例化组件都触发和script-setup标签一样
          }
      }
      </script>

    (script-setup标签最终都会编译成setup() 函数的内容,每次实例化组件,就是实例化一次setup函数。script标签里面的setup函数也是一样每次实例化组件,就是实例化一次setup函数,但是script标签setup是需要写在export default{}内的,外的只是首次引入的时候执行一次)

    2、<script setup>引入组件将自动注册</script>

    不需要在引入组件后,通过 components:{}注册组件,可直接使用

    <script setup>
    import MyComponent from './MyComponent.vue'
    //components:{MyComponent}  不需要注册直接使用
    </script>
    
    <template>
      <MyComponent />
    </template>

    3、组件通信:

    <script setup></script>中必须使用 defineProps defineEmits API 来替代 props 和 emits

    defineProps 和 defineEmits具备完整的类型推断并且在 中是直接可用的(浏览了一下掘金,发现大部分文章demo还是通过import引入这2个api,这点官方文档写得很清楚)
    defineProps 代替props

    接收父组件传递的数据(父组件向子组件传参)

    父组件:

    <template>
      <div>父组件</div>
      <Child :title="msg" />
    </template>
    
    <script setup>
    import {ref} from 'vue'
    import Child from './child.vue'
    const msg = ref('父的值')  //自动返回,在template直接解套使用
    </script>

    子组件:

    <template></template> 中可以直接使用父组件传递的props (可省略props.)

    <script-setup></script-setup> 需要通过props.xx获取父组件传递过来的props

    <template>
      <div>子组件</div>
      <div>父组件传递的值:{{title}}</div>
    </template>
    
    <script setup>
    //import {defineProps} from 'vue'   不需要引入
    
    //语法糖必须使用defineProps替代props
    const  props = defineProps({
      title: {
        type: String
      }
    });
    //script-setup 需要通过props.xx获取父组件传递过来的props
    console.log(props.title) //父的值
    </script>
    defineEmit 代替emit

    子组件向父组件传递数据(子组件向外暴露数据)

    子组件代码:

    <template>
      <div>子组件</div>
      <button @click="toEmits">子组件向外暴露数据</button>
    </template>
    
    <script setup>
    import {ref} from 'vue'
    const name = ref('我是子组件')
    //1、暴露内部数据
    const  emits = defineEmits(['childFn']);
    
    const  toEmits = () => {
      //2、触发父组件中暴露的childFn方法并携带数据
      emits('childFn',name)
    }
    </script>

    父组件代码:

    <template>
      <div>父组件</div>
      <Child  @childFn='childFn' />
      <p>接收子组件传递的数据{{childData}} </p><div class="aritcle_card flexRow">
                                                            <div class="artcardd flexRow">
                                                                    <a class="aritcle_card_img" href="/ai/875" title="百度GBI"><img
                                                                                    src="https://img.php.cn/upload/ai_manual/001/503/042/68b6d54b42fe6818.png" alt="百度GBI"  onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
                                                                    <div class="aritcle_card_info flexColumn">
                                                                            <a href="/ai/875" title="百度GBI">百度GBI</a>
                                                                            <p>百度GBI-你的大模型商业分析助手</p>
                                                                    </div>
                                                                    <a href="/ai/875" title="百度GBI" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
                                                            </div>
                                                    </div>
    </template>
    
    <script setup>
    import {ref} from 'vue'
    import Child from './child.vue'
        
    const childData = ref(null)    
    const childFn=(e)=>{
        consloe.log('子组件触发了父组件childFn,并传递了参数e')
        childData=e.value
    }    
           
    </script>

    4.<script setup>需主动向父组件暴露子组件属性 :defineExpose</script>

    使用 <script setup></script> 的组件,父组件是无法通过ref 或者 $parent 获取到子组件的ref等响应数据,需要通过defineExpose 主动暴露

    子组件代码:

    <script setup>
    import { ref } from 'vue'
    
    const a = 1
    const b = ref(2)
    //主动暴露组件属性
    defineExpose({
      a,
      b
    })
    </script>

    父组件代码:

    <template>
      <div>父组件</div>
      <Child  ref='childRef' />
      <button @click='getChildData'>通过ref获取子组件的属性 </button>
    </template>
    
    <script setup>
    import {ref} from 'vue'
    import Child from './child.vue'
    const childRef= ref()  //注册响应数据  
    const getChildData =()=>{
      //子组件接收暴露出来得值
      console.log(childRef.value.a) //1
      console.log(childRef.value.b) //2  响应式数据
    }    
    </script>

    5.语法糖其他功能

    useSlotsuseAttrs少用,由于大部分人是SFC模式开发,在<template></template>通过<slot></slot>标签就可以渲染插槽)

    如果需要在script-setup中使用 slotsattrs 需要用useSlotsuseAttrs替代

    需要引入:import { useSlots ,useAttrs } form 'vue'

    <template></template>中通过 $slots$attrs 来访问更方便(attrs用来获取父组件中非props的传递到子组件的参数/方法,attrs 用来获取父组件中非props的传递到子组件的参数/方法,attrs用来获取父组件中非props的传递到子组件的参数/方法,slots可以获取父组件中插槽传递的虚拟dom对象,在SFC模式应该用处不大,在JSX /TSX使用比较多)

    父组件:

    <template>
      <Child msg="非porps传值子组件用attrs接收" >
        <!-- 匿名插槽 -->
        <span >默认插槽</span>
        <!-- 具名插槽 -->
        <template #title>
          <h2>具名插槽</h2>
        </template>
        <!-- 作用域插槽 -->
        <template #footer="{ scope }">
          <footer>作用域插槽——姓名:{{ scope.name }},年龄{{ scope.age }}</footer>
        </template>
      </Child>
    </template>
    
    <script setup>
    // 引入子组件
    import Child from './child.vue'
    </script>

    子组件:

    <template>
      <!-- 匿名插槽 -->
      <slot />
      <!-- 具名插槽 -->
      <slot name="title" />
      <!-- 作用域插槽 -->
      <slot name="footer" :scope="state" />
      <!-- $attrs 用来获取父组件中非props的传递到子组件的参数 -->
      <p>{{ attrs.msg == $attrs.msg }}</p>
      <!--true  没想到有啥作用... -->
      <p>{{ slots == $slots }}</p>
    </template>
    
      
    <script setup>
    import { useSlots, useAttrs, reactive, toRef } from 'vue'
    const state = reactive({
      name: '张三',
      age: '18'
    })
    
    const slots = useSlots()
    console.log(slots.default()); //获取到默认插槽的虚拟dom对象
    console.log(slots.title());   //获取到具名title插槽的虚拟dom对象
    // console.log(slots.footer()); //报错  不知道为啥有插槽作用域的无法获取
    //useAttrs() 用来获取父组件传递的过来的属性数据的(也就是非 props 的属性值)。
    const attrs = useAttrs()
    </script>

    useSlots或许在JSX/TSX下更实用

    想使用JSX语法在vite需要下载相关jsx的plugins才能识别jsx

    useSlots 可以获取父组件传递过来插槽的虚拟dom对象,可以用来渲染插槽内容

    <script lang='jsx'>
    import { defineComponent, useSlots } from "vue";
    export default defineComponent({
      setup() {
        // 获取插槽数据
        const slots = useSlots();
        // 渲染组件
        return () => (
          <div>
            {slots.default?slots.default():''}
            {slots.title?slots.title():''}
          </div>
        );
      },
    });
    </script>

    大部分人是SFC模式开发,在<template></template>通过<slot></slot>标签就可以渲染插槽,这种JSX 的写法应该是很少人会使用的

    6.在setup访问路由

    • 访问路由实例组件信息:route和router

    setup 里不能访问 this,不能再直接访问 this.$routerthis.$route。(getCurrentInstance可以替代this但不推荐)

    推荐:使用useRoute 函数和useRouter函数替代this.$routethis.$router

    <script setup>
    import { useRouter, useRoute } from 'vue-router'
        const route = useRoute()
        const router = useRouter()
        
        function pushWithQuery(query) {
          router.push({
            name: 'search',
            query: {
              ...route.query,
            },
          })
        }
      <script/>
    • 导航守卫

    仍然可以使用路由实例组件的导航守卫

    import router from './router'
    router.beforeEach((to,from,next)=>{
    
    })

    也可以使用组合式api的导航守卫onBeforeRouteLeave, onBeforeRouteUpdate

    <script setup>
    import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
    
        // 与 beforeRouteLeave 相同,无法访问 `this`
        onBeforeRouteLeave((to, from) => {
          const answer = window.confirm(
            'Do you really want to leave? you have unsaved changes!'
          )
          // 取消导航并停留在同一页面上
          if (!answer) return false
        })
    
        const userData = ref()
    
        // 与 beforeRouteUpdate 相同,无法访问 `this`
        onBeforeRouteUpdate(async (to, from) => {
          //仅当 id 更改时才获取用户,例如仅 query 或 hash 值已更改
          if (to.params.id !== from.params.id) {
            userData.value = await fetchUser(to.params.id)
          }
        })
     <script/>

    组合式 API 守卫也可以用在任何由 `` 渲染的组件中,它们不必像组件内守卫那样直接用在路由组件上。

    热门AI工具

    更多
    DeepSeek
    DeepSeek

    幻方量化公司旗下的开源大模型平台

    豆包大模型
    豆包大模型

    字节跳动自主研发的一系列大型语言模型

    通义千问
    通义千问

    阿里巴巴推出的全能AI助手

    腾讯元宝
    腾讯元宝

    腾讯混元平台推出的AI助手

    文心一言
    文心一言

    文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

    讯飞写作
    讯飞写作

    基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

    即梦AI
    即梦AI

    一站式AI创作平台,免费AI图片和视频生成。

    ChatGPT
    ChatGPT

    最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

    相关专题

    更多
    JavaScript浏览器渲染机制与前端性能优化实践
    JavaScript浏览器渲染机制与前端性能优化实践

    本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

    23

    2026.03.06

    Rust内存安全机制与所有权模型深度实践
    Rust内存安全机制与所有权模型深度实践

    本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

    68

    2026.03.05

    PHP高性能API设计与Laravel服务架构实践
    PHP高性能API设计与Laravel服务架构实践

    本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

    162

    2026.03.04

    AI安装教程大全
    AI安装教程大全

    2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

    84

    2026.03.04

    Swift iOS架构设计与MVVM模式实战
    Swift iOS架构设计与MVVM模式实战

    本专题聚焦 Swift 在 iOS 应用架构设计中的实践,系统讲解 MVVM 模式的核心思想、数据绑定机制、模块拆分策略以及组件化开发方法。内容涵盖网络层封装、状态管理、依赖注入与性能优化技巧。通过完整项目案例,帮助开发者构建结构清晰、可维护性强的 iOS 应用架构体系。

    113

    2026.03.03

    C++高性能网络编程与Reactor模型实践
    C++高性能网络编程与Reactor模型实践

    本专题围绕 C++ 在高性能网络服务开发中的应用展开,深入讲解 Socket 编程、多路复用机制、Reactor 模型设计原理以及线程池协作策略。内容涵盖 epoll 实现机制、内存管理优化、连接管理策略与高并发场景下的性能调优方法。通过构建高并发网络服务器实战案例,帮助开发者掌握 C++ 在底层系统与网络通信领域的核心技术。

    29

    2026.03.03

    Golang 测试体系与代码质量保障:工程级可靠性建设
    Golang 测试体系与代码质量保障:工程级可靠性建设

    Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

    79

    2026.02.28

    Golang 工程化架构设计:可维护与可演进系统构建
    Golang 工程化架构设计:可维护与可演进系统构建

    Go语言工程化架构设计专注于构建高可维护性、可演进的企业级系统。本专题深入探讨Go项目的目录结构设计、模块划分、依赖管理等核心架构原则,涵盖微服务架构、领域驱动设计(DDD)在Go中的实践应用。通过实战案例解析接口抽象、错误处理、配置管理、日志监控等关键工程化技术,帮助开发者掌握构建稳定、可扩展Go应用的最佳实践方法。

    62

    2026.02.28

    Golang 性能分析与运行时机制:构建高性能程序
    Golang 性能分析与运行时机制:构建高性能程序

    Go语言以其高效的并发模型和优异的性能表现广泛应用于高并发、高性能场景。其运行时机制包括 Goroutine 调度、内存管理、垃圾回收等方面,深入理解这些机制有助于编写更高效稳定的程序。本专题将系统讲解 Golang 的性能分析工具使用、常见性能瓶颈定位及优化策略,并结合实际案例剖析 Go 程序的运行时行为,帮助开发者掌握构建高性能应用的关键技能。

    51

    2026.02.28

    热门下载

    更多
    网站特效
    /
    网站源码
    /
    网站素材
    /
    前端模板

    精品课程

    更多
    相关推荐
    /
    热门推荐
    /
    最新课程
    Vue3.x 工具篇--十天技能课堂
    Vue3.x 工具篇--十天技能课堂

    共26课时 | 1.6万人学习

    Vue3.x 核心篇--十天技能课堂
    Vue3.x 核心篇--十天技能课堂

    共30课时 | 1.6万人学习

    Vue3.x新特性篇--十天基础课堂
    Vue3.x新特性篇--十天基础课堂

    共20课时 | 1.2万人学习

    关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
    php中文网:公益在线php培训,帮助PHP学习者快速成长!
    关注服务号 技术交流群
    PHP中文网订阅号
    每天精选资源文章推送

    Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号