【Vue3】setup(setup函数与script setup)示例,用法以及原理(持续更新)

vue

目录

  • setup函数
    • setup函数原理说明
    • setup函数特性
    • setup函数注意点
    • setup函数中的watch与computed
    • setup拆分实例
  • script setup
    • setup 包含的生命周期
    • script setup使用方法
    • script setup的作用
      • 自动注册子组件
      • 属性和方法无需返回
      • 支持props、emit和context
        • defineProps, defineEmits
        • defineExpose
        • useSlots 和 useAttrs
        • 实例

Vue3 中的setup 一种是setup函数,一种是script setup

setup函数

setup函数原理说明

由于setup 是在beforeCreate 和 create 生命周期阶段,组件还没有创建,即还没有进入 data 方法 阶段。

setup 返回的结果集 作为 (传统写法)data 和 method 的值,确切点说是绑定到 组件对象的属性。

setup函数特性

1、setup函数是处于 生命周期函数 beforeCreate 和 Created 两个钩子函数之间的函数 也就说在 setup函数中是无法 使用 data 和 methods 中的数据和方法的

2、setup函数是 Composition API(组合API)的入口

3、在setup函数中定义的变量和方法最后都是需要 return 出去的 不然无法再模板中使用

setup 函数将接收两个参数,props&context

Props :props接收父组件传入的值,为Proxy对象,且为响应式,所以不能使用 ES6 解构,它会消除 prop 的响应性

context:官方解释=>context 是一个普通的 JavaScript 对象,它暴露组件的三个 property:

export default {

setup(props, context) {

// Attribute (非响应式对象)

console.log(context.attrs)

// 插槽 (非响应式对象)

console.log(context.slots)

// 触发事件 (方法)

console.log(context.emit)

}

}

setup函数注意点

1、由于在执行 setup函数的时候,还没有执行 Created 生命周期方法,所以在 setup 函数中,无法使用 data 和 methods 的变量和方法

2、由于我们不能在 setup函数中使用 data 和 methods,所以 Vue 为了避免我们错误的使用,直接将 setup函数中的this修改成了 undefined

3、setup函数只能是同步的不能是异步的

setup函数中的watch与computed

看下面的setup拆分实例 grandson.vue的例子

setup拆分实例

main.js

import { createApp } from \'vue\'

import App from \'./App.vue\'

createApp(App).mount(\'#app\')

App.vue

<script setup>

import Parent from \'./components/parent.vue\'

</script>

<template>

<Parent></Parent>

</template>

<style>

#app {

font-family: Avenir, Helvetica, Arial, sans-serif;

-webkit-font-smoothing: antialiased;

-moz-osx-font-smoothing: grayscale;

text-align: center;

color: #2c3e50;

margin-top: 60px;

}

</style>

parent.vue

<template>

<div @click="handleClick">我是父组件 {{info}}

<son></son>

</div>

</template>

<script>

import { defineComponent } from \'vue\'

import son from \'./son.vue\'

import useInfo from \'./info.js\'

export default defineComponent({

setup() {

let {info, handleClick} = useInfo()

return {

info,

handleClick

}

},

components: {

son

}

})

</script>

info.js

import {provide, reactive, ref } from \'vue\'

let useInfo = () => {

let info = ref(123);

let datas = reactive({

width: 100,

height: 50,

bg: \'pink\'

});

const updateInfo = (val) => {

info.value = val

}

const handleClick = () => {

console.log(\'handleClick了\');

info.value++;

console.log(\'info.value:\' + info.value);

}

provide(\'info\', info);

provide(\'datas\', datas)

provide("updateInfo", updateInfo);

return {

info,

handleClick

}

}

export default useInfo

son.vue

<template>

<div>我是子组件 {{info}}

<grand-son ref="compa"></grand-son>

</div>

</template>

<script>

import { defineComponent, inject } from \'vue\'

import grandSon from \'./grandSon.vue\';

export default defineComponent({

setup() {

const info = inject(\'info\');

return {

info

}

},

components: {

grandSon

}

})

</script>

grandson.vue

<template>

<div>我是孙子组件 <button @click="updateInfo(\'456\')">点击更新info</button>{{info}} computed: {{computedInfo}}<br />宽度{{datas.width}}, 高度:{{datas.height}}, 背景: {{datas.bg}}</div>

</template>

<script>

import { defineComponent , inject, watch, computed} from \'vue\'

export default defineComponent({

setup() {

const info = inject(\'info\');

const updateInfo = inject(\'updateInfo\');

const datas = inject(\'datas\');

watch(info, (val) => {

console.log(\'变了\');

console.log(val);

});

const computedInfo = computed(() => {

console.log(\'computed 改变了info\')

return info.value + 10

})

return {

info,

datas,

updateInfo,

computedInfo

}

},

})

</script>

script setup

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

<script setup>

// 变量

const msg = \'Hello!\'

// 函数

function log() {

console.log(msg)

}

// click 那里有问题

</script>

<template>

<div>

<div @click="log">我是: {{ msg }}</div>

</div>

</template>

setup 包含的生命周期

script setup使用方法

<script setup></script>

script setup的作用

自动注册子组件

Vue2

<template>

<div>

<h2>父组件!</h2>

<Child />

</div>

</template>

<script>

import Child from \'./Child.vue\'

export default {

component: {

Child // 注册子组件后方可在template中使用

}

}

</script>

Vue3:

<template>

<div>

<h2>父组件!</h2>

<Child />

</div>

</template>

<script>

import { defineComponent, ref } from \'vue\';

import Child from \'./Child.vue\'

export default defineComponent({

components: {

Child // 注册子组件后方可在template中使用

},

setup() {

return {

}

}

});

</script>

setup script语法

<template>

<div>

<h2>父组件!-setup script</h2>

<Child />

</div>

</template>

<script setup>

import Child from \'./Child.vue\'

// 省略了子组件注册的过程,import后可直接在template中使用

</script>

属性和方法无需返回

vue3.x语法:

如需在template中使用属性和方法,必须手动返回对应的属性和方法。这种composition API的编写规则,相对繁琐。如下:

<template>

<div>

<h2 @click="addCount">购买数量 {{ count}} 件</h2>

</div>

</template>

<script>

import { defineComponent, ref } from \'vue\';

export default defineComponent({

setup() {

const count = ref(1)

const addCount = () => {

count.value++

}

return {

count,

addCount

}

}

});

</script>

setup script语法

<template>

<div>

<h2 @click="addCount">购买数量 {{ count}} 件</h2>

</div>

</template>

<script setup>

import { ref } from \'vue\';

const count = ref(1)

const addCount = () => {

count.value++

}

</script>

支持props、emit和context

vue3.x语法

前面setup函数中提及,setup函数包含props和context2个参数,通过这两个参数,达到数据通信及事件触发的目的。

setup scrip语法

没有setup()那怎么获取到props和context呢?

setup script语法糖提供了三个新的API来供我们使用:defineProps、defineEmit和useContext。

defineProps用来接收父组件传来的值props;

defineEmit用来声明触发的事件表;

useContext用来获取组件上下文context

defineProps, defineEmits

在 script setup 中必须使用 defineProps 和 defineEmits API 来声明 props 和 emits ,它们具备完整的类型推断并且在 script setup 中是直接可用的。

<script setup>

const props = defineProps({

foo: String

});

const emit = defineEmits([\'change\', \'delete\']);

// setup code

</script>

defineExpose

使用 script setup 的组件是默认关闭的,也即通过模板 ref 或者 $parent 链获取到的组件的公开实例,不会暴露任何在 script setup 中声明的绑定。当父组件通过模板 ref 的方式获取到当前组件的实例。

<script setup>

import { ref } from \'vue\'

const a = 1

const b = ref(2)

defineExpose({

a,

b

})

</script>

useSlots 和 useAttrs

在 script setup 使用 slots 和 attrs 的情况应该是很罕见的,因为可以在模板中通过 $slots 和 $attrs 来访问它们。在你的确需要使用它们的罕见场景中,可以分别用 useSlots 和 useAttrs 两个辅助函数:

<script setup>

import { useSlots, useAttrs } from \'vue\'

const slots = useSlots()

const attrs = useAttrs()

</script>

useSlots 和 useAttrs 是真实的运行时函数,它会返回与 setupContext.slots 和 setupContext.attrs 等价的值,同样也能在普通的组合式 API 中使用。

实例

父组件:

<template>

<div>

<h2>我是父组件!-setup script</h2>

<Child ref="child" msg="hello" @child-click="childCtx" />

</div>

</template>

<script setup>

import { ref, onMounted } from \'vue\'

import Child from \'./child.vue\'

const childCtx = (e) => {

console.log(\'我是emit出来的值:\' + e)

}

let child = ref(null);

onMounted(() => {

console.log(\'我是expose出来的值:\' + child.value.name); // 123

})

</script>

子组件:

<template>

<div>

<span @click="handleClick">我是子组件! -- msg: {{ props.msg }}</span>

</div>

</template>

<script setup>

import { ref, defineProps, defineEmits, defineExpose, useAttrs, useSlots } from \'vue\'

const name = ref(\'expose name value\')

const emit = defineEmits([\'child-click\'])

const props = defineProps({

msg: String

})

const handleClick = () => {

emit(\'child-click\', \'emit click value\')

}

const slots = useSlots();

const attrs = useAttrs();

console.log(slots)

console.log(attrs)

defineExpose({

name

})

</script>

以上是 【Vue3】setup(setup函数与script setup)示例,用法以及原理(持续更新) 的全部内容, 来源链接: utcz.com/z/375971.html

回到顶部