本文介绍了如何使用 VueJS 将数据正确传递给兄弟组件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有 CountrySelectCitySelect,其中在 CountrySelect 中列出了所有国家,而在 CitySelect 中是只列出了当前所选国家的那些城市...

通过新选择的国家/地区的正确方法是什么.正如我在 vuejs 文档中所读到的:

在Vue中,父子组件关系可以概括为props down,event up.父级通过 props 将数据传递给子级,子级通过事件向父级发送消息.接下来让我们看看它们是如何工作的.

所以在这种情况下,我会检测 CountrySelect 和触发事件 changed 内的选择框的变化,以及一个国家对象.然后CountrySelect 的父组件会监听这个事件,然后当它发生时更新它的属性country.属性 country 在父组件中被观察到",改变其值会导致 DOM 更新,因此 标签上的 HTML 属性称为 country 会改变.但是,我将如何检测 CitySelect 组件的属性更改,因为我需要通过 AJAX 重新加载城市.我想将 country 属性放在 CitySelect 中的 watch 对象中,但这对我来说似乎不是一个优雅的解决方案,感觉并不奇怪正确的做法...

<country-select name="country_id" v-model="country"></country-select><city-select name="city_id" :country="country" v-model="city"></city-select></父母><模板><脚本>导出默认{数据:函数(){返回 {国家:空,城市:空,};}}

我认为的另一种方法是,如果在父级中做这样的事情:

this.$refs.citySelect.emit('countryChanged', this.country)

或:

this.$refs.citySelect.countryChanged(this.country)

我不知道这两个是否可能...那么 CountrySelect 组件告诉其兄弟组件 CitySelect 更新城市列表的正确方法是什么...

解决方案

通过将 country 作为属性传递给 CitySelect 组件,您已经em> 做你需要做的事.当country 改变时,改变的值将传递给CitySelect 组件.您只需要确保您的 CitySelect 组件知道这些更改.

这是一个工作示例.

console.clear()//按国家检索城市的模拟服务const CityService = {城市: [{id: 1, country: "USA", name: "New York"},{id: 2, country: "USA", name: "San Francisco"},{id: 3, country: "USA", name: "Boston"},{id: 4, country: "USA", name: "Chicago"},{id: 5, country: "England", name: "London"},{id: 6, country: "England", name: "Bristol"},{id: 7, country: "England", name: "Manchester"},{id: 8, country: "England", name: "Leeds"},],获取城市(国家){返回新的承诺((解决,拒绝)=> {setTimeout(() => resolve(this.cities.filter(city => city.country === country)), 250)})}}Vue.component("国家选择",{道具:[价值"],模板:`<select v-model="selectedCountry"><option v-for="country in countries" :value="country">{{country}}</option></选择>`,数据(){返回 {国家:[美国",英国"]}},计算:{所选国家:{get(){return this.value},set(v){this.$emit('input', v)}}}})Vue.component("城市选择", {道具:[价值",国家"],模板:`<select v-model="selectedCity"><option v-for="城市中的城市" :value="city">{{city.name}}</option></选择>`,数据(){返回 {城市:[]}},计算:{所选城市:{get(){return this.value},set(v){this.$emit('input', v)}}},手表:{国家(新国家){//模拟对外部服务的 AJAX 调用CityService.getCities(newCountry).then(cities => this.cities =城市)}}})新的 Vue({el: "#app",数据:{国家:空,城市:空}})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script><div id="应用程序"><country-select v-model="country"></country-select><city-select :country="country" v-model="city"></city-select><小时>所选国家/地区:{{country}} 
所选城市:{{city}}

Let's say I have CountrySelect and CitySelect, where in CountrySelect are listed all countries and in CitySelect are only listed those cities of currently selected country...

What would the proper way to pass newly selected country. As I have read in vuejs documentation:

So in this case, I would detect change of select box inside of CountrySelect and fire event changed and along with it a country object. Then the parent component of CountrySelect would listen for this event and then when that happens will update its attribute country. Attribute country is "observed" in parent component and changing its value will cause for DOM to update, so HTML attribute on <city-select> tag called country would change. But then how would I detect property change of CitySelect component, since I need to reload cities via AJAX. I think of putting country property in watch object in CitySelect but that does not seems like an elegant solution to me, it doesn't feels quire right to do...

<template>
    <parent>
        <country-select name="country_id" v-model="country"></country-select>
        <city-select name="city_id" :country="country" v-model="city"></city-select>
    </parent>
<template>

<script>
    export default {
        data: function() {
            return {
                country: null,
                city: null,
            };
        }
    }
</script>

Other way around that I think is if do something like this in parent:

this.$refs.citySelect.emit('countryChanged', this.country)

or:

this.$refs.citySelect.countryChanged(this.country)

I do not know if these two are possible... So what would be the correct way for CountrySelect component to tell to its sibling component CitySelect to update cities list...

解决方案

By passing country as a property to your CitySelect component, you are already doing what you need to do. When country changes, the changed value will be passed to the CitySelect component. You simply need to make sure your CitySelect component is aware of the changes.

Here is a working example.

console.clear()

// Simulated service for retrieving cities by country
const CityService = {
  cities: [
    {id: 1, country: "USA", name: "New York"},
    {id: 2, country: "USA", name: "San Francisco"},
    {id: 3, country: "USA", name: "Boston"},
    {id: 4, country: "USA", name: "Chicago"},
    {id: 5, country: "England", name: "London"},
    {id: 6, country: "England", name: "Bristol"},
    {id: 7, country: "England", name: "Manchester"},
    {id: 8, country: "England", name: "Leeds"},
  ],
  getCities(country){
    return new Promise((resolve, reject) => {
      setTimeout(() => resolve(this.cities.filter(city => city.country === country)), 250)
    })
  }
}

Vue.component("CountrySelect",{
  props: ["value"],
  template: `
  <select v-model="selectedCountry">
    <option v-for="country in countries" :value="country">{{country}}</option>
  </select>
  `,
  data(){
    return {
      countries: ["USA", "England"]
    }
  },
  computed:{
    selectedCountry:{
      get(){return this.value},
      set(v){this.$emit('input', v)}
    }
  }
})

Vue.component("CitySelect", {
  props: ["value", "country"],
  template: `
  <select v-model="selectedCity">
    <option v-for="city in cities" :value="city">{{city.name}}</option>
  </select>
  `,
  data(){
    return {
      cities: []
    }
  },
  computed:{
    selectedCity:{
      get(){return this.value},
      set(v){this.$emit('input', v)}
    }
  },
  watch:{
    country(newCountry){
      // simulate an AJAX call to an external service
      CityService.getCities(newCountry).then(cities => this.cities = cities)
    }
  }
})

new Vue({
  el: "#app",
  data:{
    country: null,
    city: null
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
  <country-select v-model="country"></country-select>
  <city-select :country="country" v-model="city"></city-select>
  <hr>
  Selected Country: {{country}} <br>
  Selected City: {{city}}
</div>

这篇关于如何使用 VueJS 将数据正确传递给兄弟组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-25 19:15