setup获取props和自定义事件、通过expose暴露给ref获取属性和方法、setup顶层async、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

在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值