我认为这不一定是基于Vue的问题,但我遇到了一些麻烦。
我想在画布上写一个Vue变量。如果我删除了vue,我的初始代码工作正常,但是如果我添加Vue,画布实际上并没有启动。
这是我的代码
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = "black";
ctx.font="20px Georgia";
ctx.fillText("Hello World!",10,50);
var v = new Vue({
el: '#app',
data: {
'exampleContent': 'This is TEXT'
},
watch: {
exampleContent: function(val, oldVal) {
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = "black";
ctx.font="20px Georgia";
ctx.fillText(this.exampleContent,10,50);
}
}
});
如果我评论/* var v = new Vue({ ...
,则初始位有效。如果我在观察者中记录exampleContent
的值也可以。但是关于画布的一些东西不起作用。
答案 0 :(得分:15)
请检查此jsFiddle:https://jsfiddle.net/mani04/r4mbh6nu/
编辑:使用动态文字进行了更新:https://jsfiddle.net/mani04/r4mbh6nu/1/
在上面的示例中,我可以写入画布,并确保input
文本按照您的预期进入span
,所有这些都使用Vue.js
回到你的例子,HTML是:
<div id="app">
<canvas id="canvas" width="800" height="600"></canvas>
<input type="text" v-model="exampleContent" />
<span>{{ exampleContent }}</span>
</div>
Vue.js读取#app
中的元素,并将其保留为 Vue应用的模板。因此,当构建DOM时,Vue.js现在将重新呈现您的canvas
,input
和span
元素。
在此过程中,原始画布文本 - 您在启动Vue应用程序之前设置的文本文本将丢失。
除了使用directive
之外,没有明确的方法来解决这个问题,就像在我的jsFiddle示例中一样。 Vue指令可帮助您捕获DOM元素。
在我的示例中,我定义了一个名为insert-message
的Vue指令,我在画布上使用v-insert-message
。这允许我捕获DOM元素,然后执行其他步骤:getContext
和fillText
。没有id
要求,或getElementById
没有javascript代码。
还有一件事 - 你的画布太大了,因此你无法看到你的input
和span
元素。他们在你的例子中也正常工作!
编辑:指令绑定的示例
我刚刚找到了一种使用指令的方法,并且仍然将动态内容写入画布。
检查更新的jsFiddle:https://jsfiddle.net/mani04/r4mbh6nu/1/
答案 1 :(得分:15)
这是一个适用于Vuejs 2的简单方法:
使用引用属性将画布添加到模板:
ref="myCanvas"
然后,您可以使用
在组件内的任何位置访问它var canvas = this。$ refs.myCanvas
答案 2 :(得分:6)
如@Mani's Answer中所述,Vue删除并重新呈现调用Vue实例的DOM元素。
如果将画布更新抽象为Vue实例method
,则可以在mounted
生命周期挂钩(获取exampleContent
的初始值)触发它,重新调用当watch
发生变化时,exampleContent
会发现它。
var v = new Vue({
el: '#app',
data: {
'exampleContent': 'This is TEXT'
},
methods: {
updateCanvas: function (){
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d');
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillStyle = "black";
ctx.font="20px Georgia";
ctx.fillText(this.exampleContent,10,50);
}
},
watch: {
exampleContent: function(val, oldVal) {
this.updateCanvas();
}
},
mounted: function (){
this.updateCanvas();
}
});
canvas{
background:red;
width:800px;
height:600px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.1/vue.min.js"></script>
<div id="app">
<canvas id="canvas" width="800" height="600"></canvas>
<input type="text" v-model="exampleContent" />
<span>{{ exampleContent }}</span>
</div>
前面的SO代码片段是从OP的CodePen
的分叉版本创建的