使用现有HTML中的数据加载Vue视图模型

时间:2017-02-07 18:36:09

标签: vue.js vuejs2

我想将Vue与预呈现的HTML一起使用。从长远来看,我们可能没有,但是现在似乎更容易保留服务器代码并使用Vue来管理Web应用程序的客户端逻辑。

我似乎找不到任何描述如何让视图模型从HTML加载数据的内容。我的例子与https://github.com/vuejs/Discussion/issues/56相同。即使该问题已经关闭(并且已修复?),我似乎也无法在1.x或2.x中工作。

当我设置一些HTML

<div id="myvue">
    <span v-text="message">Hello!</span>
</div>

然后为它创建一个视图模型

var vm = new Vue({
    el: '#myvue'
});

我希望让vm对象与来自HTML的数据保持一致,以便vm.message == 'Hello!'成立。但这不会发生。我最后得到的错误是message未定义版本1.对于版本2,我收到一条警告Property or method "message" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.

但是当我在vm中声明数据属性时就像这样

var myvue = new Vue({
    el: '#myvue',
    data: {
        message: <something>
    }
});

无论<something>是什么(null,一个字符串,未定义),它总是替换HTML元素中的内容。有没有办法让Vue对象从HTML加载数据?

3 个答案:

答案 0 :(得分:0)

理论上不可能直接从HTML中保存你的状态,因为渲染不是一个双射函数。两个简单的例子:

  • <p>{{ foo }}</p>呈现给<p>2</p>foo是字符串还是数字?
  • <p>{{ foo + bar }}</p>呈现给<p>6</p>foobar的价值是什么?

补充状态的最简单方法是获取用于在服务器上呈现的数据,将其序列化为JSON并直接在文档中使用<script>window.hydrationData = ...</script>呈现它。这样,您可以在创建Vue实例时将其用于data

此方法在官方Vue演示应用中为also used

答案 1 :(得分:0)

与Vue无关,但与Knockout.js一起使用时,ErikSchierboom's knockout-pre-rendered custom binding可以执行此操作。

这个组合本质上允许您定义输入或其他东西

<div id="mydiv">
    <input data-bind="init, textInput: content" value="foo"/>
</div>

然后将模型对象绑定到它

function ViewModel() {
    this.content = ko.observable();
}

var vm = new ViewModel();
ko.applyBindings(vm, $('#mydiv')[0])

在输入上使用init绑定时,vm内容会在绑定时从输入中加载值。

同样,这不是Vue。但是我想我会把它放在一边帮助别人。

答案 2 :(得分:0)

如果渲染的HTML不依赖于计算属性,则可以选择解析生成的HTML以获取数据所需的值(例如使用jQueryvanilla-js创建一个数据对象,以便在实例化时传递给VM:

$(function(){
  var app = '#app';
  var $app = $(app);
  var data = {
    a: 0, // some initial value not present in HTML
    b: $app.find('.foo').text(),
    c: $app.find('input[name=c]').val()
  };
  var vm = new Vue({
    el: app,
    template: '...template...', // if needed
    data: data,
    ...
  });
});

实例化时,数据模型应与呈现的HTML匹配。如果并非所有模板组件都是呈现的HTML的一部分,则可能需要提供模板。请注意,这很可能会导致应用程序在实例化后重新呈现。您可以将server-rendered="true"属性添加到根应用元素,以防止此,如果预呈现的HTML与vm呈现的内容相同。

另一个不那么自动化的选项是让您的模板在您的元素下方生成<script>标记,其中包含数据模型:

<script>
  window.MYSTATE = window.MYSTATE || {};
  window.MYSTATE['#app'] = {
    "a": 0,
    "b": "Some text",
    "c": "Some value"
  };
</script>

确保您的数据已正确转义为JSON格式。然后在您实例化应用程序的页面脚本中,使用window.MYSTATE [&#39;#app&#39;]作为数据对象(执行深度克隆以防止window.MYSTATE实例中的更改影响您的模型。< / p>

var vm = new Vue({
  el: '#app',
  template: '...template if needed...',
  data: $.extend(true, {}, window.MYSTATE['#app'])
  ...
});

只需确保在页面加载后进行实例化(即在关闭body标记之前将其放在页面底部)