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 return "", err
} }
// Bind the component events
page.BindEvent(ctx, doc.Selection, component)
body := doc.Selection.Find("body") body := doc.Selection.Find("body")
if body.Children().Length() == 0 { if body.Children().Length() == 0 {
@ -553,6 +556,11 @@ func (page *Page) BuildScripts(ctx *BuildContext, option *BuildOption, component
component = ComponentName(page.Route, option.ScriptMinify) component = ComponentName(page.Route, option.ScriptMinify)
} }
arguments := ""
if !ispage {
arguments = "arguments[0]"
}
scripts := []ScriptNode{} scripts := []ScriptNode{}
if page.Codes.JS.Code == "" && page.Codes.TS.Code == "" { if page.Codes.JS.Code == "" && page.Codes.TS.Code == "" {
return scripts, nil return scripts, nil
@ -566,17 +574,18 @@ func (page *Page) BuildScripts(ctx *BuildContext, option *BuildOption, component
var imports []string = nil var imports []string = nil
var source []byte = nil var source []byte = nil
if page.Codes.TS.Code != "" { 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 { if err != nil {
return nil, err return nil, err
} }
} else if page.Codes.JS.Code != "" { } 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 { if err != nil {
return nil, err return nil, err
} }
} }
// Add the script // 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.Config = page.GetConfig() page.Config = page.GetConfig()

View file

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

View file

@ -2,11 +2,7 @@ package core
import "fmt" import "fmt"
const initScriptTmpl = ` const suiLibScript = `
try {
var __sui_data = %s;
} catch (e) { console.log('init data error:', e); }
function __sui_event_handler(event, dataKeys, jsonKeys, elm, handler) { function __sui_event_handler(event, dataKeys, jsonKeys, elm, handler) {
const data = {}; const data = {};
@ -30,6 +26,43 @@ const initScriptTmpl = `
handler && handler(event, data, elm); 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 () { document.addEventListener("DOMContentLoaded", function () {
try { try {
document.querySelectorAll("[s\\:ready]").forEach(function (element) { 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 { func bodyInjectionScript(jsonRaw string, debug bool) string {
jsPrintData := "" jsPrintData := ""
if debug { if debug {
@ -86,3 +128,7 @@ func headInjectionScript(jsonRaw string) string {
func pageEventInjectScript(eventID, eventName, dataKeys, jsonKeys, handler string) string { func pageEventInjectScript(eventID, eventName, dataKeys, jsonKeys, handler string) string {
return fmt.Sprintf(pageEventScriptTmpl, eventID, eventName, dataKeys, jsonKeys, handler) 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)
}