In vue, the props, of the child component is modified by modifying the parent component props, but the child component does not respond after the modification. Why?

I want to implement a component of tabbar myself, so I define two components to combine the implementation:

< H1 > 1. TabBar < / H1 >
<template>
  <div class="tabbar">
    <tab-item v-for="item in tabItems"
      :key="item.index"
      v-bind="item"
      @tabItemOnClick="tabItemOnClick"
    >
    </tab-item>
  </div>
</template>
<script>
import TabItem from "./tabitem.vue"
export default {
  name: "tab-bar",
  components: {TabItem},
  props: {
    tabItems: {
      default: []
    }
  },
  data () {
    return {
      selectedIndex: 0
    }
  },
  created () {
    this.select(this.selectedIndex)
  },
  methods: {
    tabItemOnClick (params) {
      this.selectedIndex = params.index
      this.select(this.selectedIndex)
      this.toast(this.selectedIndex)
    },
    select (index) {
      for (let i = 0; i < this.tabItems.length; iPP) {
        var tabItem = this.tabItems[i]
        if (i === index) {
          tabItem.selected = true
        } else {
          tabItem.selected = false
        }
      }
    }
  }
}
</script>
<style>
  .tabbar {
    background-color: -sharpffffff;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: 100px;
    flex-wrap: nowrap;
    flex-direction: row;
  }
</style>
< H1 > 2.TabBarItem < / H1 >
<template>
  <div class="bar-item" @click="onTabItemClick">
    <text class="icon iconfont" :class="[ selected ? "active" : "" ]">{{ icon }}</text>
    <text class="text" :class="[ selected ? "active" : "" ]">{{ title }}</text>
    <div v-if="parseInt(dot) === 0">
      <text :class="[ needNum ? "notice" : "dot" ]">{{ dot }}</text>
    </div>
  </div>
</template>
<script>
export default {
  name: "tab-item",
  props: {
    index: {
      type: Number,
      required: true
    },
    icon: {
      type: String,
      default: ""
    },
    title: {
      type: String,
      default: ""
    },
    dot: {
      type: String,
      default: "0"
    },
    needNum: {
      type: Boolean,
      default: true
    },
    selected: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
    }
  },
  methods: {
    setNum (num) {
      if (num <= 0) {
        this.dot = ""
      } else {
        this.dot = num + ""
      }
    },
    onTabItemClick () {
      var params = {
        index: this.index
      }
      this.$emit("tabItemOnClick", params)
    }
  },
  watch: {
    selected: function (val) {
      this.toast("selected: " + this.selected + ", " + val)
    }
  }
}
</script>

<style>
  .bar-item {
    background-color: -sharpafddff;
    flex: 1;
  }
  .text, .icon {
    color: -sharp666666;
    text-align: center;
  }
  .iconfont {
    font-family: iconfont;
  }
  .icon {
    padding-top: 14px;
    font-size: 38px;
  }
  .text {
    font-size: 22px;
    padding-top: 2px;
  }
  .active {
    color: -sharpb4282d
  }
  .notice {
    position: absolute;
    top: 10px;
    right: 30px;
    width: 30px;
    height: 30px;
    border-radius: 100%;
    font-size: 26px;
    line-height: 30px;;
    text-align: center;
    color: -sharpffffff;
    background-color: -sharpff0000;
  }
  .dot {
    position: absolute;
    top:15px;
    right: 40px;
    height: 15px;
    width: 15px;
    border-radius: 100%;
    background-color: -sharpff0000;
  }
</style>
< H1 > 3. Use < / H1 >
<tab-bar :tabItems="tabs"></tab-bar>

tabs calculates attribute assignments through computed:

computed: {
    tabs: function () {
      return [{
        index: 0,
        icon: "",
        title: "",
        dot: "0",
        needNum: true,
        selected: true
      },
      {
        index: 1,
        icon: "",
        title: "",
        dot: "1",
        needNum: true,
        selected: false
      },
      {
        index: 2,
        icon: "",
        title: "",
        dot: "5",
        needNum: true,
        selected: false
      },
      {
        index: 3,
        icon: "",
        title: "",
        dot: "1",
        needNum: false,
        selected: false
      }]
    }
  }

when the TabBarItem is clicked, the click event can be passed to the parent component and modify the selected property of the selected tabItem, but the style of the modified tabBarItem component is not changed, and the watch is not changed in the child component. I don"t understand why?

Mar.03,2021

Why do you use calculation properties? your calculation properties are not bound to anything under data.
try using data directly


your tabitem component does not transmit data. You only send data to tabbar, and tabbar sends data to the subcomponent tabitem

.
Menu