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)父组件
<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>
(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>
相关推荐
一、生命周期
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