Skip to content

Commit

Permalink
Merge pull request #699 from trheyi/main
Browse files Browse the repository at this point in the history
optimize event binding logic in SUI core for just-in-time mode
  • Loading branch information
trheyi authored Jul 20, 2024
2 parents 036553b + f32a677 commit 67ffd4f
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 69 deletions.
19 changes: 15 additions & 4 deletions sui/core/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ func (page *Page) Build(ctx *BuildContext, option *BuildOption) (*goquery.Docume
doc.Find("body").SetAttr("s:ns", namespace)

// Bind the Page events
page.BindEvent(ctx, doc.Selection)
if !option.JitMode {
page.BindEvent(ctx, doc.Selection, "__page", true)
}

warnings, err := page.buildComponents(doc, ctx, option)
if err != nil {
Expand Down Expand Up @@ -170,6 +172,9 @@ func (page *Page) BuildAsComponent(sel *goquery.Selection, ctx *BuildContext, op
return "", err
}

// Bind the component events
page.BindEvent(ctx, doc.Selection, component, false)

body := doc.Selection.Find("body")

if body.Children().Length() == 0 {
Expand Down Expand Up @@ -553,6 +558,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
Expand All @@ -566,17 +576,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
Expand Down
7 changes: 7 additions & 0 deletions sui/core/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down Expand Up @@ -111,6 +114,7 @@ func (page *Page) CompileAsComponent(ctx *BuildContext, option *BuildOption) (st
opt := *option
opt.IgnoreDocument = true
opt.WithWrapper = true
opt.JitMode = true
doc, warnings, err := page.Build(ctx, &opt)
if err != nil {
return "", warnings, err
Expand Down Expand Up @@ -262,6 +266,9 @@ func (script ScriptNode) ComponentHTML(ns string) string {
}

source := fmt.Sprintf(`function %s(){%s};`, script.Component, script.Source)
if script.Component == "" {
return "<script " + strings.Join(attrs, " ") + ">\n" + script.Source + "\n</script>"
}
return "<script " + strings.Join(attrs, " ") + ">\n" + source + "\n</script>"
}

Expand Down
56 changes: 41 additions & 15 deletions sui/core/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,48 @@ import (
"golang.org/x/net/html"
)

var eventMatcher = NewAttrPrefixMatcher(`s:on-`)

// BindEvent is a method that binds events to the page.
func (page *Page) BindEvent(ctx *BuildContext, sel *goquery.Selection) {
matcher := NewAttrPrefixMatcher(`s:on-`)
sel.FindMatcher(matcher).Each(func(i int, s *goquery.Selection) {
page.appendEventScript(ctx, s)
func (page *Page) BindEvent(ctx *BuildContext, sel *goquery.Selection, cn string, ispage bool) {

sel.FindMatcher(eventMatcher).Each(func(i int, s *goquery.Selection) {
if comp, has := s.Attr("is"); has && ctx.isJitComponent(comp) {
return
}
script := GetEventScript(ctx.sequence, s, page.namespace, cn, "event", ispage)
if script != nil {
ctx.scripts = append(ctx.scripts, *script)
ctx.sequence++
}
})
}

// BindEvent is a method that binds events to the component in just-in-time mode.
func (parser *TemplateParser) BindEvent(sel *goquery.Selection, ns string, cn string) {
sel.FindMatcher(eventMatcher).Each(func(i int, s *goquery.Selection) {
script := GetEventScript(parser.sequence, s, ns, cn, "event-jit", false)
if script != nil {
script.Component = ""
script.Parent = "body"
parser.scripts = append(parser.scripts, *script)
parser.sequence++
}
})
}

func (page *Page) appendEventScript(ctx *BuildContext, sel *goquery.Selection) {
// GetEventScript the event script
func GetEventScript(sequence int, sel *goquery.Selection, ns string, cn string, prefix string, ispage bool) *ScriptNode {

if len(sel.Nodes) == 0 {
return
return nil
}

// Page events
events := map[string]string{}
dataUnique := map[string]string{}
jsonUnique := map[string]string{}
id := fmt.Sprintf("event-%d", ctx.sequence)
ctx.sequence++

id := fmt.Sprintf("%s-%d", prefix, sequence)
for _, attr := range sel.Nodes[0].Attr {

if strings.HasPrefix(attr.Key, "s:on-") {
Expand Down Expand Up @@ -71,15 +92,20 @@ func (page *Page) appendEventScript(ctx *BuildContext, sel *goquery.Selection) {

source := ""
for name, handler := range events {
source += pageEventInjectScript(id, name, dataRaw, jsonRaw, handler) + "\n"
if ispage {
source += pageEventInjectScript(id, name, dataRaw, jsonRaw, handler) + "\n"
} else {
source += compEventInjectScript(id, name, cn, dataRaw, jsonRaw, handler) + "\n"
}
sel.RemoveAttr(fmt.Sprintf("s:on-%s", name))
}

ctx.scripts = append(ctx.scripts, ScriptNode{
sel.SetAttr("s:event", id)

return &ScriptNode{
Source: source,
Namespace: page.namespace,
Namespace: ns,
Component: cn,
Attrs: []html.Attribute{{Key: "event", Val: id}},
})

sel.SetAttr("s:event", id)
}
}
58 changes: 52 additions & 6 deletions sui/core/injections.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {};
Expand All @@ -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) {
Expand Down Expand Up @@ -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 {
Expand All @@ -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)
}
Loading

0 comments on commit 67ffd4f

Please sign in to comment.