【vue3学习系列】组合式api中,替代setup()函数的<script setup>特性写法

前言

在使用composition api的时候,setup()函数的写法写多了会感觉有些繁琐,比如每次都需要return出去,不同类型变量要分ref和reactive调用等。这里就记录一下尤大大在vue3正式版发布不到两个月后推出的script setup特性。

一些细节点这里没有记录,推荐看官方文档:响应式基础


响应式数据

ref

网上说:从3.2之后,ref的性能提升很大,且以后基本数据类型或者是复杂数据类型都用ref去做处理。

我去看了源码,复杂数据类型还是借助了reactive去做响应式处理,不过都用ref确实方便一些。

<script setup>
import { ref } from 'vue'
// 定义
const obj = ref({
	name: 'nick'
})
const str = ref('a')
// 然后就可以在模板或者js中使用了,但是在js中使用的时候要xxx.value去取值
<script>

<template>
  <div>
    {{ str }}
  </div>
</template>
  • 对于无需响应式处理的变量,也就是页面不需要更新的,就直接声明,在模板中直接使用就行。
  • 为什么<script setup>标签的变量能直接用在模板上,官方说可以理解成他们在同一个作用域。
  • 为什么取值一定要用属性value的方式去取,因为值类型的响应式处理也需要依赖对象的proxy处理,所以把值类型放在了一个对象上的value属性上。
  • ref后的变量是一个原始对象的 Proxy。

前面说调用属性value的方式取值比较麻烦,已经出了一个新的实验性质的写法(最近看好像又被毙掉了):

<script setup>
let count = $ref(0)

function increment() {
  // 无需 .value
  count++
}
</script>

<template>
  <button @click="increment">{{ count }}</button>
</template>

还有个小技巧说下

<script setup>
import { ref } from 'vue'
// 定义
const arr = ref([])

let aMap = new Map()

function addItemNum(item) {
	let itemCurrent = aMap.get(item.id)
	if (itemCurrent) {
		itemCurrent.num++ 
	} else {
		let itemNew = {
			...item,
			num: 1
		}
		arr.value.push(itemNew)
		aMap.set(item.id, itemNew)
	}
}
<script>

当itemCurrent.num++触发时,arr对应的子项数据是不会改变的,因为后续itemNew存在aMap变量里的并不是响应式数据,所以要这样处理下:

function addItemNum(item) {
	let itemCurrent = aMap.get(item.id)
	if (itemCurrent) {
		itemCurrent.num++ 
	} else {
		let itemNew = ref({
			...item,
			num: 1
		})
		arr.value.push(itemNew.value)
		aMap.set(item.id, itemNew.value)
	}
}

computed

<script setup>
import { computed } from 'vue'
// 定义
const a = computed(() => {
	return xxx
})
// 使用 js中使用,a.value ,模板中直接{a}即可
<script>

同样可以写getter和setter:

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

const a = ref('1')
const b = ref('2')

const aplusb = computed({
  // getter 这个就是日常的computed功能
  get() {
    return a.value + ' ' + b.value
  },
  // setter 这个则是可以通过修改计算属性,改变所依赖响应式变量的值,例如aplusb.value = '3,4'
  set(newValue) {
    [a.value, b.value] = newValue.split(',') // 解构赋值语法
  }
})
</script>

官方说明:

  • 不推荐使用setter去改写
  • 不要在 getter 中做异步请求或者更改 DOM

watch

<script setup>
import { watch } from 'vue'
watch(
  xxx,
  () => {
    // 处理逻辑
  },
  {
    // 监听配置
    immediate: true
  }
)
<script>

数据传递

props

<script setup>
import { defineProps } from 'vue'
// 定义
const props = defineProps({
  a: {
    type: String,
    required: true,
    default: ''
  }
})
// 使用 props.a
<script>

vuex

<script setup>
import { useStore } from 'vuex'
// 定义
const store = useStore();
// 使用例子actions
store.dispatch("xxx", xxx).then()
<script>

v-model

// 自定义组件中
<script setup>
import { defineProps, defineEmits } from 'vue'
defineProps({
  modelValue: {
    type: Boolean,
    required: true
  }
})

const emits = defineEmits(['update:modelValue']) // 格式update:+ 双向绑定变量名称

// 修改数据:emits('update:modelValue', false)
<script>

// 外部直接v-model='xxxx',xxxx名称不需要与modelValue同名,这个是固定的

emit

<template>
	<div v-model="modelValue"></div>
</template>
<script setup>
import { defineProps, defineEmits } from "vue";

defineProps({
  modelValue: {
    type: Boolean,
    required: true,
  },
});
const emits = defineEmits(["update:modelValue", ...]);
const fn = () => {
  emits("update:modelValue", false);
};
</script>

父级组件:

<xxx v-model="a"></xxx>

方法定义

<script setup>
import { ref } from 'vue'
let str = ref('1')

function getStr() {
  console.log(str.value)
}

</script>

<template>
  <button @click="getStr">
    {{ str }}
  </button>
</template>

组件导入

<script setup>
import foot from './foot.vue'
<script>

然后在模板中就可以直接使用了。


获取dom

<div ref="dom"></div>

<script setup>
const dom = ref(null); // 以响应式的形式获取,默认给个null
// 使用 dom.value
<script>

路由相关

<script setup>
import { useRouter, useRoute } from 'vue-router'

const router = useRouter()
const route = useRoute()
</script>

nextTick

和setup()写法一样,用在dom“积累的最后一次更新完成后调用"

import { nextTick } from 'vue'

function increment() {
  state.count++
  nextTick(() => {
    // 访问更新后的 DOM,拿到的是最新的dom
  })
}

未来不间断补充…

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值