在vue 2中,我曾经这样调用render()
:
export default {
mounted(){
...
},
render(){
...
},
methods(){
...
}
}
我现在正试图用Vue 3和合成api做同样的事情。下面是我的尝试:
export default {
...
setup(props, context){
...
const create_canvas = (h, id, props) => {
_id.value = id
_attrs.value = props.attrs
return () => h('div', {
class: `trading-vue-${id}`,
style: {
left: props.position.x + 'px',
top: props.position.y + 'px',
position: 'absolute',
}
}, [
h('canvas', Object.assign({
id: `${props.tv_id}-${id}-canvas`,
onmousemove: e => renderer.mousemove(e),
onmouseout: e => renderer.mouseout(e),
onmouseup: e => renderer.mouseup(e),
onmousedown: e => renderer.mousedown(e),
ref: 'canvas',
style: props.style,
}, props.attrs))
].concat(props.hs || []))
};
function render() {
const id = props.grid_id
const layout = props.layout.grids[id]
return () => create_canvas(h, `grid-${id}`, {
position: {
x: 0,
y: layout.offset || 0
},
attrs: {
width: layout.width,
height: layout.height,
overflow: 'hidden'
},
style: {
backgroundColor: props.colors.back
},
hs: [
h(Crosshair, Object.assign(
common_props(),
layer_events
)),
h(KeyboardListener, keyboard_events),
h(UxLayer, {
id,
tv_id: props.tv_id,
uxs: uxs.value,
colors: props.colors,
config: props.config,
updater: Math.random(),
onCustomEvent: emit_ux_event
})
].concat(get_overlays(h))
})
};
render()
}
}
这在我的模板中似乎没有返回任何东西。我认为我没有以正确的方式调用render
函数。谁能帮我理解如何使用它?
根据我的理解,h()
是创建vnodes并接受3个参数的简短形式。
h(
tag name,
props/attributes,
array of children
)
根据我的理解,在create_canvas
中,您正在尝试创建一个包含class
和inline styles
作为道具/属性的div
,我们正在创建一个canvas
作为这个div
vnode的子节点。因此,与其直接从setup()返回vNode
,它应该返回一个返回vNode
的渲染函数。
export default {
props: {
// props will come here
},
setup(props) {
// render() { h(...) } ❌
return () => {
h('div', {
class: `trading-vue-${id}`,
style: {
left: props.position.x + 'px',
top: props.position.y + 'px',
position: 'absolute',
}
}, [
h('canvas', Object.assign({
id: `${props.tv_id}-${id}-canvas`,
onmousemove: e => renderer.mousemove(e),
onmouseout: e => renderer.mouseout(e),
onmouseup: e => renderer.mouseup(e),
onmousedown: e => renderer.mousedown(e),
ref: 'canvas',
style: props.style,
}, props.attrs))
].concat(props.hs || []))
} ✅
}
}
首先你不是在"打电话";渲染函数-你只是声明它(Vue在渲染时调用它)
在合成API中,你只需要从setup
返回渲染函数
import { ref, h } from 'vue'
export default {
props: {
/* ... */
},
setup(props) {
const count = ref(1)
// return the render function
return () => h('div', props.msg + count.value)
}
}
在将这些知识应用于您自己的代码之后,我会说setup
的最后一行不应该是render()
,而是return render()
(因为render()
函数本身返回实际的"渲染")。函数)在JS中函数被视为数据-你可以将它们存储在变量中并从函数中返回它们。当函数被存储或作为另一个函数的结果返回时,它不会立即执行——它只是被创建。给"工厂"打电话的人函数(在本例中,工厂函数是setup()
,调用者是Vue)可以存储对返回函数的引用,并且决定何时调用它
Vue Composition API的onMounted钩子的工作原理非常相似。您正在调用onMounted()
,并将新创建的函数作为参数传递。onMounted
将对函数的引用存储在某个地方,以便Vue以后可以调用它。
关键是,在setup()
中,onMounted()
首先执行,您的渲染函数作为setup
的最后一条语句返回并不重要。因为Vue决定何时调用它们"有时稍后"。我们可以合理地期望Vue在调用传递给onMounted()
的函数之前至少调用一次渲染函数(因为组件在渲染之前不能挂载)