个人个案网站 类型,wordpress群组,网站开发的技术内容,华侨大学英文网站建设文章目录 script setup基本语法顶层的绑定会被暴露给模板响应式监听与计算使用组件父子组件传参#xff08;变化较大#xff09;父 - 子 defineProps()子 - 父 defineEmits()子组件暴露给父组件内部属性 defineExpose() defineOptions() 【很少用】 script setup
变化较大父 - 子 defineProps()子 - 父 defineEmits()子组件暴露给父组件内部属性 defineExpose() defineOptions() 【很少用】 script setup
script setup 是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖。当同时使用 SFC 与组合式 API 时该语法是默认推荐。相比于普通的 script 语法它具有更多优势
更少的样板内容更简洁的代码。能够使用纯 TypeScript 声明 props 和自定义事件。更好的运行时性能 (其模板会被编译成同一作用域内的渲染函数避免了渲染上下文代理对象)。更好的 IDE 类型推导性能 (减少了语言服务器从代码中抽取类型的工作)。
基本语法
要启用该语法需要在script 代码块上添加 setup attribute
script setup
console.log(hello script setup)
/script里面的代码会被编译成组件 setup() 函数的内容。这意味着与普通的 script只在组件被首次引入的时候执行一次不同script setup 中的代码会在每次组件实例被创建的时候执行。
顶层的绑定会被暴露给模板
当使用 script setup 的时候任何在 script setup 声明的顶层的绑定 (包括变量函数声明以及 import 导入的内容) 都能在模板中直接使用
script setup
// 变量
const msg Hello!// 函数
function log() {console.log(msg)
}
/scripttemplatebutton clicklog{{ msg }}/button
/templateimport 导入的内容也会以同样的方式暴露。这意味着我们可以在模板表达式中直接使用导入的 helper 函数而不需要通过 methods 选项来暴露它
script setup
import { capitalize } from ./helpers
/scripttemplatediv{{ capitalize(hello) }}/div
/template响应式
比较常用的ref和reactive在这个语法糖中用法不变
ref定义一个基本类型的响应数据 操作数据 xxx.value读取数据: 不需要.value直接div{{xxx}}/div reactive定义一个复杂类型的响应数据 操作数据与读取数据均不需要.value
这里我们还可以使用ts中的泛型来进行约束
let person reactivePerson({list:[]
})interface RefT {value: T
}还有toRef、toRefs等函数用法没有什么大变化
监听与计算
computed与watch的使用方法在该语法糖中也没有什么变化但是我们需要弄清楚一个问题在vue3中watch、computed、watchEffect使用场景有什么不同
在vue3中watch、computed、watchEffect都是用来监听响应式数据的变化并执行相应的回调函数。但是它们的使用场景和区别有以下几点 computed是用来计算一个派生值它接受一个getter函数并返回一个只读的ref对象。computed的回调函数只有在依赖的响应式数据变化时才会重新计算否则会缓存上一次的结果。computed适合用在需要根据一些数据计算出另一个数据的场景例如根据姓名拼接全名或者根据购物车的商品计算总价。 watch是用来观察一个或多个响应式数据的变化并执行相应的回调函数。watch接受一个响应式数据源可以是ref、reactive、getter函数或者数组和一个回调函数返回一个用于停止观察的函数。watch的回调函数会在响应式数据源变化时触发同时会传入新值和旧值作为参数。watch可以指定一些选项例如immediate是否立即执行回调函数、deep是否深度观察对象的嵌套属性等。watch适合用在需要根据数据的变化执行一些副作用的场景例如发送请求、操作DOM、改变其他状态等。 watchEffect是用来自动收集响应式数据的依赖并执行相应的回调函数。watchEffect接受一个回调函数返回一个用于停止观察的函数。watchEffect的回调函数会在首次执行时收集依赖并在任何依赖变化时重新执行。watchEffect不会传入新值和旧值作为参数也不能指定immediate或deep选项。watchEffect适合用在不需要知道具体哪个数据变化只需要在数据变化时执行一些逻辑的场景例如根据数据的变化更新标题、打印日志、触发自定义事件等。
使用组件
script setup 范围里的值也能被直接作为自定义组件的标签名使用也就是说我们import组件之后不需要注册可以直接使用
script setup
import MyComponent from ./MyComponent.vue
/scripttemplateMyComponent /
/template这里 MyComponent 应当被理解为像是在引用一个变量。这就有点类似于JSX了。
父子组件传参变化较大
父 - 子 defineProps()
父组件直接使用v-bind在子组件的标签中传递数据
Menu :datadata title我是标题/Menutemplatediv classmenu菜单区域 {{ title }}div{{ data }}/div/div
/templatescript setup langts
defineProps{title:string,data:number[]
}()
/script设置默认值
type Props {title?: string,data?: number[]
}
withDefaults(definePropsProps(), {title: 张三,data: () [1, 2, 3]
})为什么这里的data的值要写成函数的返回值的形式
这里的data要通过函数的形式返回的原因是为了避免多个组件实例共享同一个数组对象导致数据混乱和污染。
如果我们不使用函数的形式返回data的默认值而是直接写成data: [1, 2, 3]那么所有使用这个组件的地方都会使用同一个数组对象如果其中一个组件实例修改了数组的内容那么其他的组件实例也会受到影响这会导致数据不一致和难以预测的行为。
因此为了保证数据的独立性和安全性我们需要使用函数的形式返回data的默认值这样每个组件实例都会得到一个新的数组对象而不会相互干扰。
子 - 父 defineEmits()
具体过程
在子组件中使用defineEmits函数来定义一个分发器emitter它接受一个字符串数组或者一个对象作为参数用来指定要分发的事件名称和类型。在子组件中使用emit方法来触发指定的事件并传递相应的数据。emit方法的第一个参数是事件名称后面的参数是要传递的数据。在父组件中使用或者v-on指令来监听子组件发射的事件并定义一个回调函数来处理接收到的数据。回调函数的参数是子组件传递的数据。
父组件
templatediv classlayoutMenu on-clickgetList/Menu/div
/templatescript setup langts
import { reactive } from vue;const getList (list: number[]) {console.log(list,父组件接受子组件);
}
/script我们在子组件中去触发这个事件
templatediv classmenubutton clickclickTap派发给父组件/button/div
/templatescript setup langts
import { reactive } from vueconst emit defineEmits([on-click])//如果用了ts可以这样两种方式
// const emit defineEmits{
// (e: on-click, name: string): void
// }()
const clickTap () {emit(on-click, 123)
}/script在vue3.3中对这个语法进行了加强
const emit defineEmits{on-click:[name:string]
}()子组件暴露给父组件内部属性 defineExpose()
首先在子组件中定义要暴露的属性
const list reactivenumber[]([4, 5, 6])defineExpose({list
})然后我们在父组件中通过ref来读 Menu refrefMenu/Menu
//这样获取是有代码提示的
script setup langts
import MenuCom from ../xxxxxxx.vue
//注意这儿的typeof里面放的是组件名字(MenuCom)不是ref的名字 ref的名字对应开头的变量名(refMenu)
const refMenu refInstanceTypetypeof MenuCom()
console.log(refMenu.value.list )
/scriptdefineOptions() 【很少用】
vue3中的defineOptions()是一个用于在 实际使用中一般来定义name 使用defineOptions()的一个例子是
script setup langts
import { defineOptions } from vue// 使用defineOptions()来定义Options API的选项
defineOptions({name: MyComponent, // 组件的名称data() { // 组件的数据return {count: 0}},methods: { // 组件的方法increment() {this.count}},computed: { // 组件的计算属性doubleCount() {return this.count * 2}},watch: { // 组件的侦听器count(newValue, oldValue) {console.log(count changed from ${oldValue} to ${newValue})}},mounted() { // 组件的生命周期钩子console.log(component mounted)}
})
/scripttemplatedivpcount: {{ count }}/ppdoubleCount: {{ doubleCount }}/pbutton clickincrement1/button/div
/template这样我们就可以在script setup中使用Options API的选项而不需要使用export default的方式。