Vue3复习和总结(Component)组件间四种数据传递的方式与插槽,props、emit、ref

Vue3复习和总结(Component)组件间四种数据传递的方式与插槽与祖孙组件间通信,props、emit、ref,Provide / Inject

代码全部放在->github仓库:https://github.com/zyugat/vue-review-all

前言:分为base、Component、router、Vuex、组合式API。5各部分。

base和Component中的例子不使用脚手架运行,需自行浏览器运行。位置->noCli

props

字符串数组

  • 父传子props

    • props两种实现:一种是以字符串数组,一种是以对象实现。

1、父组件传入:chello="hello"属性

2、子组件声明接收props: ['chello']

<div id="app">
  <cpn :chello="hello"></cpn>
</div>
<!--<template id="cpn">-->
<!--  <h2>{{ chello }}</h2>-->
<!--</template>-->
<script>
  const App = {
    data() {
      return {
        hello: 'Hello',
      }
    }
  }
  const app = Vue.createApp(App)
  app.component('cpn', {
    // template: '#cpn',
    template: `
      <h2>{{ chello }}</h2>
    `,
    // 创建props
    props: ['chello'],
  })
  app.mount('#app')
</script>

image-20211116173256435

对象

props: {
  // 1.类型限制
  // cmessage: Array,
  // chello: String,
  // 2.提供一些默认值, 以及必传值
  chello: {
    type: String,
    default: 'aaaaaaaa',
    required: true
  },
  // 类型是对象或者数组时, 默认值必须是一个函数
  cmessage: {
    type: Array,
    default () {
      return []
    }
  }
},

emit

  • 子传父→$emit

第一步:子组件创建事件。第二步:按钮监听子组件事件。最后一步:获取信息。

更多扩展看下面->自定义事件与v-model

<div id="app">
  <cpn2 @item-click="cpn2Click"></cpn2>
</div>
<script>
  const App = {
    methods: {
      // 第三步:将按钮信息发送到控制台
      cpn2Click(item) {
        console.log('cpnClick', item)
      },
    },
  }
  const app = Vue.createApp(App)
  app.component('cpn2', {
    template: `
      <button @click="btnClick">子传父</button>
    `,
    methods: {
      btnClick(event) {
        // 第一步:发射自定义事件
        this.$emit('item-click', event)
      },
    },
  })

  app.mount('#app')
</script>

image-20211116174234498

refs

父访问子→$refs

  • 给组件绑定一个ID,然后使用this.$refs.ID调用。
<div id="app">
  <button @click="btnClick" ref="test">refs获取</button>
</div>
<script>
  const App = {
    methods: {
      btnClick() {
        // 2.$refs => 对象类型
        console.log(this.$refs.test)
      },
    },
  }
  const app = Vue.createApp(App)
  app.mount('#app')
</script>

祖孙组件通信Provide / Inject

Provide / Inject

1、祖与孙组件间通信。

父组件使用 provide 选项来发送数据

后代组件使用 inject 选项来获取数据

app.component('grandfather', {
  provide: {
    user: 'John Doe',
  },
  template: `
    <father />`,
  components: {
    'father': {
      template: `
        <son />`,
      components: {
        'son': {
          inject: ['user'],
          template: `son:{{user}}`,
        },
      },
    },
  },
})

image-20211116221339750

2、如果想在 provide 中使用组件的实例 property属性,则需要将 provide 转换为返回对象的函数。

provide() {
    return {
      user: this.num,
    }
  },

3、 provide/inject 的绑定不是响应式的,如果想修改todos的长度,则需要绑定组合式API computed 属性。

provide() {
  return {
    user: Vue.computed(() => this.num),
  }
},

插槽

具名插槽

缩写:<template #header>

因为没有调用 右边 所以少了他。

<div id="app">
  <cpn3><span slot="center">标题  </span></cpn3>
  <cpn3><span slot="left">中间  </span></cpn3>
</div>
<template id="cpn3">
  <div>
    <slot name="left"><span>左边</span></slot>
    <slot name="center"><span>中间</span></slot>
    <slot name="right"><span>右边</span></slot>
  </div>
</template>

image-20211116175233031

作用域插槽

可以理解为:将外部内容放在子组件slot中

<slot :item="item" :index="index"
              :another-attribute="anotherAttribute">
      <span>{{ item }}</span>
      <span>-----{{ anotherAttribute }}</span>
</slot>

这样看懂了把?

自定义项目的渲染方式。默认插槽不能和具名插槽混用

1、v-slot:default=""v-slot="",不带参数的 v-slot 被假定对应默认插槽。

2、在插槽中,绑定了item、index、anotherAttribute,如果需要用到某个属性则可以使用 slotProps.属性名,进行调用。

slotProps可以替换为任何名字。

<div id="app">
    <cpnslot>
    <template v-slot:default="slotProps">
      <span>{{ slotProps.item }}</span>
      <span>-----{{ slotProps.anotherAttribute }}</span>
    </template>
  </cpnslot>
</div>
<script>
  const App = {}
  const app = Vue.createApp(App)
    app.component('cpnslot', {
    data() {
      return {
        items: [1, 2, 3, 4, 5],
        anotherAttribute: 'slot-anotherAttribute',
      }
    },
    template: `
      <ul>
      <li v-for="(item, index) in items">
        <slot :item="item" :index="index"
              :another-attribute="anotherAttribute"></slot>
      </li>
      </ul>
    `,
  })
  app.mount('#app')
</script>

image-20211116181117133

因为作用域插槽的内部工作原理是将你的插槽内容包括在一个传入单个参数的函数里,所以可以在里面使用JS表达式,如重命名:

将item重命名为todo

<todo-list v-slot="{ item: todo }">

动态插槽名

<template v-slot:[dynamicSlotName]>

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据你提供的代码,我看到在 `onChange` 函数中,已经调用了 `optionCityApi` 函数来获取城市列表,并将其赋值给了 `cityList`。然后通过 `updateSchema` 函数更新了 `cityId` 的选项,但是你说无法获取到市关联的列表,可能是因为你没有将 `cityId` 的选项正确地传递给 `Select` 组件。 你可以在 `cityId` 的 `componentProps` 中指定 `options` 为 `componentProps.options`,而不是将其设置为一个空数组。这样,当你更新了 `cityId` 的选项时,`Select` 组件将自动重新渲染,并显示新的选项。你还需要指定 `labelField` 和 `valueField` 属性,以确保正确地显示选项的标签和值。 修改后的代码如下: ``` { label: '省关联', field: 'provinceId', colProps: { span: 12 }, component: 'ApiSelect', componentProps: ({ formActionType }) => { return { api: optionSegmentApi, showSearch: true, optionFilterProp: 'label', resultField: 'items', labelField: 'name', valueField: 'id', onChange: async (e: any) => { const cityList = await optionCityApi(e); const { updateSchema } = formActionType; updateSchema({ field: 'cityId', componentProps: { options: cityList, labelField: 'name', valueField: 'id', }, }); console.log('cityList', cityList); // move the log statement here }, }; }, }, { label: '市关联', field: 'cityId', component: 'Select', componentProps: { showSearch: true, optionFilterProp: 'label', options: [], labelField: 'name', valueField: 'id', }, colProps: { span: 12 }, } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值