/
代码 setup
函数内,通过 ref
、reactive
创建两个变量,如果 setup
返回一个对象,则对象的属性将会被合并到模板变量的渲染上下文,也就是在 template
模板里,可以使用 setup
函数返回的对象内容(包括函数方法)。
//改造App.vue
<template>
<div>{{count}}{{state.foo}}</div>
</template>
<script>
import {ref,reactive} from 'vue'
export default{
setup(){
const count=ref(0)
const state=reactive({foo:'bar'})
return{
count,
state,
}
}
}
</script>
<template>
<div>{{count}}{{state.foo}}</div>
</template>
<script>
import {ref,reactive} from 'vue'
export default{
setup(){
const count=ref(0)
const state=reactive({foo:'bar'})
setTimeout(()=>{
count.value=1
state.foo='foo'
},2000)
return{
count,
state,
}
}
}
</script>
通过 ref
、reactive
方法包裹的变量,会被赋予响应式的能力,也就是说你在 setup
函数内改变他们的值,模板内也会响应展示改变后的值
//h 函数是 createElement 的别名,//Vue 提供了createElement 来创建虚拟domsetup
也可以返回一个函数,函数中也能使用当前 setup
函数作用域中的响应式数据
<template>
<div>{{count}}{{state.foo}}</div>
</template>
<script>
import {ref,reactive,h} from 'vue'
export default{
setup(){
const count=ref(1)
const state1=reactive({foo:'bar'})
return ()=>h('h1',[count.value,state1.foo])
}
}
</script>
通过 h
函数,将 count.value
(在 setup 函数作用域内,需要使用 .value 获取值) 和 object.foo
渲染到 h1
标签内。
props 对象:
<template>
<Test :count="count"></Test>
</template>
<script>
import { ref } from 'vue'
import Test from './components/Test.vue'
export default {
components: {
Test
},
setup() {
const count = ref(0)
return {
count
}
}
}
</script>
子:src/components 下新增 Test.vue 组件
<template>
<div>{{ count }}</div>
</template>
<script>
export default {
name: 'Test',
props: {
count: Number
},
setup(props) {
console.log('props', props)
}
}
</script>
在页面中我们打印了 props
,可以发现它被 Proxy
代理过,这是 Vue 3.0
实现响应式的核心 API,也就是说从父亲组件传到子组件的 count
变量,已经是响应式数据
并且在子组件内,可以通过 watchEffect
和 watch
观察到数据的变化情况
注意 props 不要进行解构,如 setup(...props),这样会让 props 失去响应式。
// App.vue
...
setup() {
const count = ref(0)
setTimeout(() => {
count.value = 100
}, 2000)
return {
count
}
}
...
// Test.vue
...
import { watchEffect } from 'vue'
setup(props) {
watchEffect(() => {
console.log('props.count = ', props.count)
})
}
...
context 上下文
ctx
(context)参数提供了一个上下文对象,从原来的 Vue 2.0
中的 this
选择性的暴露一些属性。
ctx
为我们提供了三个属性,分别是:
- attrs
- slots
- emit
attrs
为我们提供了最新传入的数据 ,在使用 attrs
时候,不能在 options
中声明 props
,否则 attrs
取不到变量
<template>
<div>{{ count }}</div>
</template>
<script>
import { watchEffect } from 'vue'
export default {
name: 'Test',
// props: {
// count: Number
// },
setup(props,ctx) {
console.log('props', props)
console.log('ctx',ctx.attrs.count)
return{
attrs:ctx.attrs
}
}
}
</script>
子组件调用父组件传进来的方法,并且带上回调参数
子组件接收的方法,需要通过 emits
在 options
中注册,否则会报警告。通过上下文 ctx.emit
触发传进来的方法以及返回相应的回调参数
// App.vue
<template>
<Test :count="count" @add="add"></Test>
</template>
<script>
import { ref } from 'vue'
import Test from './components/Test.vue'
export default {
name: 'App'
components: {
Test
},
setup() {
const count = ref(0)
const add = (num) => count.value += num
return {
count,
add
}
}
}
</script>
// Test.vue
<template>
<div>{{ count }}</div>
<button @click="add">++++</button>
</template>
<script>
import { watchEffect } from 'vue'
export default {
name: 'Test',
props: {
count: Number,
add: Function
},
emits: ['add'],
setup(props, ctx) {
const add = () => {
ctx.emit('add', 50)
}
return {
add
}
}
}
</script>