首页 > 解决方案 > 如何将数据传递给 Vue 实例以便反映后续更新?

问题描述

我正在尝试在加载视图并初始化自定义后动态更新 Vue JS 道具。我正在构建一个自定义 Vue 插件并使用道具来传递选项,其中一个是我需要在组件加载后动态更新传递的值的对象,例如:

<div id="app">
  <script>
  var seedData = {
    percent: 50,
    name: 'Smith'
  }
  setInterval(() => {
    seedData = {
      percent: Math.random(),
      name: 'Smith'
    }
  }, 1000)
  </script>
  <offers :parent-data="seedData"></offers>
</div>
Vue.component('offers', {
  template: '<h1>Parent Data: {{ parentData.percent }}</h1>',
  props: {
    parentData: {
      default: () => ({
        percent: 0,
        name: 'John'
      }),
      type: Object
    },
  }
});

// create a new Vue instance and mount it to our div element above with the id of app
var vm = new Vue({
  el: '#app'
});

这将从 加载初始名称/值offersData,但是setInterval不会传递 上的新值。

我尝试在我的自定义 Vue 插件中添加一个观察器,该插件通过它加载,<offers>但这似乎也不起作用:

watch: {
  parentData: function (newVal) {
    this.parentData = newVal
  }
}

更新

以下是我的实现:

代码笔-> https://codepen.io/sts-ryan-holton/pen/VwYNzdZ

标签: javascriptvue.jspluginsvuejs2

解决方案


您的代码存在多个问题

  1. Vue 将内部的所有<div id="app">内容视为模板并进行编译 - 请参阅文档

如果既不存在render函数也不template存在选项,则挂载 DOM 元素的 in-DOM HTML 将被提取为模板。在这种情况下,应使用 Vue 的 Runtime + Compiler 构建。

包括<script>标签有错误。只需尝试包含vue.js(调试构建)而不是vue.min.js(Vue 的最小化生产构建),您就会看到一堆错误(顺便说一句,使用调试构建进行开发总是一个好主意,因为它会为您提供许多有用的错误和警告)

它在产品构建中“以某种方式工作”的事实(即初始值显示在页面上)并不意味着它受到支持......

  1. 所以里面<div id="app">是Vue的模板。正如我之前在评论中所说,模板引用的所有数据都必须在 Vue 实例的上下文中。你不能将一些全局变量传递给 props。所以搬出<script>去无济于事<div id="app">

[Vue 警告]:属性或方法“seedData”未在实例上定义,但在渲染期间被引用。通过初始化该属性,确保该属性是反应性的,无论是在数据选项中,还是对于基于类的组件。

您可以做的是将seedData对象传递给根 Vue 实例,如下所示:

       var vm = new Vue({
          el: '#app',
          data: {
            seedData: seedData
          } 
        });

现在错误消失了,但数据更改仍然没有反映出来。原因不是 Vue 特定的。其简单的 JavaScript。对象在 JS 中通过引用传递。看看这段代码:

var a = { name: 'John' }
var b = a
a = { name: 'Smith' }
// b is still pointing to "John" object

要解决此问题,请不要替换整个对象。只需改变它的属性(注意Vue 反应性警告

      setInterval(function() {
          seedData.name = 'John';
          seedData.percent = Math.random();
      }, 1000)

整体解决方案:

Vue.component('offers', {
  template: '<h1>{{ parentData.name }}: {{ parentData.percent }}</h1>',
  props: {
    parentData: {
      default: () => ({
        percent: 0,
        name: 'John'
      }),
      type: Object
    },
  }
});

// create a new Vue instance and mount it to our div element above with the id of app
var vm = new Vue({
  el: '#app',
  data: {
    seedData: seedData
  } 
});
<script>
	  var seedData = {
	    percent: 60,
	    name: 'Smith'
	  }
	  setInterval(function() {
	      seedData.name = 'John';
	      seedData.percent = Math.random();
	  }, 1000)
	</script>
	<div id="app">		
	  <offers :parent-data="seedData"></offers>
	</div>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>


推荐阅读