【问题标题】:Vue watch two linked input fields for user input onlyVue watch 两个链接的输入字段仅用于用户输入
【发布时间】:2020-09-11 05:27:46
【问题描述】:

我有两个输入字段,想法是两者都可以更改另一个的值。

如果在 level 字段中输入 1 - 200 的值,Vue 会查找 level 并返回该 level 的点数并将它们输入到 points 字段中。

但我也希望反过来发生,所以如果用户在点数字段中输入他们拥有的点数,Vue 会查找点数并返回与该点数相关的级别。

除了 Vue 会进行双重计算,因为它正在监视两个字段,所以如果我在 points 字段中输入 300,它会正确返回级别 4,但是 Vue 会检测到 level 字段中的变化,然后将点更改为 250。

我只希望 Vue 检测用户何时更改字段,而不是在更改字段后重新计算。

我希望这是有道理的,这很难解释。

axios 请求返回的数据样本:-

[
    {"level":1,"points":0},
    {"level":2,"points":72},
    {"level":3,"points":175},
    {"level":4,"points":250},
    {"level":5,"points":401,}
]

一个简化的 vue 组件来演示我的工作:-

<template>
    <div>
        <div class="card-body">
            <form>
                <div class="row">
                    <div class="col">
                        <div class="form-group">
                            <input type="text" v-model="currentLevel" class="form-control">
                        </div>
                        <div class="form-group">
                            <input type="text" v-model="currentPoints" class="form-control">
                        </div>
                    </div>
                </div>
            </form>
        </div>
    </div>   
</template>

<script>
    export default { 
        data() {
            return {
                currentLevel: 1,
                currentPoints: 0,
                pointsTable: []
            }
        },
        mounted() {
            axios.get('/api/points').then(this.fetchPointsTable);
        },
        methods: {
            fetchPointsTable({data}) {
                this.pointsTable = data;
            }
        },
        watch: {
            currentLevel: function() { 
                const result = this.pointsTable.find( ({ level }) => level === parseInt(this.currentLevel) );

                this.currentPoints = result.experience;
            },
            currentPoints: function() {
                var levels = [];
                var goal = this.currentXp;

                var closest = this.xpTable.reduce(function(prev, curr) {
                    if (curr.points <= goal) {
                        levels = curr.level;
                    }
                    return Math.max(levels);
                });

                this.currentLevel = closest;
            }
        }
    }
</script>

【问题讨论】:

    标签: javascript vue.js


    【解决方案1】:

    在这种情况下,您正在寻找change 事件,该事件将在用户 更改输入值时特别激活。

    来自MDN(强调我的):

    当用户提交对元素的value 的更改时,会为&lt;input&gt;&lt;select&gt;&lt;textarea&gt; 元素触发更改事件。与input 事件不同,change 事件不一定会在每次更改元素的value 时触发

    这意味着每当用户更改任一输入中的值时,change 事件将触发,触发关联的方法并更新另一个框。这种情况不会受到任何干扰,因为当以编程方式更新其值时,另一个输入不会触发 change 事件(与跟踪所有值更改的观察者不同),因此不会触发其关联的方法。

    您的示例的调整版本:

    <template>
        <div>
            <div class="card-body">
                <form>
                    <div class="row">
                        <div class="col">
                            <div class="form-group">
                                <input
                                    type="text"
                                    v-model="currentLevel" 
                                    class="form-control" 
                                    @change="updateCurrentPoints"
                                >
                            </div>
                            <div class="form-group">
                                <input
                                    type="text"
                                    v-model="currentPoints"
                                    class="form-control"
                                    @change="updateCurrentLevel"
                                >
                            </div>
                        </div>
                    </div>
                </form>
            </div>
        </div>   
    </template>
    
    <script>
        export default { 
            data() {
                return {
                    currentLevel: 1,
                    currentPoints: 0,
                    pointsTable: []
                }
            },
            mounted() {
                axios.get('/api/points').then(this.fetchPointsTable);
            },
            methods: {
                fetchPointsTable({data}) {
                    this.pointsTable = data;
                },
                updateCurrentPoints() { // contents of currentLevel watcher
                    const result = this.pointsTable.find( ({ level }) => level === parseInt(this.currentLevel) );
    
                    this.currentPoints = result.experience;
                },
                updateCurrentLevel() { // contents of currentPoints watcher
                    var levels = [];
                    var goal = this.currentXp;
    
                    var closest = this.xpTable.reduce(function(prev, curr) {
                        if (curr.points <= goal) {
                            levels = curr.level;
                        }
                        return Math.max(levels);
                    });
    
                    this.currentLevel = closest;
                },
            }
        }
    </script>
    

    【讨论】:

    • 感谢您的回答,这可行,但是在提交更改之前它不会触发事件,即用户必须从该输入字段更改焦点。我希望有一个解决方案,可以让我在不将焦点从输入字段上移开的情况下检测到任何变化
    • 忘记最后一条评论,你的回答确实提到了这个Unlike the input event, the change event所以我把@change="updateCurrentLevel"切换到@input="updateCurrentLevel"
    猜你喜欢
    • 1970-01-01
    • 2015-02-21
    • 1970-01-01
    • 1970-01-01
    • 2018-10-30
    • 1970-01-01
    • 2020-09-12
    • 2020-09-09
    • 2016-01-31
    相关资源
    最近更新 更多