vue3 script setup 语法

502 阅读2分钟

setup 语法糖

详解: 1.目前setup sugar已经进行了定稿,vue3 + setup sugar + TS的写法看起来很香,写本文时 Vue 版本是 "^3.2.6" 2.新的 setup 选项是在组件创建之前, props 被解析之后执行,是组合式 API 的入口。

WARNING\ 在 setup 中你应该避免使用 this,因为它不会找到组件实例。setup 的调用发生在 data property、computed property 或 methods 被解析之前,所以它们无法>在 setup 中被获取。

setup 选项是一个接收 props 和 context 的函数,我们将在之后进行讨论。此外,我们将 setup 返回的所有内容都暴露给组件的其余部分 (计算属性、方法、生命周期钩子等等) 以及组件的模板。

它是 Vue3 的一个新语法糖,在 setup 函数中。所有 ES 模块导出都被认为是暴露给上下文的值,并包含在 setup() 返回对象中。相对于之前的写法,使用后,语法也变得更简单。

基础模板

<template>
  <div>
  </div>
</template>


<script setup>
  
</script>

<style lang="scss" scoped>

</style>

1. 属性和方法无需返回,直接使用

以前使用响应式数据是

<template>
	{{msg}}
</template>

<script>
import { ref } from 'vue'
export default {
	setup () {
		const msg = ref('你好 vue3');
		return {
			msg
		}
	}
}
</script>

现在使用

<template>
	{{msg}}
</template>

<script setup>
import { ref } from 'vue'
const msg = ref('你好 vue3');
</script>

reactivecomputed, 也一样可以使用:

<template>
	<div>{{msg}}</div>
	<div>{{objs.a1}}</div>
	<div>{{sum}}</div>
</template>

<script setup>
import { ref, reactive, computed } from 'vue'

const msg = ref('你好 vue3');

const objs = reactive({
	a1: 1,
	b1: 2
})

const sum = computed(() => {
	return obj.a1 + 3;
});
</script>

2. 组件自动注册

父组件

<template>
  <div class="login">
    <HelloWorld :msg="msg" @changMsg="changMsg"></HelloWorld>
  </div>
</template>

<script setup>
import HelloWorld from '../components/HelloWorld.vue'
import { ref } from 'vue'
const msg = ref('我是父组件的msg')
const changMsg = (val) =>{
  msg.value = val
}
</script>

<style lang="scss" scoped>

</style>

子组件

 <template>
      <h1>{{ msg }}</h1>
      <el-button @click="handleChange">改变父组件的msg</el-button>
</template>

<script setup>
import { defineProps, defineEmits } from 'vue'

defineProps({
  msg: String
})
const emit = defineEmits(['changMsg'])
const handleChange = () =>{
  emit('changMsg','子附件改变父组件的值')
}

</script>

<style lang="scss" scoped>
</style>

main.js的引入

import { createApp } from 'vue'
import App from './App.vue'
import router from './router';
import store from './store'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const app = createApp(App)
app.use(ElementPlus).use(router).use(store).mount('#app')

vuex的操作

./store/index.js

import { createApp } from 'vue'
import { createStore } from 'vuex'

// Create a new store instance.
const store = createStore({
  state() {
    return {
      userInfo: { name: 'tanwei', age: 18 }
    }
  },
  mutations: {
    increment(state) {
      state.count++
    },
    changeUserInfo(state, val) {
      console.log(state, 111);
      state.userInfo = val
    }
  },
  actions: {
    changeUserInfoAction({ commit }, val) {
      commit('changeUserInfo', val)
    }
  }
})

export default store;

在main.js里引用

import { createApp } from 'vue'
import App from './App.vue'
import router from './router';
import store from './store'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

const app = createApp(App)
app.use(ElementPlus).use(router).use(store).mount('#app')

在组件内使用

<template>
  <div class="login">
    {{userInfo.name}}
    <el-button @click="changeUserInfo">修改vuex用户信息</el-button>
  </div>
</template>

<script setup>
import { ref, reactive, toRefs } from 'vue'
import { useStore } from "vuex";
const store = useStore();

const { userInfo } = toRefs(store.state);

const changeUserInfo = () => {
  store.dispatch('changeUserInfoAction',{name:'hahaha',age:19})
}

</script>

<style lang="scss" scoped>

</style>

对外暴露属性(defineExpose)

<script setup> 的组件默认不会对外部暴露任何内部声明的属性。
如果有部分属性要暴露出去,可以使用 defineExpose

子组件 Child.vue

<template>
	{{msg}}
</template>

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

let msg = ref("组件");
let num = ref(1234);

// defineExpose无需导入,直接使用
defineExpose({
	msg,
	num
});
</script>

父组件 Home.vue

<template>
	<Child ref="child" />
</template>

<script setup>
import { ref, onMounted } from 'vue'
import Child from '@/components/Child.vue'

let child = ref(null);

onMounted(() => {
	console.log(child.value.msg); // Child Components
	console.log(child.value.num); // 123
})
</script>