javascript - How to call render functions in Vue 3 composition api? - Stack Overflow

Back in vue 2 i used to call render() like that:export default {mounted(){...},render(){...},methods()

Back in vue 2 i used to call render() like that:

export default {
    mounted(){
        ...
    },
    render(){
        ...
    },
    methods(){
        ...
    }
}

I'm now trying to do the same with Vue 3 and the position api. Here is what i tried:

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(
                        mon_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()
    }
}

This doesn't seem to return anything in my template. I think that i'm not calling the render function in the right way. Can anyone help me understanding how to use it?

Back in vue 2 i used to call render() like that:

export default {
    mounted(){
        ...
    },
    render(){
        ...
    },
    methods(){
        ...
    }
}

I'm now trying to do the same with Vue 3 and the position api. Here is what i tried:

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(
                        mon_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()
    }
}

This doesn't seem to return anything in my template. I think that i'm not calling the render function in the right way. Can anyone help me understanding how to use it?

Share Improve this question asked May 13, 2022 at 19:49 JayK23JayK23 2734 gold badges27 silver badges62 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

As per my understanding, h() is a short form to create the vnodes and accept 3 parameters.

h(
    tag name,
    props/attributes,
    array of children
)

As per my understanding, In create_canvas you are trying to create a div which contains a class and inline styles as a props/attributes and we are creating a canvas as a children of this div vnode. Hence, Instead of returning the vNode directly from setup(), it should return a render function that returns a vNode.

export default {
    props: {
      // props will e 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 || []))
       } ✅
    }
}

First you are are not "calling" render function - you are just declaring it (Vue is caling it when rendering)

In Composition API you just need to return render function from 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)
  }
}

After applying this knowledge on your own code I would say that the last line of setup should not be render() but return render() (because the the render() function itself returns actual "render" function)


In JS functions are treated as data - you can store them in variables and return them from the functions. When the function is stored or returned as a result of another function, it is not executed immediately - it is only created. The one who calls the "factory" function (in this case factory function is setup() and the caller is Vue) can store the reference to the returned function and decides when to call it

The Vue Composition API onMounted hook works very similarly. You are calling onMounted() passing a newly created function as an argument. onMounted stores the reference to the function somewhere so the Vue can later call it.

The point is that it does not matter that in setup() the onMounted() is executed 1st and your render function is returned as a last statement of setup. Because Vue decides when to call them "sometimes later". And it is reasonable to expect that Vue for sure will call your render function at least once before calling a function passed into onMounted() (because ponent cannot be mounted before it is rendered)

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744177075a4561805.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信