单击vue js子元素后更改页面上的内容

时间:2019-10-30 17:02:57

标签: javascript vue.js

我正在创建一个将在页面上显示产品的应用程序。这些产品中的每一个都有一个功能列表,例如“电池电量”,“充电时间”,甚至只是随功能而异的描述。我的问题是,如何制作可点击的元素,当单击该元素时将查找与该按钮/图标关联的数据,然后更新页面上的内容以反映这一点?此内容可能会或可能不会出现在某种形式的v-for循环中。

在下面查看我所拥有和想要实现的示例。

子组件:

<template>
  <li>
    <button @click="$emit('changeProductData', feature)">
      <img :src="require('../assets/images/' + feature.item.img)" />
    </button>
  </li>
</template>

<script>
export default {
  props: {
    feature: Object
  }
}
</script>

父组件:

<template>
  <div>
    <div v-for="product in getProduct(productId)" :key="product.productId">
      {{ product }}
      <Halo
        :featuresCount="
          `circle-container-` + product.features.length.toString()
        "
      >
        <Feature
          v-for="(feature, key, index) in product.features"
          :key="index"
          :feature="feature"
          @changeProductData="something" // this is where we call the custom event
        ></Feature>
      </Halo>

      <h1>This is where I want to dynamically inject the title for each feature on clicking corresponding feature</h1>

    </div>
  </div>
</template>

<script>
import Halo from '@/components/ProductHalo.vue'
import Feature from '@/components/ProductFeature.vue'
import json from '@/json/data.json'

export default {
  name: 'ProductSingle',
  components: {
    Halo,
    Feature
  },
  data() {
    return {
      products: json
    }
  },
  computed: {
    productId() {
      return this.$route.params.id
    }
  },
  methods: {
    getProduct(id) {
      let data = this.products
      return data.filter(item => item.productId == id)
    },
    something(e) {
      // ideally we have a method here that grabs the corresponding 
      //feature then displays it on the page
      console.log(e.item.text)
    }
  }
}
</script>

我的console.log调用确实确实从data.json中调用了正确的标题,如下所示:

[
  {
    "productId": 1,
    "name": "Test 1",
    "image": "sample.jpg",
    "features": [
      {
        "item": {
          "text": "Something else",
          "img": "sample.jpg"
        }
      },
      {
        "item": {
          "text": "Turbo",
          "img": "wine.jpg"
        }
      },
      {
        "item": {
          "text": "Strong",
          "img": "sample.jpg"
        }
      }
    ]
  }
]

所以看来我可以根据每个相应项目的点击来访问我的标题,只是不确定如何在任意位置显示该标题!有什么神奇的Vue js专家可以解决这个难题? TIA

1 个答案:

答案 0 :(得分:0)

选项1:更改子组件

我不是只为一个功能按钮创建组件,而是将整个功能列表嵌入到h1组件中,以便在其中显示所选功能。因此,子组件将如下所示:

<template>
  <div>
    <li v-for="(feature, key, index) in features" :key="index">
      <button @click="setFeature(feature)">
        <img :src="require('../assets/images/' + feature.item.img)" />
      </button>
    </li>
    <h1>{{ clickedFeuatureText }}</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
        clickedFeuatureText:null
    }
  },
  methods: {
    setFeature(e){
      this.clickedFeuatureText = e.item.text
    }
  },
  props: {
    features: Array
  }
}
</script>

这是具有相应更改的父组件:

<template>
  <div>
    <div v-for="product in getProduct(productId)" :key="product.productId">
      {{ product }}
      <Halo
        :featuresCount="
          `circle-container-` + product.features.length.toString()
        "
      >
        <Feature :features=" product.features"></Feature>
      </Halo>
    </div>
  </div>
</template>

<script>
import Halo from '@/components/ProductHalo.vue'
import Feature from '@/components/ProductFeature.vue'
import json from '@/json/data.json'

export default {
  name: 'ProductSingle',
  components: {
    Halo,
    Feature
  },
  data() {
    return {
      products: json
    }
  },
  computed: {
    productId() {
      return this.$route.params.id
    }
  },
  methods: {
    getProduct(id) {
      let data = this.products
      return data.filter(item => item.productId == id)
    }
  }
}
</script>

选项2:为一种产品创建新组件

另一种方法是保留子组件不变,但是创建代表列表中一个产品的新组件:

<template>
  <div>
      {{ product }}
      <Halo
        :featuresCount="
          `circle-container-` + product.features.length.toString()
        "
      >
        <Feature
          v-for="(feature, key, index) in product.features"
          :key="index"
          :feature="feature"
          @changeProductData="setFeatureText"
        ></Feature>
      </Halo>

      <h1>{{ clickedFeature}}</h1>

    </div>
  </div>
</template>

<script>
import Feature from '@/components/ProductFeature.vue'
import Halo from '@/components/ProductHalo.vue'

export default {
  name: 'product',
  components: {
    Feature,
    Halo 
  },
  data () {
    return {
      clickedFeature: null
    }
  },
  props: {
    product: Object
  },
  methods: {
    setFeatureText(e) {
      this.clickedFeature = e.item.text
    }
  }
}
</script>

然后使用新的Product组件:

<template>
  <div>
    <product 
      v-for="product in getProduct(productId)" 
      :key="product.productId" 
      :product="product"
    ></product>
  </div>
</template>

<script>
import Product from '@/components/Product.vue'
import json from '@/json/data.json'

export default {
  name: 'ProductSingle',
  components: {
    Product
  },
  data() {
    return {
      products: json
    }
  },
  computed: {
    productId() {
      return this.$route.params.id
    }
  },
  methods: {
    getProduct(id) {
      let data = this.products
      return data.filter(item => item.productId == id)
    }
  }
}
</script>
相关问题