更新不相关的 Vue.js 变量导致模板中的输入值消失

Updating unrelated Vue.js variable causing input values in template to disappear

我的单文件 Vue 组件出现一个奇怪的问题,当我更新一个不相关的变量(Vue.js 变量)时,我所有的输入(我输入的内容,而不是元素本身)都消失了.

我已经使用 Vue 单文件组件几个月了,但我从未 运行 遇到过这样的事情。这是奇怪的部分,变量按预期成功更新,但如果我在模板中包含变量,那么所有输入都会消失。

该功能正在查找 'agents',然后让用户知道找到了多少条记录以及 he/she 是否要查看它们。如果用户单击 "View" link,则会向他们显示 bootstrap 模式,向他们显示记录,以便他们可以 select 一个。

这是我已经尝试过的方法:

  1. 从输入中删除所有 ID 并仅使用 refs="" 获取值。
  2. 更改 'agents' 变量名。以为它可能与一些流氓全球或其他东西发生冲突。
  3. 仔细检查了父组件和该组件没有被重新渲染。我通过在 mounted() 函数中放置 console.log() 注释来做到这一点,正如预期的那样,它只渲染一次。
  4. 使用 Vue 开发工具扩展查看密钥,以确保密钥未被更改。
  5. setTimeout(()=>{},5000) 中执行了 searchAgent() 函数,看看我对 _.debounce 的使用是否导致了问题。
  6. 使用 jquery 从输入而不是引用中获取值。
  7. 将新记录分配给局部变量 agentsArray,然后将其传递给一个函数,该函数将其分配给 vue 变量 'agents'(它基本上是一个不必要的更长的路径,但我想为什么不尝试它)
  8. 仔细检查了我对 'this' 的所有使用,以确保我没有不小心使用错误的 this 并导致一些未知错误。
  9. 使用 V 模型,但使用它没有帮助,因为我仍然必须在模板中的模态内包含 'agents'。
  10. 仅在'agents' 不是空数组后,使用v-if 语句在模板中呈现模态HTML。
  11. 更新:根据建议,从 mounted() 函数内部的 $(document).ready() 内部删除了该函数。

模板:

<template>
    <div class="Q mb-0">
        <a href="" id="help"><i class="far fa-question-circle"></i></a>
        <center>
            <p class="display-1">{{title}}</p>
            <a href="#/" class="SkipStepStyle">{{prefix}} is Representing Themselves Skip This Step.</a>
            <div id="searchResults" class="hidden" style="margin-top:5px;">
                <a id="searchResultsText" class="SkipStepStyle"></a>
                <a
                        id="viewSearchResults"
                        style="font-weight: bold;"
                        class="hidden SkipStepStyle"
                        v-on:click="displayAgents"
                >
                    View
                </a>
            </div>
            <form class="mt-2 BuyerSellerAgentInfo">
                <div class="form-row">
                    <div class="form-group col-md-6">
                        <input
                                ref="NameFirst"
                                type="text"
                                :name="prefix+'sAgent_NameFirst'"
                                placeholder="FIRST NAME"
                                class="AnswerChoice"
                                :value="currentAnswers[prefix+'sAgent_NameFirst'].Answer"
                        >
                    </div>
                    <div class="form-group col-md-6">
                        <input
                                ref="NameLast"
                                type="text"
                                :name="prefix+'sAgent_NameLast'"
                                placeholder="LAST NAME"
                                class="AnswerChoice"
                                :value="currentAnswers[prefix+'sAgent_NameLast'].Answer"
                        >
                    </div>
                </div>
                <div class="form-row">
                    <div class="form-group col-md-6">
                        <input
                                ref="Email"
                                type="text"
                                :name="prefix+'sAgent_Email'"
                                placeholder="EMAIL ADDRESS"
                                class="AnswerChoice"
                                :value="currentAnswers[prefix+'sAgent_Email'].Answer"
                        >
                    </div>
                    <div class="form-group col-md-6">
                        <input
                                ref="Phone"
                                type="text"
                                :name="prefix+'sAgent_Phone'"
                                maxlength="14"
                                placeholder="PHONE #"
                                class="AnswerChoice"
                                :value="currentAnswers[prefix+'sAgent_Phone'].Answer"
                        >
                    </div>
                </div>
                <div class="form-row">
                    <div class="form-group col-md-6">
                        <input
                                ref="Brokerage"
                                type="text"
                                :name="prefix+'sAgent_Brokerage'"
                                placeholder="AGENT'S BROKERAGE"
                                class="AnswerChoice"
                                :value="currentAnswers[prefix+'sAgent_Brokerage'].Answer"
                        >
                    </div>
                    <div class="form-group col-md-6">
                        <input
                                ref="License"
                                type="text"
                                :name="prefix+'sAgent_License'"
                                placeholder="AGENT'S LICENSE #"
                                class="AnswerChoice"
                                :value="currentAnswers[prefix+'sAgent_License'].Answer"
                        >
                    </div>
                </div>
                <input
                        class="AnswerChoice"
                        type="hidden"
                        :name="prefix+'sAgent_ID'"
                        :value="currentAnswers[prefix+'sAgent_ID'].Answer || '1'"
                >
                <input
                        class="AnswerChoice"
                        type="hidden"
                        :name="prefix+'sAgent_BrokerageID'"
                        :value="currentAnswers[prefix+'sAgent_BrokerageID'].Answer || '1'"
                >
            </form>
        </center>
        <div v-if="agents.length > 0" class="modal" id="AgentPopup">
            <div class="vertical-alignment-helper">
                <div class="modal-dialog vertical-align-center">
                    <div class="modal-content">
                        <div class="modal-body">
                            <center>
                                <h5 class="d-inline-block mb-3">Select {{prefix}}'s Agent:</h5>
                            </center>
                            <button v-on:click="displayCategories" type="button" class="close shadow" data-dismiss="modal">&times;</button>
                            <ul>
                                <li v-for="agent in agents">{{ agent.NameFull || agent.NameFirst+' '+agent.NameLast }}</li>
                                <li class="border-0">{{prefix}}’s agent is not in this list</li>
                            </ul>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</template>

脚本:

import _ from 'lodash';
    export default {
        name: "AgentInformation",
        props: {
            friendlyIndex: {
                type: String,
                default: null,
            },
            title: {
                type: String,
                default: null,
            },
            answerChoices:{
                type: Array,
                default: () => []
            },
            currentAnswers: {
                type: Object,
                default: () => {},
            },
            prefix: {
                type: String,
                default: '',
            },
            token: {
                type: String,
                default: '',
            },
        },
        methods: {
            debounceFunction(func,timer){
                let vueObject = this;
                return _.debounce(()=>{
                    vueObject[func]();
                },timer);
            },
            displayCategories(){
                $('.categories').show();
            },
            displayAgents(){
                $('.categories').hide();
                $('#AgentPopup').modal({backdrop:'static',keyboard:false});
            },
            searchAgent() {
                let vueObject = this;
                console.log('calling searchAgent()');
                let agentSearchRoute = correctVuexRouteURL(vueObject.$store.getters.routeName('search.agent'));
                if (!agentSearchRoute) genericError('Agent Search Route Not Found. Error code: a-s-001');
                else
                {
                    let dataObject = {
                        NameFirst: this.$refs.NameFirst.value,
                        NameLast: this.$refs.NameLast.value,
                        Email: this.$refs.Email.value,
                        Phone: this.$refs.Phone.value,
                        License: this.$refs.License.value,
                        _token: this.token,
                    };

                    console.log(dataObject);

                    vueObject.$http.post(agentSearchRoute, dataObject).then((r) => {
                        let status = r.body.status;
                        if (status == 'success')
                        {
                            vueObject.agents            = r.body.agents;
                            let searchResultsContainer  = $('#searchResults');
                            let searchResultsText       = $('#searchResultsText');
                            let viewSearchResultsLink   = $('#viewSearchResults');
                            let agentCount              = 
   vueObject.agents.length;
                            searchResultsContainer.removeClass('hidden');
                            if(agentCount > 0)
                            {
                                let rText = agentCount > 1 ? 'records' : 
   'record';
                                searchResultsText.text(agentCount+' '+rText+' 
   found.');
                                viewSearchResultsLink.removeClass('hidden');
                            }
                            else
                            {
                                if (!viewSearchResultsLink.hasClass('hidden'))
                                    viewSearchResultsLink.addClass('hidden');
                                searchResultsText.text('No records found.');
                            }
                        }
                    });
                }
            },
        },
        data(){
            return {
                agents: [],
            }
        },
        mounted() {
            let vueObject = this;
            console.log('mounted');
            $(document).ready(function(){
                $('#phone').mask('(###)-###-####');
                $('.AnswerChoice').on('input', () => {
                    let searchAgent = 
  vueObject.debounceFunction('searchAgent',500);
                    searchAgent();
                });
            });

        }
    }

问题似乎是模板不喜欢将 'agents' 变量放在其中。当我删除模态容器或仅删除对 'agents' 的引用时,它会按预期工作。如果我更改变量名,它不会解决问题。

对解决方案有什么想法吗?我是否遗漏了一些明显和愚蠢的东西?!

编辑:我忘了添加一些东西,我认为这不会以任何方式影响它,但值得一提。该组件在父级内部动态呈现。

渲染组件:

<component
                            v-for="(component,i) in selectedView"
                            :is="component['Component']"
                            v-bind="bindAttributes(component)"
                            :key="component.ID"
                    >
                    </component>

更改agents将导致整个模板重新运行。不仅仅是提到 agents 的位,该模板中的所有内容都将更新。

当用户键入您的 <input> 元素之一时,您不会将该值存储在任何地方。你有一个 :value 来插入值,但是当值改变时你没有更新它。结果将是,当 Vue 重新渲染所有内容时,它将跳回到其原始值。

您应该能够通过将 currentAnswers 中的初始值设置为非空值来确认这一点。您应该会发现,每当 agents 更改时,它都会跳回到那些初始值。

解决方案只是确保您的数据与用户输入的内容保持同步。通常这会使用 v-model 来完成,但在这种情况下这有点棘手,因为您使用的是支持值,你不应该真正改变一个支持(单向数据流)。相反,您应该使用事件将所需的更改传达给拥有该数据的任何组件。

这里有一个简单的测试用例来单独演示问题:

new Vue({
  el: '#app',
  
  data () {
    return {
      count: 0,
      value: 'initial'
    }
  }
})
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>
<div id="app">
  <input :value="value">
  <button @click="count++">Click count: {{ count }}</button>
</div>