我希望能够在我的vue.js应用程序中使用两个窗口,一个用于管理数据,另一个用于显示相同的数据。 (想象一下现场演示,我可以在笔记本电脑的一个窗口中动态更改内容,但我的观众看到数据的简化表示 - 即,他们看不到所有编辑工具 - 在一个单独的窗口中投影屏幕。)
作为原型,我尝试过实现一个基本的todo应用程序,如下所示:
<html>
<body id="app">
<div id="entry-form">
<input type="text" placeholder="enter a todo item" v-model="todo">
<button v-on:click="addTodo">+</button>
</div>
<div id="todo-list">
<ol>
<li v-for="t in todos">
<span>{{ t }}</span><button v-on:click="delTodo">-</button>
</li>
</ol>
</div>
<button v-on:click="openViewer">Viewer</button>
<script src="vue.min.js"></script>
<script>
var stateData = {
todo : '',
todos : [],
}
new Vue({
el: '#app',
data: stateData,
methods : {
addTodo : function() {
if ( this.todo ) {
this.todos.push(this.todo);
this.todo = '';
}
},
delTodo : function(index) {
this.todos.splice(index,1);
},
openViewer : function() {
var w = window.open("viewer.html", "viewer");
w.getStateData = function() {
return stateData;
}
}
},
});
</script>
</body>
</html>
然后是一个viewer.html(由上面文件中的openViewer函数打开),如下所示:
<html>
<body id="viewer">
<div id="todo-list">
<ol>
<li v-for="t in todos">
<span>{{ t }}</span>
</li>
</ol>
</div>
<script src="vue.min.js"></script>
<script>
window.onload = function() {
new Vue({ el: "#viewer", data: getStateData() });
}
</script>
</body>
</html>
这似乎让我在那里中途。我可以输入一些待办事项并单击“查看器”按钮,然后会打开第二个窗口,显示预期的待办事项。但是,当我在打开查看器窗口后开始输入新的待办事项时,事情开始表现得很奇怪。输入字段在模糊时清除,并且待办事项列表不再出现在主窗口中,但仍可在查看器窗口中使用。
显然,我正在滥用vue.js的工作方式。是我试图用vue.js实现的吗?如果是这样,请告诉我如何以vue.js方式完成这项工作?
由于
答案 0 :(得分:3)
我认为localStorage
API就是您所需要的。 localStorage
在数据更新时触发事件 - 您可以从其他窗口读取的事件。
观看演示:http://html5demos.com/storage-events
信息链接到文档:Javascript; communication between tabs/windows with same origin
github上的一个库,用于处理交叉表通信,如果您有兴趣:https://github.com/diy/intercom.js/
我认为您希望在Vue组件中添加watch
功能,每当stateData
值更新时,您都希望更新localStorage
中的相应变量。这会将事件发送到另一个窗口。类似的东西:
应用窗口:
new Vue({
el: '#app',
data: {
todo : '',
todos : [],
},
methods : {
addTodo : function() {
if ( this.todo ) {
this.todos.push(this.todo);
this.todo = '';
}
},
delTodo : function(index) {
this.todos.splice(index,1);
},
openViewer : function() {
window.open("viewer.html", "viewer");
}
},
watch:{
stateData: {
deep:true,
handler:function(newValue){
window.localStorage.setItem('viewer-demo',newValue);
}
}
}
});
查看器窗口:
new Vue({
el: "#viewer",
data: {
stateData: {
todo : '',
todos : []
}
},
ready:function(){
addEvent(window, 'storage', function (event) {
if (event.key == 'viewer-demo') {
this.stateData = event.newValue;
}
}.bind(this));
}
});