【问题标题】:Vue JS Ajax data not populating Vue-Tribute on loadVue JS Ajax 数据在加载时未填充 Vue-Tribute
【发布时间】:2019-01-08 02:21:36
【问题描述】:

我正在使用 Vue Tribute 组件https://github.com/syropian/vue-tribute

当“显示”数据属性设置为 true 时最初加载页面时,我得到“不匹配!”。但是,如果我在页面加载时将“显示”数据属性设置为 false,然后手动将其设置为 true,我将按预期获得两个结果。我试图将函数调用包装在“已安装、创建和更新”内,但我收到了相同的结果。我正在使用setTimeout() 来模拟我用来加载远程数据的 AJAX 调用。

var app = new Vue({
  el: '#myApp',
  data: function() {
    return {
      show: true,
      tributeOptions: {
        values: []
      }
    };
  },
  mounted: function() {
    this.getTributeOptions();
  },
  methods: {
    getTributeOptions: function(resource) {
      var vm = this;
      setTimeout(function() {
         vm.tributeOptions.values = [
            { key: 'Phil Heartman', value: 'pheartman' },
            { key: 'Gordon Ramsey', value: 'gramsey' }
          ];
      }, 500)
    }
  }
})

<div id="myApp">
  <div v-if="show">
    <vue-tribute :options="tributeOptions">
      <input type="text" placeholder="@" />
    </vue-tribute>
  </div>
</div>

https://codepen.io/anon/pen/QBQaNB?editors=1111

【问题讨论】:

    标签: javascript vue.js


    【解决方案1】:

    检查Vue Tribute source code at Github,您会看到它只会在mounted() 中创建一个new Tribute 实例。这意味着即使您在安装后更改 props=options 的值,也不会影响任何内容。

    所以一种解决方案是确保在挂载之前准备好贡品选项,因此更新created() 中的值将是一个想法。

    var app = new Vue({
      el: '#myApp',
      data: function() {
        return {
          tributeOptions: {
            values: []
          }
        };
      },
      created: function () {
       this.tributeOptions.values = [
          { key: 'Phil Heartman', value: 'pheartman' },
          { key: 'Gordon Ramsey', value: 'gramsey' }
        ]
      },
      mounted: function() {
        //this.getTributeOptions();
      },
      methods: {
        getTributeOptions: function(resource) {
          var vm = this;
          setTimeout(function() {
             vm.tributeOptions.values = [
                { key: 'Phil Heartman', value: 'pheartman' },
                { key: 'Gordon Ramsey', value: 'gramsey' }
              ];
          }, 500)
        }
      }
    })
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-tribute"></script>
    <div id="myApp">
        <vue-tribute :options="tributeOptions">
          <input type="text" placeholder="@" />
        </vue-tribute>
    </div>

    另一种解决方案是在 Github 中下载 Vue Tribute 的源代码,然后自己实现update Tribute instance

    更新:创建实现update Tribute optionsone pull request

    第三种解决方案是每次tributeOptions 更新后通过绑定不同的键强制重新挂载

    就像下面的演示。

    var app = new Vue({
      el: '#myApp',
      data: function() {
        return {
          tributeOptions: {
            values: []
          },
          tributeKey: 0
        };
      },
      mounted: function() {
        this.getTributeOptions();
      },
      methods: {
        getTributeOptions: function(resource) {
          var vm = this;
          setTimeout(function() {
             vm.tributeOptions.values = [
                { key: 'Phil Heartman', value: 'pheartman' },
                { key: 'Gordon Ramsey', value: 'gramsey' }
              ];
              vm.tributeKey+=1
          }, 500)
        }
      }
    })
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-tribute"></script>
    <div id="myApp">
        <vue-tribute :options="tributeOptions" :key="tributeKey">
          <input type="text" placeholder="@" />
        </vue-tribute>
    </div>

    【讨论】:

    • @Yamaha32088 我刚刚创建了one pull request,它实现了“更新致敬选项”。你可以拿那个试试看。
    【解决方案2】:

    虽然您上面的解决方法可能会奏效,但问题在于您使用的库 在https://github.com/syropian/vue-tribute/blob/master/src/index.js#L19

    mounted() {
      const $el = this.$slots.default[0].elm;
    
      this.tribute = new Tribute(this.options);
    ...
    }
    

    options 值在mounted() 中只使用一次,并且没有用于在选项更改时更新值的处理程序。

    更好的方法是watch 更改this.options,并分别更新组件内的值。

    【讨论】:

      【解决方案3】:

      我找到了这个问题的答案:Vuejs mount the child components only after data has been loaded

      更新代码:

      var app = new Vue({
        el: '#myApp',
        data: function() {
          return {
            userDataLoaded: false,
            tributeOptions: {
              values: []
            }
          };
        },
        mounted: function() {
          this.getTributeOptions();
        },
        methods: {
          getTributeOptions: function(resource) {
            var vm = this;
            setTimeout(function() {
               vm.tributeOptions.values = [
                  { key: 'Phil Heartman', value: 'pheartman' },
                  { key: 'Gordon Ramsey', value: 'gramsey' }
                ];
              vm.dataLoaded = true;
            }, 500)
          }
        }
      })
      
      <div id="myApp">
        <template>
          <template v-if="dataLoaded">
            <vue-tribute :options="tributeOptions">
              <input type="text" placeholder="@" />
            </vue-tribute>
          </template>
        </template>
      </div>
      

      【讨论】:

      • 实际上你所做的是重建(重新安装)v-if 中的组件。最好的方法应该是给vue-tribute添加一个观察者,然后观察options,如果发生变化,删除旧实例然后创建新实例。那么父组件就不需要关心 force-remount 等了。
      猜你喜欢
      • 2022-12-13
      • 2021-04-22
      • 1970-01-01
      • 2017-06-19
      • 1970-01-01
      • 2017-03-31
      • 2018-10-24
      • 1970-01-01
      • 2020-12-12
      相关资源
      最近更新 更多