文章目录
- 1. setup获取props和自定义事件
- 2. 通过expose暴露给ref获取属性和方法
- 3. setup顶层async
- 4. setup返回函数
1. setup获取props和自定义事件
child 组件:
<template>
<div>
<h3>我是child组件 -- {{ title }}</h3>
<button @click="setTitle">修改父title中的数据</button>
</div>
</template>
<script>
export default {
// props单向数据流,子不能修改父
// 写法1:
// props: ['title'],
// 写法2:
props: {
title: {
type: String
}
},
// setup里面不能使用this,在此处this它的指向为undefined
// 参数1:props对象,可以用它来接受props数据,但是此对象一定不能解构
// 参数2:context对象,里面包含了 slots emit expose attrs
setup(props, { emit }) {
console.log(props.title)
// console.log(slots)
const setTitle = () => {
// 发送一个自定义事件,让父组件去绑定实现,这样完成修改title
emit('onSetTitle', Date.now() + ' - @@')
}
return { setTitle }
}
}
</script>
<style lang="scss" scoped>
</style>
父组件:
<template>
<div>
<child :title="title" @onSetTitle="setTitle">aaaa</child>
</div>
</template>
<script>
import { ref } from 'vue'
import child from './components/child.vue'
export default {
components: { child },
setup() {
const title = ref('我是父组件标题')
const setTitle = tit => {
title.value = tit
}
return { title, setTitle }
}
}
</script>
<style lang="scss" scoped></style>
2. 通过expose暴露给ref获取属性和方法
child组件:
<template>
<div>
<h3>我是child组件 -- {{ title }}</h3>
<button @click="setTitle">修改父title中的数据</button>
</div>
</template>
<script>
export default {
// props单向数据流,子不能修改父
// 写法1:
// props: ['title'],
// 写法2:
props: {
title: {
type: String
}
},
// setup里面不能使用this,在此处this它的指向为undefined
// 参数1:props对象,可以用它来接受props数据,但是此对象一定不能解构
// 参数2:context对象,里面包含了 slots emit expose attrs
setup(props, { emit, expose }) {
console.log(props.title)
const setTitle = () => {
// 发送一个自定义事件,让父组件去绑定实现,这样完成修改title
emit('onSetTitle', Date.now() + ' - @@')
}
// expose 如果你不用它,则在父组件中使用ref得到当前的实例,并且里面所有的方法和属性你都能调用,没有封装性。使用它后,你可以指定需要暴露给父组件ref调用的方法或属性。
expose({
name: 'abc'
})
return { setTitle }
}
}
</script>
<style lang="scss" scoped>
</style>
父组件:
<template>
<div>
<child ref="childRef" :title="title" @onSetTitle="setTitle">aaaa</child>
</div>
</template>
<script>
import { ref } from 'vue'
import child from './components/child.vue'
export default {
components: { child },
setup() {
const title = ref('我是父组件标题')
const childRef = ref(null)
const setTitle = tit => {
title.value = tit
console.log(childRef.value)
}
return { title, setTitle, childRef }
}
}
</script>
<style lang="scss" scoped></style>
3. setup顶层async
当 setup 需要返回一个 promise 对象时,即在顶层 setup 前添加 async 必须使用 Suspense 包裹,否则会报错。也就是说,当你的 async 不是加在顶层 setup 上时,不用拿 Suspense 包裹。
子组件:
<template>
<div>
<h3>我是child组件</h3>
<button>修改父title中的数据</button>
</div>
</template>
<script>
export default {
// setup需要返回一个 {} | ()=>{} | promise=> 必须使用 Suspense包裹
// 顶层async
async setup() {
return { }
}
}
</script>
<style lang="scss" scoped></style>
父组件:
<template>
<div>
<Suspense>
<child />
</Suspense>
</div>
</template>
<script>
import child from './components/child.vue'
export default {
components: { child },
setup() {
return {}
}
}
</script>
<style lang="scss" scoped></style>
于是我们就可以在子组件中通过 axios 进行网络请求。
子组件:
<template>
<div>
<h3>我是child组件</h3>
<button>修改父title中的数据</button>
</div>
</template>
<script>
import axios from 'axios'
import { onMounted, ref } from 'vue'
export default {
// setup需要返回一个 {} | ()=>{} | promise=> 必须使用 Suspense包裹
// 顶层async
async setup() {
let films = ref([])
onMounted(async () => {
let ret = await axios.get(
'https://api.iynn.cn/film/api/v1/getNowPlayingFilmList?cors=T&cityId=110100&pageNum=1&pageSize=10'
)
films.value = ret.data.data.films
})
return { films }
}
}
</script>
<style lang="scss" scoped></style>
父组件:
<template>
<div>
<Suspense>
<child />
</Suspense>
</div>
</template>
<script>
import child from './components/child.vue'
export default {
components: { child },
setup() {
return {}
}
}
</script>
<style lang="scss" scoped></style>
异步组件 + setup 配置顶层 async + Suspense 组件中的 default 和 fallback:
子组件:
<template>
<div>
<h3>我是child组件</h3>
<button>修改父title中的数据</button>
</div>
</template>
<script>
import axios from 'axios'
import { onMounted, ref } from 'vue'
export default {
// setup需要返回一个 {} | ()=>{} | promise=> 必须使用 Suspense包裹
// 顶层async
async setup() {
let films = ref([])
onMounted(async () => {
let ret = await axios.get(
'https://api.iynn.cn/film/api/v1/getNowPlayingFilmList?cors=T&cityId=110100&pageNum=1&pageSize=10'
)
films.value = ret.data.data.films
})
return { films }
}
}
</script>
<style lang="scss" scoped></style>
父组件:
<template>
<div>
<Suspense>
<!-- 成功显示的 -->
<template #default>
<child />
</template>
<!-- 加载中显示的 -->
<template #fallback>
<loading />
</template>
</Suspense>
</div>
</template>
<script>
import { ref, defineAsyncComponent } from 'vue'
// 异步组件 + setup配置选项顶层 async 配合 Suspense 组件
const child = defineAsyncComponent(() => import('./components/child.vue'))
export default {
components: { child },
setup() {
return {}
}
}
</script>
<style lang="scss" scoped></style>
4. setup返回函数
返回函数 ,它就相当于 render方法,不需要 template 模板。
子组件:
<script>
import { ref, h } from 'vue'
export default {
// 返回函数 它就相当于 render方法,模板,不需要template
setup() {
return () => {
return h('div', null, [
h('h3', null, '我是一个标题'),
h(
'button',
{
onClick: () => console.log('我是点击事件')
},
'按钮'
)
])
}
}
}
</script>
父组件:
<template>
<div>
<child />
</div>
</template>
<script>
// import { ref } from 'vue'
import child from './components/child.vue'
export default {
components: { child },
setup() {
return {}
}
}
</script>
<style lang="scss" scoped></style>
也可以用 jsx 语法实现上面的需求:
父组件:
<template>
<div>
<child />
</div>
</template>
<script>
import child from './components/child'
export default {
components: { child },
setup() {
return {}
}
}
</script>
<style lang="scss" scoped></style>
子组件(快捷键 rfc):
const Child = () => {
return (
<div>
<h3>jsx</h3>
<button>jsx</button>
</div>
)
}
export default Child