搜尋
首頁web前端Vue.jsVue3怎麼使用setup語法糖拒絕寫return

Vue3怎麼使用setup語法糖拒絕寫return

May 12, 2023 pm 06:34 PM
vue3returnsetup

    Vue3.2 setup语法糖

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

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

    1.

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

    <script setup></script>语法糖

    <script setup>
    //import引入的内容
    import { getToday } from &#39;./utils&#39;  
    // 变量
    const msg = &#39;Hello!&#39;
    // 函数
    function log() {
      console.log(msg)
    }
    </script>
    
    //在template中直接使用声明的变量、函数以及import引入的内容
    <template>
      <div @click="log">{{ msg }}</div>
       <p>{{getToday()}}</p>
    </template>

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

    <script>
    //import引入的内容
    import { getToday } from &#39;./utils&#39;  
    export default{
     setup(){
        // 变量
        const msg = &#39;Hello!&#39;
        // 函数
        function log() {
          console.log(msg)
        }
        //想在tempate里面使用需要在setup内return暴露出来
        return{
           msg,
           log,
           getToday 
        }
     }
    }
    </script>
    
    <template>
      <div @click="log">{{ msg }}</div>
       <p>{{getToday()}}</p>
    </template>

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

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

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

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

    2、

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

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

    3、组件通信:

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

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

    defineProps 代替props

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

    父组件:

    <template>
      <div>父组件</div>
      <Child :title="msg" />
    </template>
    
    <script setup>
    import {ref} from &#39;vue&#39;
    import Child from &#39;./child.vue&#39;
    const msg = ref(&#39;父的值&#39;)  //自动返回,在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 &#39;vue&#39;   不需要引入
    
    //语法糖必须使用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 &#39;vue&#39;
    const name = ref(&#39;我是子组件&#39;)
    //1、暴露内部数据
    const  emits = defineEmits([&#39;childFn&#39;]);
    
    const  toEmits = () => {
      //2、触发父组件中暴露的childFn方法并携带数据
      emits(&#39;childFn&#39;,name)
    }
    </script>

    父组件代码:

    <template>
      <div>父组件</div>
      <Child  @childFn=&#39;childFn&#39; />
      <p>接收子组件传递的数据{{childData}} </p>
    </template>
    
    <script setup>
    import {ref} from &#39;vue&#39;
    import Child from &#39;./child.vue&#39;
        
    const childData = ref(null)    
    const childFn=(e)=>{
        consloe.log(&#39;子组件触发了父组件childFn,并传递了参数e&#39;)
        childData=e.value
    }    
           
    </script>

    4.

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

    子组件代码:

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

    父组件代码:

    <template>
      <div>父组件</div>
      <Child  ref=&#39;childRef&#39; />
      <button @click=&#39;getChildData&#39;>通过ref获取子组件的属性 </button>
    </template>
    
    <script setup>
    import {ref} from &#39;vue&#39;
    import Child from &#39;./child.vue&#39;
    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 id="具名插槽">具名插槽</h2>
        </template>
        <!-- 作用域插槽 -->
        <template #footer="{ scope }">
          <footer>作用域插槽——姓名:{{ scope.name }},年龄{{ scope.age }}</footer>
        </template>
      </Child>
    </template>
    
    <script setup>
    // 引入子组件
    import Child from &#39;./child.vue&#39;
    </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 &#39;vue&#39;
    const state = reactive({
      name: &#39;张三&#39;,
      age: &#39;18&#39;
    })
    
    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=&#39;jsx&#39;>
    import { defineComponent, useSlots } from "vue";
    export default defineComponent({
      setup() {
        // 获取插槽数据
        const slots = useSlots();
        // 渲染组件
        return () => (
          <div>
            {slots.default?slots.default():&#39;&#39;}
            {slots.title?slots.title():&#39;&#39;}
          </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 &#39;vue-router&#39;
        const route = useRoute()
        const router = useRouter()
        
        function pushWithQuery(query) {
          router.push({
            name: &#39;search&#39;,
            query: {
              ...route.query,
            },
          })
        }
      <script/>
    • 导航守卫

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

    import router from &#39;./router&#39;
    router.beforeEach((to,from,next)=>{
    
    })

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

    <script setup>
    import { onBeforeRouteLeave, onBeforeRouteUpdate } from &#39;vue-router&#39;
    
        // 与 beforeRouteLeave 相同,无法访问 `this`
        onBeforeRouteLeave((to, from) => {
          const answer = window.confirm(
            &#39;Do you really want to leave? you have unsaved changes!&#39;
          )
          // 取消导航并停留在同一页面上
          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 守卫也可以用在任何由 `` 渲染的组件中,它们不必像组件内守卫那样直接用在路由组件上。

    以上是Vue3怎麼使用setup語法糖拒絕寫return的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    陳述
    本文轉載於:亿速云。如有侵權,請聯絡admin@php.cn刪除
    Netflix的前端:React(或VUE)的示例和應用Netflix的前端:React(或VUE)的示例和應用Apr 16, 2025 am 12:08 AM

    Netflix使用React作為其前端框架。 1)React的組件化開發模式和強大生態系統是Netflix選擇它的主要原因。 2)通過組件化,Netflix將復雜界面拆分成可管理的小塊,如視頻播放器、推薦列表和用戶評論。 3)React的虛擬DOM和組件生命週期優化了渲染效率和用戶交互管理。

    前端景觀:Netflix如何處理其選擇前端景觀:Netflix如何處理其選擇Apr 15, 2025 am 12:13 AM

    Netflix在前端技術上的選擇主要集中在性能優化、可擴展性和用戶體驗三個方面。 1.性能優化:Netflix選擇React作為主要框架,並開發了SpeedCurve和Boomerang等工具來監控和優化用戶體驗。 2.可擴展性:他們採用微前端架構,將應用拆分為獨立模塊,提高開發效率和系統擴展性。 3.用戶體驗:Netflix使用Material-UI組件庫,通過A/B測試和用戶反饋不斷優化界面,確保一致性和美觀性。

    React與Vue:Netflix使用哪個框架?React與Vue:Netflix使用哪個框架?Apr 14, 2025 am 12:19 AM

    NetflixusesAcustomFrameworkcalled“ Gibbon” BuiltonReact,notReactorVuedIrectly.1)TeamSperience:selectBasedonFamiliarity.2)ProjectComplexity:vueforsimplerprojects:reactforforforproproject,reactforforforcompleplexones.3)cocatizationneedneeds:reactoffipicatizationneedneedneedneedneedneeds:reactoffersizationneedneedneedneedneeds:reactoffersizatization needefersmoreflexibleise.4)

    框架的選擇:是什麼推動了Netflix的決定?框架的選擇:是什麼推動了Netflix的決定?Apr 13, 2025 am 12:05 AM

    Netflix在框架選擇上主要考慮性能、可擴展性、開發效率、生態系統、技術債務和維護成本。 1.性能與可擴展性:選擇Java和SpringBoot以高效處理海量數據和高並發請求。 2.開發效率與生態系統:使用React提升前端開發效率,利用其豐富的生態系統。 3.技術債務與維護成本:選擇Node.js構建微服務,降低維護成本和技術債務。

    反應,vue和Netflix前端的未來反應,vue和Netflix前端的未來Apr 12, 2025 am 12:12 AM

    Netflix主要使用React作為前端框架,輔以Vue用於特定功能。 1)React的組件化和虛擬DOM提升了Netflix應用的性能和開發效率。 2)Vue在Netflix的內部工具和小型項目中應用,其靈活性和易用性是關鍵。

    前端中的vue.js:現實世界的應用程序和示例前端中的vue.js:現實世界的應用程序和示例Apr 11, 2025 am 12:12 AM

    Vue.js是一種漸進式JavaScript框架,適用於構建複雜的用戶界面。 1)其核心概念包括響應式數據、組件化和虛擬DOM。 2)實際應用中,可以通過構建Todo應用和集成VueRouter來展示其功能。 3)調試時,建議使用VueDevtools和console.log。 4)性能優化可通過v-if/v-show、列表渲染優化和異步加載組件等實現。

    vue.js和React:了解關鍵差異vue.js和React:了解關鍵差異Apr 10, 2025 am 09:26 AM

    Vue.js適合小型到中型項目,而React更適用於大型、複雜應用。 1.Vue.js的響應式系統通過依賴追踪自動更新DOM,易於管理數據變化。 2.React採用單向數據流,數據從父組件流向子組件,提供明確的數據流向和易於調試的結構。

    vue.js vs.反應:特定於項目的考慮因素vue.js vs.反應:特定於項目的考慮因素Apr 09, 2025 am 12:01 AM

    Vue.js適合中小型項目和快速迭代,React適用於大型複雜應用。 1)Vue.js易於上手,適用於團隊經驗不足或項目規模較小的情況。 2)React的生態系統更豐富,適合有高性能需求和復雜功能需求的項目。

    See all articles

    熱AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智慧驅動的應用程序,用於創建逼真的裸體照片

    AI Clothes Remover

    AI Clothes Remover

    用於從照片中去除衣服的線上人工智慧工具。

    Undress AI Tool

    Undress AI Tool

    免費脫衣圖片

    Clothoff.io

    Clothoff.io

    AI脫衣器

    AI Hentai Generator

    AI Hentai Generator

    免費產生 AI 無盡。

    熱門文章

    R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
    4 週前By尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.最佳圖形設置
    4 週前By尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.如果您聽不到任何人,如何修復音頻
    4 週前By尊渡假赌尊渡假赌尊渡假赌
    R.E.P.O.聊天命令以及如何使用它們
    4 週前By尊渡假赌尊渡假赌尊渡假赌

    熱工具

    mPDF

    mPDF

    mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

    Atom編輯器mac版下載

    Atom編輯器mac版下載

    最受歡迎的的開源編輯器

    EditPlus 中文破解版

    EditPlus 中文破解版

    體積小,語法高亮,不支援程式碼提示功能

    PhpStorm Mac 版本

    PhpStorm Mac 版本

    最新(2018.2.1 )專業的PHP整合開發工具

    WebStorm Mac版

    WebStorm Mac版

    好用的JavaScript開發工具