Refactor event binding logic in SUI core

This commit is contained in:
Max 2024-07-20 10:47:46 +08:00
parent bafe3bb20f
commit fbfd3f270a
4 changed files with 88 additions and 13 deletions

View file

@ -170,6 +170,9 @@ func (page *Page) BuildAsComponent(sel *goquery.Selection, ctx *BuildContext, op
return "", err
}
// Bind the component events
page.BindEvent(ctx, doc.Selection, component)
body := doc.Selection.Find("body")
if body.Children().Length() == 0 {
@ -553,6 +556,11 @@ func (page *Page) BuildScripts(ctx *BuildContext, option *BuildOption, component
component = ComponentName(page.Route, option.ScriptMinify)
}
arguments := ""
if !ispage {
arguments = "arguments[0]"
}
scripts := []ScriptNode{}
if page.Codes.JS.Code == "" && page.Codes.TS.Code == "" {
return scripts, nil
@ -566,17 +574,18 @@ func (page *Page) BuildScripts(ctx *BuildContext, option *BuildOption, component
var imports []string = nil
var source []byte = nil
if page.Codes.TS.Code != "" {
source, imports, err = page.CompileTS([]byte(page.Codes.TS.Code), option.ScriptMinify)
code := fmt.Sprintf("this.store = new __sui_store(%s);\n%s", arguments, page.Codes.TS.Code)
source, imports, err = page.CompileTS([]byte(code), option.ScriptMinify)
if err != nil {
return nil, err
}
} else if page.Codes.JS.Code != "" {
source, imports, err = page.CompileJS([]byte(page.Codes.JS.Code), option.ScriptMinify)
code := fmt.Sprintf("this.store = new __sui_store(%s);\n%s", arguments, page.Codes.JS.Code)
source, imports, err = page.CompileJS([]byte(code), option.ScriptMinify)
if err != nil {
return nil, err
}
}
// Add the script

View file

@ -58,6 +58,9 @@ func (page *Page) Compile(ctx *BuildContext, option *BuildOption) (string, []str
}
// SUI lib
head.AppendHtml("\n\n" + `<script name="sui" type="text/javascript">` + suiLibScript + `</script>` + "\n\n")
// Page Config
page.Config = page.GetConfig()

View file

@ -10,14 +10,26 @@ import (
)
// BindEvent is a method that binds events to the page.
func (page *Page) BindEvent(ctx *BuildContext, sel *goquery.Selection) {
func (page *Page) BindEvent(ctx *BuildContext, sel *goquery.Selection, component ...string) {
// Component events
if len(component) > 0 && component[0] != "" {
fmt.Println("component events:", page.Route, component[0])
matcher := NewAttrPrefixMatcher(`s:on-`)
sel.FindMatcher(matcher).Each(func(i int, s *goquery.Selection) {
fmt.Println("\tcomponent event", i, s.Nodes[0].Data)
page.appendEventScript(ctx, s, component[0])
})
return
}
matcher := NewAttrPrefixMatcher(`s:on-`)
sel.FindMatcher(matcher).Each(func(i int, s *goquery.Selection) {
page.appendEventScript(ctx, s)
page.appendEventScript(ctx, s, "")
})
}
func (page *Page) appendEventScript(ctx *BuildContext, sel *goquery.Selection) {
func (page *Page) appendEventScript(ctx *BuildContext, sel *goquery.Selection, component string) {
if len(sel.Nodes) == 0 {
return
@ -71,13 +83,18 @@ func (page *Page) appendEventScript(ctx *BuildContext, sel *goquery.Selection) {
source := ""
for name, handler := range events {
source += pageEventInjectScript(id, name, dataRaw, jsonRaw, handler) + "\n"
if component == "" {
source += pageEventInjectScript(id, name, dataRaw, jsonRaw, handler) + "\n"
} else {
source += compEventInjectScript(id, name, component, dataRaw, jsonRaw, handler) + "\n"
}
sel.RemoveAttr(fmt.Sprintf("s:on-%s", name))
}
ctx.scripts = append(ctx.scripts, ScriptNode{
Source: source,
Namespace: page.namespace,
Component: component,
Attrs: []html.Attribute{{Key: "event", Val: id}},
})

View file

@ -2,11 +2,7 @@ package core
import "fmt"
const initScriptTmpl = `
try {
var __sui_data = %s;
} catch (e) { console.log('init data error:', e); }
const suiLibScript = `
function __sui_event_handler(event, dataKeys, jsonKeys, elm, handler) {
const data = {};
@ -26,10 +22,47 @@ const initScriptTmpl = `
}
}
})
handler && handler(event, data, elm);
};
function __sui_store(elm) {
elm = elm || document.body;
this.Get = function (key) {
return elm.getAttribute("data:" + key);
}
this.Set = function (key, value) {
elm.setAttribute("data:" + key, value);
}
this.GetJSON = function (key) {
const value = elm.getAttribute("json:" + key);
if (value && value != "") {
try {
const res = JSON.parse(value);
return res;
} catch (e) {
const message = e.message || e || "An error occurred";
console.error(` + "`[SUI] Event Handler Error: ${message}`" + `, elm);
return null;
}
}
return null;
}
this.SetJSON = function (key, value) {
elm.setAttribute("json:" + key, JSON.stringify(value));
}
}
`
const initScriptTmpl = `
try {
var __sui_data = %s;
} catch (e) { console.log('init data error:', e); }
document.addEventListener("DOMContentLoaded", function () {
try {
document.querySelectorAll("[s\\:ready]").forEach(function (element) {
@ -71,6 +104,15 @@ const pageEventScriptTmpl = `
});
`
const compEventScriptTmpl = `
document.querySelector("[s\\:event=%s]").addEventListener("%s", function (event) {
const dataKeys = %s;
const jsonKeys = %s;
const handler = new %s(this).%s;
__sui_event_handler(event, dataKeys, jsonKeys, this, handler);
});
`
func bodyInjectionScript(jsonRaw string, debug bool) string {
jsPrintData := ""
if debug {
@ -86,3 +128,7 @@ func headInjectionScript(jsonRaw string) string {
func pageEventInjectScript(eventID, eventName, dataKeys, jsonKeys, handler string) string {
return fmt.Sprintf(pageEventScriptTmpl, eventID, eventName, dataKeys, jsonKeys, handler)
}
func compEventInjectScript(eventID, eventName, component, dataKeys, jsonKeys, handler string) string {
return fmt.Sprintf(compEventScriptTmpl, eventID, eventName, dataKeys, jsonKeys, component, handler)
}