-
Application:
- An application handles routing between many pages.
- Sets up ViewEngine
-
Pages:
- Only one page renders at a time determined by URL.
- Can start many controllers.
-
Controllers:
- Can render views, but doesn't have to.
- Is one "mount context" for a "view engine" and has it's own mount point.
-
ViewEngine:
- Agnostic view processor for controllers
-
Views/Components/etc.
- React code
Last active
July 16, 2020 22:13
-
-
Save tgroshon/1441acdd6812334c9edbdca3ad4f5737 to your computer and use it in GitHub Desktop.
Interesting Framework Idea
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ReactClassComponent, ReactHookComponent } from "./Components"; | |
import { Page, Controller } from "./Framework"; | |
import { ReactViewEngine } from "./ReactViewEngine"; | |
/* | |
=========================== | |
Non-react Application Code | |
=========================== | |
*/ | |
class MainController extends Controller { | |
views = [ReactHookComponent, ReactClassComponent]; | |
publicFn() { | |
window.alert("Controller Public Function called"); | |
} | |
} | |
class HomePage extends Page { | |
route = "/"; | |
controllerClasses = [MainController]; | |
} | |
class Application { | |
viewEngine = new ReactViewEngine(); | |
start() { | |
// TODO: Start a router and only run page for current matching URL | |
const page = new HomePage(this); | |
page.mount(); | |
} | |
} | |
const app = new Application(); | |
app.start(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ReactDOM from "react-dom"; | |
import React from "react"; | |
/* | |
================ | |
React Components | |
================ | |
*/ | |
export class ReactClassComponent extends React.Component { | |
render() { | |
return <h2>Application rendered</h2>; | |
} | |
} | |
export function ReactHookComponent({ controller }) { | |
React.useEffect(() => { | |
console.log("Hook Component side-effect fired"); | |
}); | |
return ( | |
<p> | |
Hook Component{" "} | |
<button onClick={() => controller.publicFn()}> | |
Trigger Controller Method | |
</button> | |
</p> | |
); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Controllers: | |
* - A page has many controllers. Each can render views, but doesn't have to. | |
* - Each controller is one "render context" for a "view engine". | |
* - Each controller has it's own mount point on the page. (Or none) | |
*/ | |
export class Controller { | |
views = []; | |
constructor(page, viewEngine) { | |
this.page = page; | |
this.viewEngine = viewEngine; | |
} | |
get mountPoint() { | |
if (!this._mountPoint) { | |
const el = document.createElement("DIV"); | |
document.body.appendChild(el); | |
this._mountPoint = el; | |
} | |
return this._mountPoint; | |
} | |
start() { | |
this.viewEngine.mount(this, this.views, this.mountPoint); | |
} | |
} | |
/** | |
* Pages: | |
* - An application has many pages. Pages integrate with router so only one | |
* page renders at a time determined by URL. | |
* - Can start many controllers. | |
*/ | |
export class Page { | |
route = "/"; | |
controllerClasses = []; // NOTE: Page can have multiple controllers | |
constructor(app) { | |
this.application = app; | |
} | |
get controllers() { | |
if (!this._controllers) { | |
this._controllers = this.controllerClasses.map(ControllerKlass => { | |
return new ControllerKlass(this, this.application.viewEngine); | |
}); | |
} | |
return this._controllers; | |
} | |
mount() { | |
this.controllers.forEach(controller => controller.start()); | |
} | |
} | |
/** | |
* Application | |
* - Handles config and routing | |
* - Sets the ViewEngine | |
*/ | |
export class Application { | |
start() { | |
// TODO: Start a router and only run page for current matching URL | |
throw new Error("Needs implemented"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import ReactDOM from "react-dom"; | |
/** | |
* ViewEngine | |
* - createElement: API compatible with JSX | |
* - mount: proxy ReactDOM.render() | |
*/ | |
export class ReactViewEngine { | |
createElement(...args) { | |
return React.createElement(...args); | |
} | |
mount(controller, views, mountPoint) { | |
return ReactDOM.render( | |
views.map((View, i) => this.createElement(View, { controller, key: i })), | |
mountPoint | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment