-
Notifications
You must be signed in to change notification settings - Fork 781
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
What are the design goals of this project? 🎯 #9
Comments
I would like to know, too. |
I was building a web client for a project at work. My first choice was React+Redux, since that's what we already use, but I wanted something more lightweight and without the frameworkyness of React. I made the first prototype using Elm, which I really like, but it was too difficult to integrate with 3rd party components, e.g. CodeMirror. yo-yo/chooyo-yo is an abstraction on top of bel and morphodom (which mutates DOM nodes directly) whereas I preferred a virtual DOM approach like Snabbdom. There's choo too, an abstraction on top of yo-yo with a much nicer API.
Hyperapp~1kb. It's almost vanilla. No deps, other than Hyperx (itself no deps) which is how we write HTML using JavaScript, but without breaking JavaScript. You can still use JSX if you want. Hyperapp has Elm-like state management, a router and a tiny virtual dom implementation with SVG support, inline CSS, boolean HTML props and create, update and remove events for DOM nodes. Integrating 3rd party components with Hyperapp is easy too. See this example with CodeMirror. CompareLet's see a input box + heading example. Hyperappconst { app, html } = require("hyperapp")
app({
model: "",
update: {
text: (_, value) => value
},
view: (model, msg) => html`
<div>
<h1>Hello ${model}</h1>
<input oninput=${e => msg.text(e.target.value)} />
</div>`
}) Chooconst html = require("choo/html")
const choo = require("choo")
const app = choo()
app.model({
state: { title: "" },
reducers: {
update: (state, data) => ({ title: data })
}
})
const mainView = (state, prev, send) => html`
<main>
<h1>Hello ${state.title}</h1>
<input type="text" oninput=${e => send("update", e.target.value)}>
</main>
`
app.router(["/", mainView])
const tree = app.start()
document.body.appendChild(tree) Mercuryvar document = require("global/document")
var hg = require("mercury")
var h = require("mercury").h
function App() {
var state = hg.struct({
text: hg.value(""),
handles: hg.value(null)
})
state.handles.set(hg.handles({
change: setText
}, state))
return state
}
function inputBox(value, sink) {
return h("input.input", {
value: value,
name: "text",
type: "text",
"ev-event": hg.changeEvent(sink)
})
}
App.render = function render(state) {
return h("div", [
h("p.content", "Hello " + state.text),
h("p", [
"Change it here: ",
inputBox(state.text, state.handles.change)
])
])
}
function setText(state, data) {
state.text.set(data.text)
}
hg.app(document.body, App(), App.render) Cyclejsconst { run } = require("@cycle/xstream-run")
const { div, label, input, hr, h1, makeDOMDriver} = require("@cycle/dom")
function main(sources) {
const sinks = {
DOM: sources.DOM.select(".field").events("input")
.map(ev => ev.target.value)
.startWith("")
.map(name =>
div([
label("Name:"),
input(".field", { attrs: { type: "text" } }),
hr(),
h1("Hello " + name),
])
)
}
return sinks
}
run(main, {
DOM: makeDOMDriver("#app-container")
}) Mithril
const m = require("mithril")
var name = ""
const helloWorld = {
view: _ => [
m("h1", "Hello " + name),
m("input", {
value: name,
oninput: e => name = e.target.value
})
]
}
m.mount(document.body, helloWorld) |
Thanks for the awesome explanation @jorgebucaran. Did you end up using this library for your work project? How has that been? Do you have plans for the future direction of this repo? I agree with your points, that's basically where I'm at too. yoyo and choo I think are very cool experiments, but some of the design decisions have created some extra complexity. The namespace/state pattern, and direct dom mutation have made some things difficult (not to say that I've made something nicer). Though also choo has grown a lot, which may have added more to the scope. Can you elaborate on the use of MutationObserver and code smell? |
hey @jorgebucaran I know you from I'm amazed by the simplicity of the code, I really like it. Some comments/questions in my head right now: (1) are you planning to add tests to the library? I wouldn't feel comfortable using it in production without… (2) since this is somewhat similar to (3) the only thing I would miss are "hooks" for elements (like in |
Yes I was thinking the same things @acstll :). Very nice experiment in finding the most minimal implementation of the elm pattern, and the code is so simple. Was also wondering about what tests would look like. |
Did you end up using this library for your work project?Yes. I upgraded our project to use Hyperapp from yo-yo. Can you elaborate on the use of MutationObserver and code smell?It seems lifecycle events don't make sense if you are working directly with the DOM, e.g. using morphodom. The DOM has no onload/onunload for individual elements. In order to support on load/unload events for DOM elements they use the MutationObserver API which adds more complexity to their architecture (MutationObserver is only supported in IE11 too). Are you planning to add tests to the library?Yes. Soon! 🙇 Include the above explanation in the README / mention chooTotally. Maybe we can add a FAQ in the future! Does Hyperapp support hooks like Snabbdom?Yes. It's just missing in the docs. The term we'll use is _lifecycle methods, since we're already using hooks for something else. Lifecycle Methods
Examplesapp({
view: _ => html`
<div oncreate=${e => console.log(e)}>Hi.</div>`
}) Advanced Exampleapp({
model: 0,
update: {
toggle: model => model === 0 ? 1 : model === 1 ? 2 : 0
},
view: (model, msg) => html`
<div>
${model > 0
? html`
<ul>
<li style=${{ color: model === 1 ? "inherit" : "deepskyblue" }}>
Leonardo
</li>
<li style=${{ color: model === 1 ? "inherit" : "orange" }}>
Michelangelo
</li>
<li style=${{ color: model === 1 ? "inherit" : "red" }}>
Raphael
</li>
<li style=${{ color: model === 1 ? "inherit" : "purple" }}
onupdate=${_ => console.log("UPDATE")}
oncreate=${_ => console.log("CREATE")}
onremove=${_ => console.log("REMOVE")}>Donatello
</li>
</ul>`
: html`
<ul>
<li>Krang</li>
</ul>`
}
<button onclick=${msg.toggle}>Mutate!</button>
</div>`,
}) |
Bonus: The virtual DOM approach is faster in most benchmarks compared to morphodom. |
A lot has changed since you opened this issue @nichoth 👋. The core values of the project still remain to be a small (or the smallest) JavaScript frontend framework that is useful out of the box and implements a sane subset of the Elm Architecture, supports Hyperx, JSX and it's easy to learn. |
Hi. Cool repo. I was wondering if you have goals for the project and how they might differ from existing libraries (there are so many). For example,
choo
comes to mind as having a similar elm-like design.The text was updated successfully, but these errors were encountered: