从Vue2到Vue3学习汇总知识点(二):组合式 API和组合式 API 语法糖 (<script setup>)

15 篇文章 0 订阅
14 篇文章 0 订阅

什么是组合式API

官方文档https://v3.cn.vuejs.org/guide/composition-api-introduction.html#%E4%BB%80%E4%B9%88%E6%98%AF%E7%BB%84%E5%90%88%E5%BC%8F-api

痛点:使用 (data、computed、methods、watch) 组件选项来组织逻辑通常都很有效。然而,当我们的组件开始变得更大时,逻辑关注点的列表也会增长。尤其对于那些一开始没有编写这些组件的人来说,这会导致组件难以阅读和理解。

对比

选项式API写法
component.vue

export defalut {
	components: {},
	data() {
		return {}
	},
	computed:{},
	watch:{},
	methods:{},
	mounted() {}
 }
组合式API写法

(setup 选项是一个接收 props 和 context 的函数,我们将在之后进行讨论。)

component.vue

export default {
  components: {  },
  props: {
    user: {}
  },
  setup(props) { // 不应在setup中使用this,因为它不会访问到组件实例。setup调用在data、computed.... 之前。
  	**使用 `toRefs` 创建对 `props` 中的 `user` property 的响应式引用**
  	const { user } = toRefs(props)

    **使用ref声明响应式变量,使用counter.value进行访问,保证响应式不会在某个地方丢失。**
    import { ref, onMounted, watch, computed   } from 'vue'
	const counter = ref(0)
	console.log(counter.value) // 0

	**声明methods**
	const plusCounter = function() {
		counter ++;
	}

	**访问生命周期钩子函数,前缀为on。**
	onMounted() {}

	**使用watch**
	watch(counter, (newValue, oldValue) => {
  		console.log('The new counter value is: ' + counter.value)
	})

	**使用computed,为了访问新创建的计算变量的 value,我们需要像 ref 一样使用 .value property**
	const twiceTheCounter = computed(() => counter.value * 2)
	
	
    return { 
		counter,
		plusCounter,
		twiceTheCounter
	} 
	** 这里返回的任何内容都可以用于组件的其余部分,并且ref在模板中不需要用.value进行访问。**
  }
  // 组件的“其余部分”
}

深入setup

使用 setup 函数时,它将接收两个参数:props、context

props

因为 props 是响应式的,你不能使用 ES6 解构,它会消除 prop 的响应性。如果需要解构 prop,可以在 setup 函数中使用 toRefs 函数来完成此操作:

import { toRefs } from 'vue'
setup(props) {
const { title } = toRefs(props)
console.log(title.value)
}

如果某个prop是可选的,未传入的情况toRefs不会为其创建一个ref,这是需要用到toRef

import { toRef } from 'vue'
setup(props) {
  const title = toRef(props, 'title')
  console.log(title.value)
}
context

传递给 setup 函数的第二个参数是 context。context 是一个普通 JavaScript 对象(所以可以安全的使用解构),暴露了其它可能在 setup 中有用的值:

export default {
  setup(props, context) {
    // Attribute (非响应式对象,等同于 $attrs)
    console.log(context.attrs)

    // 插槽 (非响应式对象,等同于 $slots)
    console.log(context.slots)

    // 触发事件 (方法,等同于 $emit)
    console.log(context.emit)

    // 暴露公共 property (函数)
    console.log(context.expose)
  }
}

attrs 和 slots 是有状态的对象,它们总是会随组件本身的更新而更新。这意味着你应该避免对它们进行解构,并始终以 attrs.x 或 slots.x 的方式引用 property。请注意,与 props 不同,attrs 和 slots 的 property 是非响应式的。如果你打算根据 attrs 或 slots 的更改应用副作用,那么应该在 onBeforeUpdate 生命周期钩子中执行此操作。

访问组件的 property

执行 setup 时,你只能访问以下 property:
props、attrs、slots、emit
换句话说,你将无法访问以下组件选项:
data、computed、methods、refs (模板 ref)

使用渲染函数

setup 还可以返回一个渲染函数,该函数可以直接使用在同一作用域中声明的响应式状态:

import { h, ref, reactive } from 'vue'

export default {
  setup() {
    const readersNumber = ref(0)
    const book = reactive({ title: 'Vue 3 Guide' })
    // 请注意这里我们需要显式使用 ref 的 value
    return () => h('div', [readersNumber.value, book.title])
  }
}

返回一个渲染函数将阻止我们返回任何其它的东西。从内部来说这不应该成为一个问题,但当我们想要将这个组件的方法通过模板 ref 暴露给父组件时就不一样了。

我们可以通过调用 expose 来解决这个问题,给它传递一个对象,其中定义的 property 将可以被外部组件实例访问:

import { h, ref } from 'vue'
export default {
  setup(props, { expose }) {
    const count = ref(0)
    const increment = () => ++count.value

    expose({
      increment
    })

    return () => h('div', count.value)
  }
}

这个 increment 方法现在将可以通过父组件的模板 ref 访问。

组合式 API 语法糖 (<script setup>)

# 基本语法、释义
<script setup>
console.log('hello script setup')
</script>
  • 里面的代码会被编译成组件 setup() 函数的内容。这意味着与普通的 <script> 只在组件被首次引入的时候执行一次不同,<script setup> 中的代码会在每次组件实例被创建的时候执行
  • 当使用 <script setup> 的时候,任何在 <script setup> 声明的顶层的绑定 (包括变量,函数声明,以及 import 导入的内容) 都能在模板中直接使用
# 原有的API在<script setup>中的使用
<script setup>
使用组件
import MyComponent from './MyComponent.vue'

响应式
import { ref } from 'vue'
const count = ref(0)

props
const props = defineProps({
  foo: String
})

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

defineExpose(组件中要暴露出去的属性)
const a = 1
const b = ref(2)

defineExpose({
  a,
  b
})

自定义指令 (必须遵循 vNameOfDirective 这样的命名规范)
const vMyDirective = {
  beforeMount: (el) => {
    // 在元素上做些操作
  }
}

useSlots 和 useAttrs (也可以可以在模板中直接通过$slots和$attrs来访问)
import { useSlots, useAttrs } from 'vue'
const slots = useSlots()
const attrs = useAttrs()
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值