父组件代码
<template>
  <div class="page_content_container">
    <div class="recommand_communities_container">
      <community_card v-for="(community,index) in communities" v-bind:key="index" v-bind:community="community" v-on:onclick="onChosen" />
    </div>
  </div>
</template>
<script>
import community_card from '../community_card.vue';
export default {
  components: { community_card},
  name: "page_content",
  data: function () {
    return {
      communities:[
		{
			id:'1'
			name:'1-C',
			intro:'1-C Test',
			avatar:'/1-C-avatar.jpg'
			selected:true
		},
		{
			id:'2'
			name:'2-C',
			intro:'2-C Test',
			avatar:'/2-C-avatar.jpg'
			selected:false
		},
		{
			id:'3'
			name:'3-C',
			intro:'3-C Test',
			avatar:'/3-C-avatar.jpg'
			selected:false
		},
	  ]
    }
  },
  methods: {
    onChosen:function(communityId){
      for (let index = 0; index < this.communities.length; index++) {
        const element = this.communities[index];
        if(element.id == communityId ){
           element.selected = true;
		   // element.name = 'DoTest'; 有这一行 子组件的 class 会变更 ,没有则不会变更
        }else{
          element.selected = false
        }
      }
    }
  },
};
</script>
<style scoped>
.page_content_container {
  height: 800px;
  width: 100%;
  display:flex;
}
.recommand_communities_container {
  height: 800px;
  width: 240px;
  margin: 0;
  padding: 0;
  display: inline-block;
}
.recommand_community_post_container {
  border-radius: 15px;
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 0;
  border-left:1px solid rgba(0, 0, 0, 0.22);
  display: inline;
}
</style>
子组件
<template>
  <div class="community_card_container" v-bind:class="{'selected':community.selected}" v-on:click="onclick">
    <div class="community_card_avatar_container">
      <img :src="community.avatar" :title="community.name" />
    </div>
    <div class="community_card_base_info_container">
      <div>{{ community.name }}</div>
      <div>{{ community.intro }}</div>
    </div>
  </div>
</template>
<script>
export default {
  name: "community_card",
  data: function () {
    return {
	
    }
  },
  methods: {
    onclick: function () {
      this.$emit('onclick',this.community.id)
    },
  },
  props:['community']
};
</script>
<style scoped>
.community_card_container {
  height: 76px;
  width: 236px;
  border: lightslategray 2px solid;
  display: flex;
  border-radius: 10px;
}
.selected{
  background-color:lightskyblue ;
}
.community_card_container .community_card_avatar_container {
  height: 76px;
  width: 76px;
  display: inline;
  text-align: center;
}
.community_card_container .community_card_base_info_container {
  width: 136px;
  border-left:rgb(177, 171, 204) 2px solid;
}
.community_card_container .community_card_avatar_container img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
}
.community_card_container .community_card_base_info_container div {
  height: 38px;
  width: 136px;
  line-height: 38px;
  text-align:center;
  overflow:hidden;
}
</style>
请教原因和怎么解决
使用axios 在变更数据后 使用this.$forceupdate() 重新渲染视图
子组件更新了selected的数据 父组件实际上并没有更新 而name 这些是同步更新的
|      1bootvue      2021-02-02 14:27:59 +08:00 props:['community']   这种写法   子组件   仅仅会把 props 数据 copy 一份为本地变量使用 如果希望观察到 props 的变化 子组件应该用 computed 官方文档说的很清楚 https://cn.vuejs.org/v2/guide/components-props.html#%E5%8D%95%E5%90%91%E6%95%B0%E6%8D%AE%E6%B5%81 | 
|  |      2shintendo      2021-02-02 14:30:13 +08:00 一个建议:提问时为了方便他人阅读,尽可能先整理代码,至少不要有缺少逗号这种问题,最重要的是删除所有与问题无关的干扰代码,当你最后得到一个能复现问题的最短代码时,大概率你自己就发现问题的所在了。 | 
|  |      3ZZ222ZZ      2021-02-02 14:32:40 +08:00 好像这个需要用到深度监听,如果只是 community 属性的值发生变化,props 是不会更新的 | 
|      4Lemeng      2021-02-02 14:33:53 +08:00 代码有点多,把不要的去掉,尽量精简,一眼就知道问题所在 | 
|      5chenluo0429      2021-02-02 14:39:45 +08:00 凭感觉口胡一下。 子组件响应式的监听只到 community 这一层,对于其属性的变更不会响应。解决方案是将 community 的属性分别在 props 里面传给子组件,或者子组件添加若干 computed 计算属性来监听具体属性的变化。 | 
|      6jadeborner      2021-02-02 14:46:13 +08:00 用 this.$set | 
|  |      7hengshenyu      2021-02-02 14:49:18 +08:00 我本地运行了下,没有问题。className 可以响应变化。建议看看缓存?或者 vue 版本升级? | 
|  |      8hengshenyu      2021-02-02 14:49:35 +08:00 就是少了些逗号 | 
|  |      9ragnaroks      2021-02-02 14:50:39 +08:00 复制你的代码,使用 vue-cli 运行,没有任何问题,点击后就切换为蓝色底色了 | 
|  |      10shakaraka PRO 同意#5 的说话。 其次我是建议你更改子组件的状态的话就用一个 bind: selected 即可,不要包装在对象里面,不然检测不到对象变化,除非你重新赋值 community 。 可以试一下 watch,watch 有一个 deep 选项,或者试一下 computed 。 | 
|  |      11Aruforce OP @bootvue  不是,’拷贝‘这句事实错误, @ZZ222ZZ @chenluo0429 @jadeborner @bootvue 如当前代码这种写死数据的情况,是能够根据 selected 的变更 class value 的 @shintendo @Lemeng 抱歉。。。 | 
|  |      13shakaraka PRO 父组件改成 ``` <community_card v-for="(community,index) in communities" :selected="community.selected" :avatar="community.avatar" :name="community.name" :intro="community.intro" /> ``` 子组件改成 ``` export default { name: "community_card", props:['selected', 'avatar', 'name', 'intro'] }; ``` 这样试试? | 
|      14JXS      2021-02-02 15:01:55 +08:00 data 接收 prop,然后监听一下 prop,在监听里面去把数值改变一下看可以不 | 
|  |      16hengshenyu      2021-02-02 15:13:43 +08:00 @Aruforce 因为你是从 axios 获取的数据,所以我猜测你可能没有在 data 对它进行声明。Vue 实例生成时也就没有进行代理。 Vue 需要使用的数据都需要预先声明,否则就需要使用 this.$set(),手动处理。 | 
|  |      17Curtion      2021-02-02 15:19:54 +08:00 既然写死数据那就说明不是组件传值问题引起的,你应该从其他地方入手。 我说一个可能的原因:你的 communities 变量在实际业务上可能是异步获取的,并且其中并没有 selected 属性?  考虑使用 Vue.set | 
|  |      18Aruforce OP @hengshenyu 应该不是吧。。子组件的数据是我从父组件传递进去的。。所有的属性都有值。。peopertySetter 应该被代理了才对了 | 
|      19ugu      2021-02-02 15:23:07 +08:00 通过索引直接修改数据,vue 无法监听到,建议使用 splice 或者 set | 
|  |      20Aruforce OP @Curtion 在 axios complete 的返回里面 element.selected = true 做了这个操作了 | 
|  |      21jrtzxh020      2021-02-02 15:33:23 +08:00 不考虑性能的话。最简单的方法新建一个变量 a,将 communities 深拷贝赋值给 a,遍历 a 修改 selected 后。最后重新赋值 this.communities = a | 
|  |      23jrtzxh020      2021-02-02 15:37:56 +08:00 @jrtzxh020 或者在 onChosen 方法最后调用 this.communities =  JSON.parse(JSON.stringify(this.communities)) 哈哈 不是很建议 | 
|      24yor1g      2021-02-02 16:22:00 +08:00 更新 element 方法不对  子组件检查不到变更  https://cn.vuejs.org/v2/api/#Vue-set | 
|  |      25Doracis      2021-02-02 16:29:10 +08:00 不看代码先凭经验说,加深度监听 deep immediate,要么父组件 this.$set | 
|  |      26RoshanWu      2021-02-02 20:39:19 +08:00 用个定时器模拟了下 LZ 说的「从后台通过 axios 抓取的数据 」,也没看出啥异常 ``` setTimeout(() => { this.communities[0].selected = false }, 3000); ``` | 
|  |      27rodrick      2021-02-02 22:21:57 +08:00 总得来说 community.id 如果要传回去的话就最好 copy 一下再传,毕竟我总觉得把 prop 去$set 响应式有点怪,专一原则上来说 prop 就作为一个父子传参读取就好了 | 
|      28zqx      2021-02-03 06:40:55 +08:00 via Android 总的来说就是不要推测 vue 组件什么时候会重新渲染 forceupdate 写多了会让代码不好维护,导致下一个程序员不容易从代码中追踪数据变化 你明知道 vue 组件不会响应的数据变化(几种常见情况,官网有实例),就用 watch 手动监听它(开启 deep 选项) |