问个 Vue 的问题,父组件通过 props 传值给子组件,在父组件内更改数据 子组件的 class 属性没有变更,详情见代码

2021-02-02 14:09:06 +08:00
 Aruforce

父组件代码

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

请教原因和怎么解决

2379 次点击
所在节点    程序员
28 条回复
bootvue
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
shintendo
2021-02-02 14:30:13 +08:00
一个建议:提问时为了方便他人阅读,尽可能先整理代码,至少不要有缺少逗号这种问题,最重要的是删除所有与问题无关的干扰代码,当你最后得到一个能复现问题的最短代码时,大概率你自己就发现问题的所在了。
ZZ222ZZ
2021-02-02 14:32:40 +08:00
好像这个需要用到深度监听,如果只是 community 属性的值发生变化,props 是不会更新的
Lemeng
2021-02-02 14:33:53 +08:00
代码有点多,把不要的去掉,尽量精简,一眼就知道问题所在
chenluo0429
2021-02-02 14:39:45 +08:00
凭感觉口胡一下。
子组件响应式的监听只到 community 这一层,对于其属性的变更不会响应。解决方案是将 community 的属性分别在 props 里面传给子组件,或者子组件添加若干 computed 计算属性来监听具体属性的变化。
jadeborner
2021-02-02 14:46:13 +08:00
用 this.$set
hengshenyu
2021-02-02 14:49:18 +08:00
我本地运行了下,没有问题。className 可以响应变化。建议看看缓存?或者 vue 版本升级?
hengshenyu
2021-02-02 14:49:35 +08:00
就是少了些逗号
ragnaroks
2021-02-02 14:50:39 +08:00
复制你的代码,使用 vue-cli 运行,没有任何问题,点击后就切换为蓝色底色了
wunonglin
2021-02-02 14:53:11 +08:00
同意#5 的说话。

其次我是建议你更改子组件的状态的话就用一个 bind: selected 即可,不要包装在对象里面,不然检测不到对象变化,除非你重新赋值 community 。

可以试一下 watch,watch 有一个 deep 选项,或者试一下 computed 。
Aruforce
2021-02-02 14:54:06 +08:00
@bootvue 不是,’拷贝‘这句事实错误,
@ZZ222ZZ @chenluo0429 @jadeborner @bootvue 如当前代码这种写死数据的情况,是能够根据 selected 的变更 class value 的
@shintendo @Lemeng 抱歉。。。
Aruforce
2021-02-02 14:55:49 +08:00
@ragnaroks 是的 但是 我的数据是从后台通过 axios 抓取的数据 这种情况下 不行 颜色无法改变
wunonglin
2021-02-02 14:57:48 +08:00
父组件改成
```
<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']
};
```


这样试试?
JXS
2021-02-02 15:01:55 +08:00
data 接收 prop,然后监听一下 prop,在监听里面去把数值改变一下看可以不
Aruforce
2021-02-02 15:08:01 +08:00
@wunonglin 并不行
hengshenyu
2021-02-02 15:13:43 +08:00
@Aruforce 因为你是从 axios 获取的数据,所以我猜测你可能没有在 data 对它进行声明。Vue 实例生成时也就没有进行代理。
Vue 需要使用的数据都需要预先声明,否则就需要使用 this.$set(),手动处理。
Curtion
2021-02-02 15:19:54 +08:00
既然写死数据那就说明不是组件传值问题引起的,你应该从其他地方入手。 我说一个可能的原因:你的 communities 变量在实际业务上可能是异步获取的,并且其中并没有 selected 属性? 考虑使用 Vue.set
Aruforce
2021-02-02 15:22:42 +08:00
@hengshenyu 应该不是吧。。子组件的数据是我从父组件传递进去的。。所有的属性都有值。。peopertySetter 应该被代理了才对了
ugu
2021-02-02 15:23:07 +08:00
通过索引直接修改数据,vue 无法监听到,建议使用 splice 或者 set
Aruforce
2021-02-02 15:30:02 +08:00
@Curtion 在 axios complete 的返回里面 element.selected = true 做了这个操作了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/750598

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX