simple-boot-front

front end SPA frameworks

Usage no npm install needed!

<script type="module">
  import simpleBootFront from 'https://cdn.skypack.dev/simple-boot-front';
</script>

README

Single Page Application Framworks npm version license Chat Github

Our primary goals are

  • Single Page Application Framworks for Web
  • Provide a radically faster and widely accessible getting started experience for all front end.

📄 introduction page [link]


🚀 Quick start cli

npm init simple-boot-front projectname
cd projectname
npm start
  • Installation and Getting Started
npm install simple-boot-front

😃 examples


📄 Code description

start

<!DOCTYPE html><html lang="en"><body id="app"></body></html>
const option = new SimFrontOption(window).setUrlType(UrlType.hash);
const simpleApplication = new SimpleBootFront(Index, option);
simpleApplication.run();

@Sim

Objects managed by the SimpleBootFront framework

  • parameter: SimConfig {schema: string}
@Sim({scheme: 'index'})

@Component

<!--template.html-->
<h1>${this.title}</h1>
<div dr-inner-html="this.html"></div>
@Sim()
@Component({
  selector: 'index', // default class name LowerCase
  template,
  styles: [style]
})
export class Index {
  public title = ''
  public html = ''
  public setData(title: string, html: string) {
    this.title = title;
    this.html = html;
  }
}

using

constructor(index: Index){...}
<index></index>
<!-- dr-set: $index.setData('data'); $element, $innerHTML, $attributes -->
<index dr-set="$index.setData('hello component', $innerHTML)"></index>

@Router

@Sim()
@Router({
    path: '',
    route: {
        '/': Home,
        '/user': User,
        '/user/:id': UserDetail
    }
})
@Component({
    template,
    styles: [style]
})
export class Index implements RouterAction {
    child?: any;
    canActivate(url: any, module: any): void {
        this.child = module;
    }
}

activeRoute

constructor(routerManager: RouterManager){
    // get path data
    routerManager.activeRouterModule.pathData.id; // /user/:id
}

component include

<route component="this.child"></route>

router option

  • attribute
    • router-active-class: url === href attribute => class add (a-classname, b-classname)
      • value: add and remove class name
    • router-inactive-class: url !== href attribute => class add (a-classname, b-classname)
      • value: add and remove class name
    <a router-link="/home" router-active-class="active" router-inactive-class="inactive">home</a>
    
    • router-link:
      • value: router link

@Script

@Sim({scheme: 'i18nScript'})
@Script({
    name: 'i18n'
})
export class I18nScript extends ScriptRunnable {
    public language?: Language;
    constructor(public i18nService: I18nService) {
        super();
        i18nService.subject.subscribe(it => {
            this.language = it;
            this.render();  // <-- ref target  rerender
        })
    }
    run(key: string): any {
        return this.language?.defaultData?.[key] ?? key;
    }
}

using script

counstructor(i18nScript: I18nScript) {...}
counstructor(scriptService: ScriptService) {
  const i18nScript = scriptService.getScript('i18n');
}
<div>${$scripts.i18n('Get Locale JSON')}</div>
<div dr-if="$scripts.i18n('Get Locale JSON') === 'wow'"> is wow</div>

@PostConstruct

Methods that you run for a separate initialization operation after the object is created

@PostConstruct
post(projectService: ProjectService) {
    console.log('post Construct  and dependency injection')
}

@After, @Before (AOP)

fire($event: MouseEvent, view: View<Element>) {
    console.log('fire method')
    this.data = RandomUtils.random(0, 100);
}

@Before({property: 'fire'})
before(obj: any, protoType: Function) {
    console.log('before', obj, protoType)
}

@After({property: 'fire'})
after(obj: any, protoType: Function) {
    console.log('after', obj, protoType)
}

@ExceptionHandler

@ExceptionHandler(TypeError)
public exceptionTypeError(e: TypeError) {
  console.log('TypeError exception:')
}

@ExceptionHandler(SimError)
public exception1(e: SimError) {
  console.log('SimError exception:')
}

@ExceptionHandler(RouterError)
public exception3(e: RouterError) {
  console.log('NotFountRoute exception:')
}

@ExceptionHandler(SimNoSuch)
public exception2(e: SimNoSuch) {
  console.log('NoSuchSim exception:')
}

View template engine (dom-render)

  • DomRender npm version Github
  • It's a compiler that takes your declarative components and converts them into efficient JavaScript that surgically updates the DOM.
  • Update view only for parts where the value has changed.
  • event: addEventListener (attribute)
<div>
    click: <button dr-event-click="this.name = 'name' + new Date()">click</button> <br>
    change: <input type="text" dr-event-change="this.name = $target.value"> <br>
    input: <input type="text" dr-event-input="this.name = $target.value"> <br>
    keyup: <input type="text" dr-event-keyup="this.name = $target.value"> <br>
    keydown: <input type="text" dr-event-keydown="this.name = $target.value"><br>
    ...
    submit: <form dr-event-submit="console.log($event); $event.preventDefault();"><input type="text"> <button type="submit">submit</button></form><br>
    window-event-popstate: <input type="text" dr-window-event-popstate="alert(this.name)"><br>
</div>...

  • If you want to see more information Move here go dom-render github

LifeCycle

Module LifeCycle interface

  • LifeCycle
    • onCreate(): Sim onCreate just one call
  • OnChangedRender
    • onChangedRender(): change rended in module event
  • OnFinish
    • onFinish(): lifecycle finish event
  • OnInit
    • onInit(): module load event
  • OnDestroy
    • onDestroy(): module destroy event
  • OnInitedChild
    • onInitedChild(): module and child module inited event

Intent event broker

constructor(intentManager: IntentManager){...}
// call
queryParamCall() {
  this.intentManager.publish(new Intent('layout://info/data?a=wow&aa=zzz', Math.floor(RandomUtils.random(0, 100))));
}
call() {
  this.intentManager(new Intent('layout://info/datas', Math.floor(RandomUtils.random(0, 100))));
}
targetCall() {
  this.intentManager(new Intent('layout://', Math.floor(RandomUtils.random(0, 100))));
  // default callback method -> subscribe(i: Intent)
}
globalCall() {
  this.intentManager(new Intent('://info/datas', Math.floor(RandomUtils.random(0, 100))));
}
windowEventCall() {
  const data = new CustomEvent('intent', {detail: {uri: 'index://showStore', data: {id: 'id data'}}});
  window.dispatchEvent(data);
}

// receive
showStore(i: Intent) {
  this.datas = i.data + '->' + i.params.aa
}
@Sim({scheme: 'layout'})
@Component({
  template,
  styles: [css]
})
export class App {
    info = new AppInfo();
    constructor() {}
}
export class AppInfo {
    datas = 'default data';
    data(i: Intent) {
        this.datas = i.data + '->' + i.params.aa
    }
}

Advice

  • global advice
@Sim()
export class Advice {

    @ExceptionHandler()
    public exception0(e: any) {
        console.log('Advice Global exception:')
    }

    @Before({type: Aop, property: 'unkown'})
    public beforeTest(obj: any, f: Function, name: string) {
        console.log('before Test:')
    }

    @After({type: Aop, property: 'unkown'})
    public afterTest(obj: any, f: Function, name: string) {
        console.log('after Test:')
    }
}
const option = new SimFrontOption(window, [Advice]).setUrlType(UrlType.hash);
const simpleApplication = new SimpleBootFront(AppRouter, option);
simpleApplication.run();

License

  • MIT
  • visualkhh@gmail.com