javascript - 如何使用 VueJS 正确地将数据传递给同级组件?

标签 javascript vue.js vuejs2

假设我有 CountrySelectCitySelect ,在 CountrySelect 中列出了所有国家和 CitySelect仅列出当前所选国家/地区的城市...

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

In Vue, the parent-child component relationship can be summarized as props down, events up. The parent passes data down to the child via props, and the child sends messages to the parent via events. Let’s see how they work next.

所以在这种情况下,我会检测CountrySelect内选择框的变化和火灾事件changed以及一个国家对象。然后是CountrySelect的父组件将监听此事件,然后当发生这种情况时将更新其属性 country 。属性country在父组件中被“观察到”,更改其值将导致 DOM 更新,因此 <city-select> 上的 HTML 属性标签名为 country会改变的。但是我如何检测 CitySelect 的属性变化组件,因为我需要通过 AJAX 重新加载城市。我想把country属性(property) watch CitySelect 中的对象但这对我来说似乎不是一个优雅的解决方案,感觉这样做不太正确......

<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>

我认为如果在父级中做这样的事情:

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

或者:

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

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

最佳答案

通过将country作为属性传递给您的CitySelect组件,您已经做您需要做的事情。当country更改时,更改的值将传递给CitySelect组件。您只需确保您的 CitySelect 组件了解这些更改。

这是一个工作示例。

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>

关于javascript - 如何使用 VueJS 正确地将数据传递给同级组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48190694/

相关文章:

javascript - jQuery addClass 和标准 classList.addClass 有什么区别?

javascript - 获取 `url` 的访问被 CORS 策略 : No 'Access-Control-Allow-Origin' header is present on the requested resource. ReactJS 阻止

mysql - VueJS 中的数组循环所有空值函数

vue.js - 带有单选按钮的 VueJS 简单工具

javascript - 如何将提取数据与从不同提取调用的图像匹配?

javascript - 在 Javascript 中删除属性

javascript - 在 vee validate 内的正则表达式中转义单引号和双引号

javascript - 除了第一个之外, Canvas 不会在表格内绘制

javascript - Vuetify 数据表创建自定义过滤器

javascript - 尝试使用 v-for 循环和对象属性动态创建 URL,但收到 GET 错误