admin管理员组

文章数量:1336732

I've created a simple ponent named DefaultButton. It bases on properties, that are being set up whenever this ponent is being created. The point is that after mounting it, It does not react on changes connected with "defaultbutton", that is an object located in properties

<template>
  <button :class="buttonClass" v-if="isActive" @click="$emit('buttonAction', defaultbutton.id)" >
    {{ this.defaultbutton.text }} 
  </button>
  <button :class="buttonClass" v-else disabled="disabled">
    {{ this.defaultbutton.text }} 
  </button>
</template>


<script>
export default {
  name: "defaultbutton",
  props: {
    defaultbutton: Object
  },
  puted: {
    buttonClass() {
      return `b41ngt ${this.defaultbutton.state}`;
    },
    isActive() {
      return (this.defaultbutton.state === "BUTTON_ACTIVE" || this.defaultbutton.state === "BUTTON_ACTIVE_NOT_CHOSEN");
    }
  }
};
</script>

Having following ponent as a parent one:

<template>
    <div v-if="state_items.length == 2" class="ui placeholder segment">
        {{ this.state_items[0].state }}
        {{ this.state_items[1].state }}
        {{ this.current_active_state }}
      <div class="ui two column very relaxed stackable grid">
        <div class="column">
            <default-button :defaultbutton="state_items[0]" @buttonAction="changecurrentstate(0)"/>
        </div>
        <div class="middle aligned column">
            <default-button :defaultbutton="state_items[1]" @buttonAction="changecurrentstate(1)"/>
        </div>
      </div>
      <div class="ui vertical divider">
        Or
      </div>
    </div>

</template>


<script type="text/javascript">
    import DefaultButton from '../Button/DefaultButton'

    export default {
        name: 'changestatebox',
        data() {
            return {
                current_active_state: 1
            }
        },
        props: {
            state_items: []
        },
        ponents: {
            DefaultButton
        },
        methods: {
            changecurrentstate: function(index) {
                if(this.current_active_state != index) {
                    this.state_items[this.current_active_state].state = 'BUTTON_ACTIVE_NOT_CHOSEN';
                    this.state_items[index].state = 'BUTTON_ACTIVE';
                    this.current_active_state = index;
                }
            },
        },
        mounted: function () {
            this.state_items[0].state = 'BUTTON_ACTIVE';
            this.state_items[1].state = 'BUTTON_ACTIVE_NOT_CHOSEN';
        }
    }

</script>

It clearly shows, using:

{{ this.state_items[0].state }}
{{ this.state_items[1].state }}
{{ this.current_active_state }}

that the state of these items are being changed, but I am unable to see any results on the generated "DefaultButtons". Classes of objects included in these ponents are not being changed.

@edit

I've pletely changed the way of delivering the data. Due to this change, I've abandoned the usage of an array; instead I've used two pletely not related object. The result is the same - class of the child ponent's object is not being

DefaulButton.vue:

<template>
  <button :class="buttonClass" v-if="isActive" @click="$emit('buttonAction', defaultbutton.id)" >
    {{ this.defaultbutton.text }} 
  </button>
  <button :class="buttonClass" v-else disabled="disabled">
    {{ this.defaultbutton.text }} 
  </button>
</template>

<style lang="scss">
  import './DefaultButton.css';
</style>

<script>
export default {
  name: "defaultbutton",
  props: {
    defaultbutton: {
      type: Object,
      default: () => ({
        id: '',
        text: '',
        state: '',
      })
    }
  },
  puted: {
    buttonClass() {
      return `b41ngt ${this.defaultbutton.state}`;
    },
    isActive() {
      return (this.defaultbutton.state === "BUTTON_ACTIVE" ||
        this.defaultbutton.state === "BUTTON_ACTIVE_NOT_CHOSEN");
    }
  }
};
</script>

ChangeStateBox.vue:

<template>
    <div class="ui placeholder segment">
        {{ this.state_first.state }}
        {{ this.state_second.state }}
        {{ this.current_active_state }}
      <div class="ui two column very relaxed stackable grid">
        <div class="column">
            <default-button :defaultbutton="state_first" @buttonAction="changecurrentstate(0)"/>
        </div>
        <div class="middle aligned column">
            <default-button :defaultbutton="state_second" @buttonAction="changecurrentstate(1)"/>
        </div>
      </div>
      <div class="ui vertical divider">
        Or
      </div>
    </div>

</template>

<script type="text/javascript">
    import DefaultButton from '../Button/DefaultButton'

    export default {
        name: 'changestatebox',
        data() {
            return {
                current_active_state: 1
            }
        },
        props: {
            state_first: {
                type: Object,
                default: () => ({
                  id: '',
                  text: ''  
                })
            },
            state_second: {
                type: Object,
                default: () => ({
                  id: '',
                  text: ''  
                })
            },
        },
        ponents: {
            DefaultButton
        },
        methods: {
            changecurrentstate: function(index) {
                if(this.current_active_state != index) {
                    if(this.current_active_state == 1){

                        this.$set(this.state_first, 'state', "BUTTON_ACTIVE_NOT_CHOSEN");
                        this.$set(this.state_second, 'state', "BUTTON_ACTIVE");

                    } else {

                        this.$set(this.state_first, 'state', "BUTTON_ACTIVE");
                        this.$set(this.state_second, 'state', "BUTTON_ACTIVE_NOT_CHOSEN");

                    }
                    this.current_active_state = index;
                }
            },
        },
        created: function () {
            this.state_first.state = 'BUTTON_ACTIVE';
            this.state_second.state = 'BUTTON_ACTIVE_NOT_CHOSEN';
        }
    }
</script>

I've created a simple ponent named DefaultButton. It bases on properties, that are being set up whenever this ponent is being created. The point is that after mounting it, It does not react on changes connected with "defaultbutton", that is an object located in properties

<template>
  <button :class="buttonClass" v-if="isActive" @click="$emit('buttonAction', defaultbutton.id)" >
    {{ this.defaultbutton.text }} 
  </button>
  <button :class="buttonClass" v-else disabled="disabled">
    {{ this.defaultbutton.text }} 
  </button>
</template>


<script>
export default {
  name: "defaultbutton",
  props: {
    defaultbutton: Object
  },
  puted: {
    buttonClass() {
      return `b41ngt ${this.defaultbutton.state}`;
    },
    isActive() {
      return (this.defaultbutton.state === "BUTTON_ACTIVE" || this.defaultbutton.state === "BUTTON_ACTIVE_NOT_CHOSEN");
    }
  }
};
</script>

Having following ponent as a parent one:

<template>
    <div v-if="state_items.length == 2" class="ui placeholder segment">
        {{ this.state_items[0].state }}
        {{ this.state_items[1].state }}
        {{ this.current_active_state }}
      <div class="ui two column very relaxed stackable grid">
        <div class="column">
            <default-button :defaultbutton="state_items[0]" @buttonAction="changecurrentstate(0)"/>
        </div>
        <div class="middle aligned column">
            <default-button :defaultbutton="state_items[1]" @buttonAction="changecurrentstate(1)"/>
        </div>
      </div>
      <div class="ui vertical divider">
        Or
      </div>
    </div>

</template>


<script type="text/javascript">
    import DefaultButton from '../Button/DefaultButton'

    export default {
        name: 'changestatebox',
        data() {
            return {
                current_active_state: 1
            }
        },
        props: {
            state_items: []
        },
        ponents: {
            DefaultButton
        },
        methods: {
            changecurrentstate: function(index) {
                if(this.current_active_state != index) {
                    this.state_items[this.current_active_state].state = 'BUTTON_ACTIVE_NOT_CHOSEN';
                    this.state_items[index].state = 'BUTTON_ACTIVE';
                    this.current_active_state = index;
                }
            },
        },
        mounted: function () {
            this.state_items[0].state = 'BUTTON_ACTIVE';
            this.state_items[1].state = 'BUTTON_ACTIVE_NOT_CHOSEN';
        }
    }

</script>

It clearly shows, using:

{{ this.state_items[0].state }}
{{ this.state_items[1].state }}
{{ this.current_active_state }}

that the state of these items are being changed, but I am unable to see any results on the generated "DefaultButtons". Classes of objects included in these ponents are not being changed.

@edit

I've pletely changed the way of delivering the data. Due to this change, I've abandoned the usage of an array; instead I've used two pletely not related object. The result is the same - class of the child ponent's object is not being

DefaulButton.vue:

<template>
  <button :class="buttonClass" v-if="isActive" @click="$emit('buttonAction', defaultbutton.id)" >
    {{ this.defaultbutton.text }} 
  </button>
  <button :class="buttonClass" v-else disabled="disabled">
    {{ this.defaultbutton.text }} 
  </button>
</template>

<style lang="scss">
  import './DefaultButton.css';
</style>

<script>
export default {
  name: "defaultbutton",
  props: {
    defaultbutton: {
      type: Object,
      default: () => ({
        id: '',
        text: '',
        state: '',
      })
    }
  },
  puted: {
    buttonClass() {
      return `b41ngt ${this.defaultbutton.state}`;
    },
    isActive() {
      return (this.defaultbutton.state === "BUTTON_ACTIVE" ||
        this.defaultbutton.state === "BUTTON_ACTIVE_NOT_CHOSEN");
    }
  }
};
</script>

ChangeStateBox.vue:

<template>
    <div class="ui placeholder segment">
        {{ this.state_first.state }}
        {{ this.state_second.state }}
        {{ this.current_active_state }}
      <div class="ui two column very relaxed stackable grid">
        <div class="column">
            <default-button :defaultbutton="state_first" @buttonAction="changecurrentstate(0)"/>
        </div>
        <div class="middle aligned column">
            <default-button :defaultbutton="state_second" @buttonAction="changecurrentstate(1)"/>
        </div>
      </div>
      <div class="ui vertical divider">
        Or
      </div>
    </div>

</template>

<script type="text/javascript">
    import DefaultButton from '../Button/DefaultButton'

    export default {
        name: 'changestatebox',
        data() {
            return {
                current_active_state: 1
            }
        },
        props: {
            state_first: {
                type: Object,
                default: () => ({
                  id: '',
                  text: ''  
                })
            },
            state_second: {
                type: Object,
                default: () => ({
                  id: '',
                  text: ''  
                })
            },
        },
        ponents: {
            DefaultButton
        },
        methods: {
            changecurrentstate: function(index) {
                if(this.current_active_state != index) {
                    if(this.current_active_state == 1){

                        this.$set(this.state_first, 'state', "BUTTON_ACTIVE_NOT_CHOSEN");
                        this.$set(this.state_second, 'state', "BUTTON_ACTIVE");

                    } else {

                        this.$set(this.state_first, 'state', "BUTTON_ACTIVE");
                        this.$set(this.state_second, 'state', "BUTTON_ACTIVE_NOT_CHOSEN");

                    }
                    this.current_active_state = index;
                }
            },
        },
        created: function () {
            this.state_first.state = 'BUTTON_ACTIVE';
            this.state_second.state = 'BUTTON_ACTIVE_NOT_CHOSEN';
        }
    }
</script>
Share Improve this question edited Dec 3, 2018 at 14:54 Artur Drożdżyk asked Dec 3, 2018 at 13:09 Artur DrożdżykArtur Drożdżyk 6151 gold badge6 silver badges20 bronze badges 2
  • You have declared your prop wrong. defaultbutton should be an object, and required should be one entry in that object. – Roy J Commented Dec 3, 2018 at 13:57
  • Well, I've changed it now in such a way, that required does not exist anymore, but the result it the same - It seems that the defaultbutton works like is not referenced to the parent's data – Artur Drożdżyk Commented Dec 3, 2018 at 14:05
Add a ment  | 

3 Answers 3

Reset to default 2

You're declaring props wrong. It is either an array of prop names or it is an object with one entry for each prop declaring its type, or it is an object with one entry for each prop declaring multiple properties.

You have

    props: {
        state_items: []
    },

but to supply a default it should be

    props: {
        state_items: {
            type: Array,
            default: []
        }
    },

But your problem is most likely that you're mutating state_items in such a way that Vue can't react to the change

Your main problem is the way you are changing the button state, according with Array change detection vue can't detect mutations by indexing.

Due to limitations in JavaScript, Vue cannot detect the following changes to an array:

When you directly set an item with the index, e.g. vm.items[indexOfItem] = newValue When you modify the length of the array, e.g. vm.items.length = newLength

In case someone will be having the same issue:

@Roy J as well as @DobleL were right.

The reason behind this issue was related with the wrong initialization of state objects.

According to the documentation:

Vue cannot detect property addition or deletion. 
Since Vue performs the getter/setter conversion process during instance
initialization, a property must be present in the 
data object in order for Vue to convert it and make it reactive. 

Before reading this sentence, I used to start with following objects as an initial data:

var local_state_first = {
  id: '1',
  text: 'Realized',
};

var local_state_second = {
    id: '2',
    text: 'Active'  
};

and the correct version of it looks like this:

var local_state_first = {
  id: '1',
  text: 'Realized',
  state: 'BUTTON_ACTIVE'
};

var local_state_second = {
  id: '2',
  text: 'Active',
  state: 'BUTTON_ACTIVE'
};

whereas declaring the main ponent as:

<change-state-box :state_first="local_state_first" :state_second="local_state_second" @buttonAction="onbuttonAction"/>

Rest of the code remains the same ( take a look at @edit mark in my main post )

本文标签: javascriptVuejsComputed property not updatingchild componentStack Overflow