首页 > 解决方案 > 更新不相关的 Vue.js 变量导致模板中的输入值消失

问题描述

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

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

该功能正在查找“代理”,然后让用户知道已找到多少条记录以及他/她是否想查看它们。如果用户单击“查看”链接,则会向他们显示一个引导模式,向他们显示记录,以便他们可以选择一个。

这是我已经尝试过的:

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

模板:

<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();
                });
            });

        }
    }

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

对解决方案有任何想法吗?我错过了一些明显和愚蠢的东西吗?

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

渲染组件:

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

标签: javascriptvue.jsbootstrap-modal

解决方案


更改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>


推荐阅读