最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin5浏览0评论

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)

发布评论

评论列表(0)

  1. 暂无评论