vue3 setup语法糖

阅读数:131 评论数:0

跳转到新版页面

分类

html/css/js

正文

一、概述

<script setup> 是在单文件组件(SFC)中使用组合式API的编译时语法糖,解决Vue3.0中setup需要频繁将声明的变量、函数以及import引入的内容通过return向外暴露,才能在<template/>使用的问题。
 
使用setup语法糖后,不用写setup函数;组件只需要引入不需要注册;属性和方法也不需要返回,可以直接在template模板中使用。
 
如果你需要指定一个组件的名称,你可以使用 defineComponent 的 name 选项,或者在 <script setup> 中使用 name 特殊的编译宏。
<script setup>
import { defineComponent } from 'vue'

// 使用特殊的编译宏来指定组件的名称
defineComponent({
  name: 'MyComponentName'
})

// 组件的其他逻辑...
</script>

<template>
  <!-- 组件模板 -->
</template>

二、基本使用

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

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

这意味着与普通的 <script> 只在组件被首次引入的时候执行一次不同,<script setup> 中的代码会在每次组件实例被创建的时候执行

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

三、引入组件将自动注册

<script setup>
import MyComponent from './MyComponent.vue'
</script>

<template>
  <MyComponent />
</template>

四、组件通信

下面三者全部写在子组件中

defineProps: 子组件接收父组件中传来的props。

defineEmits:子组件可以调用父组件中的方法。

definExpose:子组件暴漏对象和方法,可以在父组件中拿到。

需要使用defineProps和defineEmits API来代替props和emits

1、props

(1)父组件

<template>
  <div>父组件</div>
  <Child :title="msg" />
</template>

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

(2)子组件

  • <template/> 中可以直接使用父组件传递的props (可省略props.)
  • <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>

2、emit

(1)子组件

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

(2)父组件

<template>
  <div>父组件</div>
  <Child  @childFn='childFn' />
  <p>接收子组件传递的数据{{childData}} </p>
</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>

五、主动暴漏组件属性defineExpose

在 Vue 3 中,defineExpose 是一个特殊的编译时宏,它允许你明确地指定哪些方法、属性或其他响应式状态应该被暴露给父组件,当使用 <script setup> 语法糖时特别有用。这意味着你可以定义一个组件的公共 API,而不需要将所有的内部状态都暴露出去。

使用 <script setup> 时,默认情况下,模板内部可以访问所有顶层的绑定,但父组件不能访问这些绑定。如果你想要让父组件通过 ref 或者 template refs 访问子组件的状态或方法,你需要使用 defineExpose

(1)子组件

<script setup>
import { ref } from 'vue'

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

(2)父组件

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

六、语法糖的其他功能

<template/>中通过 $slots$attrs 来访问更方便(attrs用来获取父组件中非props的传递到子组件的参数/方法,attrs 用来获取父组件中非props的传递到子组件的参数/方法,attrs用来获取父组件中非props的传递到子组件的参数/方法,slots可以获取父组件中插槽传递的虚拟dom对象,在SFC模式应该用处不大,在JSX /TSX使用比较多)
 
(1)父组件
<template>
  <Child msg="非porps传值子组件用attrs接收" >
    <!-- 匿名插槽 -->
    <span >默认插槽</span>
    <!-- 具名插槽 -->
    <template #title>
      <h1>具名插槽</h1>
    </template>
    <!-- 作用域插槽 -->
    <template #footer="{ scope }">
      <footer>作用域插槽——姓名:{{ scope.name }},年龄{{ scope.age }}</footer>
    </template>
  </Child>
</template>

<script setup>
// 引入子组件
import Child from './child.vue'
</script>

(2)子组件

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

 

 




相关推荐

<script> export default { setup() { const func1= () => { console.log("func1");

一、生命周期 1、vue2生命周期 beforeCreate #实例初始化之后,进行数据侦听和事件/侦听器的配置之前同步调用 created #实例创建完成后被立即同步调用 beforeMount #

一、使用pnpm新建项目 可以使用npm 或yarn或pnpm来初始化Vite项目 pnpm create vite xxx(项目名称) #选择vue #选择js cd xxx (进入项目目录) #安

一、概述 在vue2中,data函数里返回的值直接为响应式,但在vue3中我们需要使用一些函数才能达到这个效果。 setup函数中拿不到vue的this。 二、常用函数 <template> <d

缓存页面主要Jul为了防止重复渲染dom,减少加载时间及性能消耗,提高用户体验。 一、旧版的语法 <keep-alive> <router-view v-if="$route.meta.kee

一、在main.js挂载 import { createApp } from 'vue' import App from './App.vue' import router from './route

一、概述 在vue3中没有$refs这个对象,可以使用如下方法 <template> <div><input type="text" ref="txt1" value="hello" /></div>

方式一、全局引入 全局引入element之后事,element已经在app.config.globalProperties添加了全局方法$message,所以可以在组件中直接使用。 方式二、按需引入

一、useRouter传参的方式 1、隐匿传参params import { useRouter } from 'vue-router' export default { setup() {

方案一: 使用app.config.globalProperties. // 初始化相关 import { createApp } from 'vue' import { nextTick } fro