vue3 中 <script setup> 到底干了什么

🍳 这就是一个语法

<script setup> 这是vue的一个语法,大家都这样用。💨 写在里面的变量/函数,都相当于包在setup函数中一样。下面是一个简单的对比

  • setup函数
js 复制代码
<script>
export default {
	setup() {
		const count = ref(0)
		const msg = ref('setupScript')
		const increase = () => {
			count.value++
			console.log(count.value)
		}
		return {
			count,
			msg,
			increase
		}
	}
}
</script>
  • setup 语法糖(当然如果需要子组件的属性/变量,这里需要defineExpose 做导出)
js 复制代码
<script setup>
const count = ref(0)
const msg = ref('setupScript')
const increase = () => {
	count.value++
}
</script>

🍑 通过Inspect 来观察 script setup和 setup 函数的区别(vite-plugin-inspect:查看编译的结果)

💻 setup 函数

  • template 模版 经过编译,成了render 函数
  • setup 函数 经过编译,什么也没有改变

💻 script setup

  • template 模版 经过编译,成了render 函数
  • script setup 的形式,编译成了 setup函数,去执行,最终通过 expose 导出,所以 <script setup> 就是一个语法糖,本质还是 setup 函数,只不过里面自动做了一个expose

📄 expose 是什么(摘自vue 官方文档)

用于声明当组件实例被父组件通过模板引用访问时暴露的公共属性。

默认情况下 setup 函数,会将组件实例向父组件暴露所有的实例属性,这可能不是我们希望看到的,而expose 就是限定子组件只能向外暴露哪些属性/方法

🌰 组件具体实例观察

js 复制代码
<template>
	<SetupFun ref="setupFunRef" />
	<SetupScript ref="setupScriptRef" />
</template>
<script setup>
import SetupFun from './components/setupFun.vue'
import SetupScript from './components/setupScript.vue'

const setupFunRef = ref(null)
const setupScriptRef = ref(null)

onMounted(() => {
	console.log('%c [ setup 函数 ]-15', 'font-size:16px; background:pink; color:#bf2c9f;', setupFunRef.value)

	console.log('%c [setup 语法糖  ]-23', 'font-size:16px; background:pink; color:#bf2c9f;', setupScriptRef.value)
	console.log('%c [setup 语法糖  ]-23', 'font-size:16px; background:pink; color:#bf2c9f;', setupScriptRef.value.$el)
})
</script>

通过 setup 函数,会将组件的属性/实例, 相关隐藏属性,全部暴露出去

通过 script setup什么都没有暴露出去

🦄 setup 函数不香吗,为什么还要 script setup ?

setup 函数,会将 组件实例属性/API 全部暴露给父组件。好是好,使用起来变得超级方便,但是这也存在一个潜在的巨大问题,父子组件完全没有边界,$root,$parent,$el 随便用,组件很可能拥有一些应保持私有的内部状态或方法,以避免紧耦合, 也会导致单项数据流被打破,时间久了,容易造成数据混乱,变成一堆石山。这里为了方便没有举实例属性,举了一个方法来说明如何破坏单项数据流

比如:

js 复制代码
onMounted(() => {
         // 在父组件调用子组件的increase,
        //而子组件的increase 里写了修改 count的逻辑
        console.log('%c [ setup 函数 ]-15',  setupFunRef.value.increase()) 
        
	console.log('%c [ setup 函数 ]-16',  setupFunRef.value.count) // count由 0 -》1 在
 }

🤔 可以指定特定暴露属性/方法吗?->expose

js 复制代码
   <script>
export default {
	setup(props, { expose }) {
		const count = ref(0)
		const msg = ref('setupScript')
		const increase = () => {
			count.value++
			console.log(count.value)
		}
                // 通过 expost 指定暴露当法,同时不会向外暴露子组件实例上的所有实例属性
		expose({
			count,
			msg,
			increase
		})
	}
}
</script> 

📝 script setup 如何暴露 方法/属性

vue提供来一个全局的宏来做属性/方法的暴露。在编译后,也是使用 expose 做属性/方法暴露

js 复制代码
<script setup>
const msg = ref('setupScript')
const count = ref(0)
const increase = () => {
	count.value++
}
defineExpose({ msg, count, increase })
</script>

但是如果不使用defineExpose做暴露 ,就不会暴露出任何属性方法, 就像使用 setup 不用return ,就不会暴露出任何属性方法,就像西方不能没有耶路撒冷 !!!

📝 全局的宏 defineExpose 为什么不需要导入,就能直接使用?

通过插件,可以看到,script setup 经过编译 会变成setup 函数,而 defineExpose 经过编译 会变成expose。所以 defineExpose 并不参与运行, 只参与编译做一个对应关系,所以不需要引入

📝 编译时? 运行时 傻傻分不清 ?

我们写的template, script setup 不会直接运行,而是经过一层编译。将template 模版编译成render 函数,将 script setup 编译成 setup 函数,将 defineExpose 编译成 expose,或者其他的宏函数defineModel编译成 propsdefineEmits编译成 emits 等等

这些宏函数只在编译时起作用,和相关函数做一个对应关系并不会在运行时执行这些宏函数,所以不需要引入这些宏函数

至此,我们已经明白了script setup 到底干了什么

🎊 总结

  • script setup 就是一个语法糖,经过 编译,最终还是 setup 函数。
  • 在 script setup 如果想获取子组件的属性/方法,需要通过 defineExpose 暴露
  • defineExpose 最终也会编译成 expose, defineExpose不会参与运行时,所以不用做导入。
相关推荐
ggdpzhk2 小时前
VUE:基于MVVN的前端js框架
前端·javascript·vue.js
活宝小娜6 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点6 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow6 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
刚刚好ā7 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
会发光的猪。10 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
天下代码客10 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js
周全全10 小时前
Spring Boot + Vue 基于 RSA 的用户身份认证加密机制实现
java·vue.js·spring boot·安全·php
ZwaterZ11 小时前
vue el-table表格点击某行触发事件&&操作栏点击和row-click冲突问题
前端·vue.js·elementui·c#·vue
码农六六11 小时前
vue3封装Element Plus table表格组件
javascript·vue.js·elementui