低開開發筆記(二):低程式碼編輯器基本原理

养肥胖虎發表於2024-04-15

好傢伙,

完整程式碼已開源

https://github.com/Fattiger4399/ph-questionnaire.git

本片我們來講述

如何將dsl的資料渲染為檢視

1.資料格式

dsl: {
                component: 'div',
                wid: 0,
                props: {
                },
                style: { background: '    #FFF8DC' },
                children: [

                    {
                        wid: 1,//序號
                        component: 'ph-radio', //元件名
                        props: {    //元件資料介面
                            No: 1,
                            title: "我是輸入框",
                            options_1: "選項一一",
                            options_2: "選項二二"
                        },
                        style: { top: '300px', left: '300px', zIndex: '1', border: "2px dashed red" },//元件配置項
                        attrs: {

                        },
                        events: {
                        }
                    },
]

2.vue的h函式

h 函式是 Vue.js 中的一個輔助函式,通常用於建立虛擬 DOM 元素(VNode)。

在 Vue.js 中,h 函式實際上是 createElement 函式的別名

createElement 函式是 Vue.js 內部用來建立虛擬 DOM 元素(VNode)的核心函式。

h 函式接收三個引數

  • 第一個引數:表示要建立的元素的標籤名、元件或者函式。
  • 第二個引數:是一個包含元素屬性、樣式、事件等資訊的物件。
  • 第三個引數:是元素的子元素,可以是一個陣列或者單個元素。

3.編輯器程式碼解釋

程式碼如下:

<script>
export default {
    data() {
        return {
            a: true
        }
    },
    props: ['dsl', 'model'],
    render(h) {
        let dsl = this.dsl;
        return this.generator(h, dsl);
    },
    methods: {
        adddraggable() {

        },
        select(e) {
            console.log(e);
        },
        generator(h, dsl) {
            //h(tagName,props,children)
            //當前元素,元素屬性,子元素
            return h(dsl.component, this.generateProps(h, dsl), this.generateChildren(h, dsl));
        },
        generateProps(h, dsl) {
            let self = this;
            let result = {
            }
            result.props = {
                ...dsl.props
            }
            result.attrs = {
                ...dsl.attrs
            }
            result.style = { ...dsl.style }

            if (self.model.selected) {
                if (self.model.selected.wid == dsl.wid) {
                    // 獲取所有的按鈕元素
                    const allElements = document.getElementById('editor.div')
                    console.log(allElements)

                }
            }
            if (dsl.events) {
                result.on = {
                    click: function (e) {
                        // console.log(e, dsl.wid, this);
                        e.preventDefault();
                        self.$emit('select', { e, dsl });
                    },
                };

            }
            return result;
        },/**
 * 該函式用於生成child節點
 * @param {*} h 
 * @param {*} dsl 
 */
        generateChildren(h, dsl) {

            let result = dsl.children &&
                dsl.children.map((child) => this.generator(h, child))
                || [];

            // (A&&B)||C

            if (dsl.text) result.push(dsl.text)
            // console.log(result)
            return result;
        }
    },
    mounted() {
    }
}
</script>

解釋

本質上是對props屬性遞迴處理後,使用vue的h函式將dsl全部渲染出來

讓我們把重點放在這句上

return h(dsl.component, this.generateProps(h, dsl), this.generateChildren(h, dsl));
  1. generator 方法用於生成 Vue 元素,根據傳入的 dsl 配置資訊,設定元素的屬性、樣式、事件等,並返回生成的元素。

  2. generateProps 方法用於生成元素的屬性,包括 propsattrsstyle,同時根據條件判斷是否新增事件監聽器。

  3. generateChildren 方法用於生成元素的子元素,遍歷 dsl 中的 children,對每個子元素呼叫 generator 方法生成對應的 Vue 元素,並返回所有子元素的陣列。

最終效果如下:

相關文章