最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Vue.js using a computed property to show or hide part of a component - Stack Overflow

programmeradmin1浏览0评论

I'm trying to show / hide part of a ponent based on the value in a drop down list. Before moving this part of my form, using a puted property worked just fine. However... I am using two way binding in my ponent and it seems that the puted value of the property I am using is updating too late. Here is the ponent js

Vueponent('system', {

    template: '#system',

    props: ['name', 'count'],

    puted: {
        issummit: function() {
            return this.name === '5a37fda9f13db4987411afd8';
        }
        // audiovideo: function() {
        //     return this.system === params.id.easy3eeg || this.system === params.id.easy3psg || this.system === params.id.essentia;
        // }
    },

    data () {
        return { 
            systemname: this.name,
            systemcount: this.count,
            systemoptions: [
                { text: 'Select One', value: null },
                { text: 'Summit', value:'5a37fda9f13db4987411afd8'},
                { text: 'Essentia', value:'5a37fda1de9e84bb9c44a909'},
                { text: 'Alterna', value:'5a8caadc86dc269de9887b0f'},
                { text: 'Easy III PSG', value:'5a37fe27b1e43d5ca589aee3'},
                { text: 'Easy III EEG', value:'5a37fd9a08a387d4efcf9ddb'},
                { text: 'IOMAX', value:'5a8cab59a1353f170f6e92a4'},
                { text: 'Cascade Pro', value:'5a8cab696f6a77f774e8de7f'}
            ]
        }
    },

    watch: {
        name (name) {
            this.systemname = name;
        },
        count (count) {
            this.systemcount = count;
        }
    },

    methods: {
        updateName: function() {
            this.$emit('update:name', this.systemname);
        },
        updateCount: function() {
            this.$emit('update:count', this.systemcount);
        }
    }
});

Here is the ponent template

    <script type="text/x-template" id="system">
        <b-row>
            <b-form-group class="col-sm" label="Count">
                <b-form-input type="number" @change="updateCount" required v-model="systemcount" class="col-sm"></b-form-input>
            </b-form-group>
            <b-form-group class="col-sm" label="System">
                <b-form-select @change="updateName" :options="systemoptions" required v-model="systemname"></b-form-select>
            </b-form-group>

            <!-- Summit Options -->
            <template v-if="issummit">
                <b-form-group class="col-sm" label="Channels">
                    <b-form-input type="number" required v-model="summitchannels"></b-form-input>
                </b-form-group>
                <b-form-group label="Accessories">
                    <b-form-checkbox-group v-model="summitaccessories" :options="summitoptions">
                    </b-form-checkbox-group>
                </b-form-group>
            </template> 

        </b-row>
    </script>
    <script src="scripts/system.js"></script>

And here is the template in use

<system v-for="system in systems"
    :name.sync="system.name"
    :count.sync="system.count">
</system>

The puted value does update... however the problem is that it seems to update after it is used to determine the rendering. If I select "Summit" in my drop down, I would expect the hidden part of my ponent to show, that its not until I select something else that it is then shown... the second time I make a selection the puted value from the previous attempt is used.

EDIT Per some suggestions I edited the select to use a regular DOM object and this fixed the issue. However, this only became an issue when I moved this over to a template... everything worked peachy before... any ideas?

<div role="group" class="col-sm b-form-group form-group">
    <label class="col-form-label pt-0">System</label>
    <div>
        <select @change="updateName" class="form-control custom-select" required v-model="systemname">
            <option v-for="o in systemoptions" :value="o.value">{{o.text}}</option>
        </select>
    </div>
</div>

I'm trying to show / hide part of a ponent based on the value in a drop down list. Before moving this part of my form, using a puted property worked just fine. However... I am using two way binding in my ponent and it seems that the puted value of the property I am using is updating too late. Here is the ponent js

Vue.ponent('system', {

    template: '#system',

    props: ['name', 'count'],

    puted: {
        issummit: function() {
            return this.name === '5a37fda9f13db4987411afd8';
        }
        // audiovideo: function() {
        //     return this.system === params.id.easy3eeg || this.system === params.id.easy3psg || this.system === params.id.essentia;
        // }
    },

    data () {
        return { 
            systemname: this.name,
            systemcount: this.count,
            systemoptions: [
                { text: 'Select One', value: null },
                { text: 'Summit', value:'5a37fda9f13db4987411afd8'},
                { text: 'Essentia', value:'5a37fda1de9e84bb9c44a909'},
                { text: 'Alterna', value:'5a8caadc86dc269de9887b0f'},
                { text: 'Easy III PSG', value:'5a37fe27b1e43d5ca589aee3'},
                { text: 'Easy III EEG', value:'5a37fd9a08a387d4efcf9ddb'},
                { text: 'IOMAX', value:'5a8cab59a1353f170f6e92a4'},
                { text: 'Cascade Pro', value:'5a8cab696f6a77f774e8de7f'}
            ]
        }
    },

    watch: {
        name (name) {
            this.systemname = name;
        },
        count (count) {
            this.systemcount = count;
        }
    },

    methods: {
        updateName: function() {
            this.$emit('update:name', this.systemname);
        },
        updateCount: function() {
            this.$emit('update:count', this.systemcount);
        }
    }
});

Here is the ponent template

    <script type="text/x-template" id="system">
        <b-row>
            <b-form-group class="col-sm" label="Count">
                <b-form-input type="number" @change="updateCount" required v-model="systemcount" class="col-sm"></b-form-input>
            </b-form-group>
            <b-form-group class="col-sm" label="System">
                <b-form-select @change="updateName" :options="systemoptions" required v-model="systemname"></b-form-select>
            </b-form-group>

            <!-- Summit Options -->
            <template v-if="issummit">
                <b-form-group class="col-sm" label="Channels">
                    <b-form-input type="number" required v-model="summitchannels"></b-form-input>
                </b-form-group>
                <b-form-group label="Accessories">
                    <b-form-checkbox-group v-model="summitaccessories" :options="summitoptions">
                    </b-form-checkbox-group>
                </b-form-group>
            </template> 

        </b-row>
    </script>
    <script src="scripts/system.js"></script>

And here is the template in use

<system v-for="system in systems"
    :name.sync="system.name"
    :count.sync="system.count">
</system>

The puted value does update... however the problem is that it seems to update after it is used to determine the rendering. If I select "Summit" in my drop down, I would expect the hidden part of my ponent to show, that its not until I select something else that it is then shown... the second time I make a selection the puted value from the previous attempt is used.

EDIT Per some suggestions I edited the select to use a regular DOM object and this fixed the issue. However, this only became an issue when I moved this over to a template... everything worked peachy before... any ideas?

<div role="group" class="col-sm b-form-group form-group">
    <label class="col-form-label pt-0">System</label>
    <div>
        <select @change="updateName" class="form-control custom-select" required v-model="systemname">
            <option v-for="o in systemoptions" :value="o.value">{{o.text}}</option>
        </select>
    </div>
</div>
Share Improve this question edited Mar 14, 2018 at 4:38 ferics2 asked Mar 8, 2018 at 6:53 ferics2ferics2 5,4427 gold badges31 silver badges46 bronze badges 2
  • How do pass value to props name? – sfy Commented Mar 8, 2018 at 7:34
  • I believe there are issues with v-if in such use cases when checking dynamic properties – venimus Commented Mar 13, 2018 at 14:40
Add a ment  | 

3 Answers 3

Reset to default 3 +50

I have a minimal reproduction in https://jsfiddle/3vkqLnxq/1/

It works as intended. The change is all b-* tags are changed to dom.

So the most possible cause is that b-form-select has some issue.

You should use getters and setters for puted property data binded.

Something like this:

puted: {
  issummit: {
    // getter
    get: function () {
      return this.name === '5a37fda9f13db4987411afd8';
    },
    // setter
    set: function (newValue) {
      this.systemname = newValue;
    }
  }
}

More:

https://v1.vuejs/guide/puted.html#Computed-Setter

I solved a similar problem with changing the

@change="updateName"

to

@change.native="updateName"

(https://v2.vuejs/v2/guide/ponents.html#Binding-Native-Events-to-Components)

This let me use the "real" direct change event (and not the too late one) which solved my problem.

发布评论

评论列表(0)

  1. 暂无评论