【问题标题】:Vue.js v-if not reacting to variable changeVue.js v-if 对变量变化没有反应
【发布时间】:2017-01-31 14:39:31
【问题描述】:

我正在玩 vue.js,但在正确使用 v-if 方面有些困难。

我正在尝试在模板内进行条件模板渲染。在created 方法中,变量isloaded 设置为true,这应该会导致模板重新渲染并让“正在加载数据”消息消失。

但是,日志表明,2s 的延迟有效,因此达到了回调,但看起来我没有正确更新数据变量。

我已经尝试了几件事,现在我将“true/false”更改为字符串,以便更接近官方主页上给出的示例,但仍然没有成功。我希望你能帮助我,因此提前非常感谢。

请在下面找到有趣的coden-ps:

var step1 = Vue.component('step1', {
  template: '#step1',
  data: function() {
    return {
      accounts: [],
      isloaded: 'false'
    }
  },
  created: function() {
    console.log("created");
    setTimeout(function() {
      console.log("times over");
      this.isloaded = 'true';
      this.accounts = [{
        id: 1234,
        name: "germany"
      }];
    }, 2000);
  },
  methods: {
    loaded: function() {
      console.log(this.isloaded === 'true');
      return this.isloaded === 'true';
    }
  }

})

new Vue({
  el: '#main'
});
<script src="https://unpkg.com/vue@2.1.10/dist/vue.js"></script>
<template id="step1">
  <div class="step1">
    <h1>Welcome please choose your account:</h1>
    <template v-if="isloaded === 'false'">
      <p>Loading Data</p>
    </template>
    <template v-else>
      <select>
        <template v-for="account in accounts">
          <option :value="account.id">{{ account.name }}</option>
        </template>
      </select>
    </template>

  </div>
</template>

<div id="main">
  <step1></step1>
</div>

【问题讨论】:

  • 这不会解决您的问题,但可能会阻止进一步的问题。由于isLoaded 是一个布尔值,你应该这样对待它。 'true' 和 'false' 应该只是 truefalse

标签: javascript vue.js


【解决方案1】:

有时这可能是由模板中的错误引起的。例如,我在v-else 案例中使用了未定义的方法,这就是为什么看起来v-if 没有反应性。去掉v-else中未定义的方法或定义该方法即可解决问题。

注意:即使在实例上定义了方法,也请务必检查您发送的参数是否有效。

new Vue({
  el: '#app',
  data(){
    return {
      isLoading: true
    }
  },
  mounted() {
    setTimeout(() => {
      this.isLoading = false
    }, 2000)
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <template v-if="isLoading">
    Loading...
  </template>
  <template v-else>
    loading finished
    
    {{ an_undefined_method() }}
  </template>
</div>

【讨论】:

    【解决方案2】:

    来自Vue.js - Reactivity in Depth docs

    例如,当您设置 vm.someData = 'new value' 时,组件 不会立即重新渲染。它将在下一个“滴答”中更新, 当队列被刷新时。

    随着数据在创建的生命周期钩子中发生变化,我们需要使用$nextTick 更多信息可以在上面的页面中找到。

    var step1 = Vue.component('step1', {
      template: '#step1',
      data: function() {
        return {
          accounts: [],
          isloaded: false
        }
      },
      created: function() {
        console.log("created");
        var self = this;
        setTimeout(function() {
          console.log("times over");
          self.$nextTick(function() {
            self.isloaded = true;
            self.accounts = [{
              id: 1234,
              name: "germany"
            }];
          })
    
        }, 2000);
      }
    
    })
    
    new Vue({
      el: '#main'
    });
    <script src="https://unpkg.com/vue@2.1.10/dist/vue.js"></script>
    <template id="step1">
      <div class="step1">
        <h1>Welcome please choose your account:</h1>
        <template v-if="isloaded===false">
          <p>Loading Data</p>
        </template>
        <template v-else>
          <select>
            <template v-for="account in accounts">
              <option :value="account.id">{{ account.name }}</option>
            </template>
          </select>
        </template>
    
      </div>
    </template>
    
    <div id="main">
      <step1></step1>
    </div>

    但是,如果您将加载数据的代码放在一个方法中,并从created 挂钩中调用该方法。它可以在没有$nextTick 的情况下工作。

    methods: {
        loadData: function() {
            var self = this;
            setTimeout(function() {
                console.log("times over");
                self.isloaded = true;
                self.accounts = [{
                    id: 1234,
                    name: "germany"
                }];
            }, 2000);
        }
    },
    created: function() {
        console.log("created");
        this.loadData();
    }
    

    【讨论】:

      【解决方案3】:

      this 的范围不正确。 function () 语法创建自己的范围。您可以将正确的范围保存在一个 var 中并使用它,如下所示:

      created: function() {
        var that = this
        setTimeout(function() {
          console.log("times over");
          that.isloaded = 'true';
          that.accounts = [{
            id: 1234,
            name: "germany"
          }];
        }, 2000);
      },
      

      或者,您可以使用arrow function,它不会绑定自己的thisargumentssupernew.target

      created: function() {
        setTimeout(() => {
          console.log("times over");
          this.isloaded = 'true';
          this.accounts = [{
            id: 1234,
            name: "germany"
          }];
        }, 2000);
      },
      

      【讨论】:

      【解决方案4】:

      将您的方法更新为只有一个 =,并删除返回。

      methods: {
        loaded: function() {
          console.log(this.isloaded === 'true');
          this.isloaded = 'true';
        }
      } 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-06
        • 2023-01-24
        • 2018-01-20
        • 1970-01-01
        • 2018-12-20
        • 2022-11-02
        • 2021-04-17
        • 1970-01-01
        相关资源
        最近更新 更多