Hyperapp是一个JavaScript库,用于构建功能丰富的Web应用程序。 它结合了实用的Elm启发式状态管理方法和支持键更新和生命周期事件的VDOM引擎-所有这些都无需依赖。 提供或占用几个字节,将整个源代码缩小并压缩到大约1 KB。

在本教程中,我将向您介绍Hyperapp,并引导您完成一些代码示例,以帮助您立即上手。 我假定对HTML和JavaScript有所了解,但是不需要具有其他框架的先前经验。

你好,世界

我们将从一个简单的演示开始,该演示显示所有运动部件如何协同工作。

您也可以在线尝试代码 。

import { h, app } from "hyperapp"
// @jsx hconst state = {count: 0
}const actions = {down: () => state => ({ count: state.count - 1 }),up: () => state => ({ count: state.count + 1 })
}const view = (state, actions) => (<div><h1>{state.count}</h1><button onclick={actions.down}>-</button><button onclick={actions.up}>+</button></div>
)app(state, actions, view, document.body)

这几乎是每个Hyperapp应用程序的外观。 单个状态对象,填充状态的动作以及将状态和动作转换为用户界面的视图。

在app函数内部,我们复制了您的状态和动作(对我们不拥有的对象进行突变是不礼貌的)并将它们传递给视图。 我们还会包装您的操作,以便它们在每次状态更改时重新呈现应用程序。

app(state, actions, view, document.body)

状态是描述您的应用程序数据模型的普通JavaScript对象。 这也是一成不变的。 要更改它,您需要定义动作并调用它们。

const state = {count: 0
}

在视图内部,您可以显示状态的属性,使用它来确定应该显示或隐藏UI的哪些部分,等等。

<h1>{state.count}</h1>

您还可以将操作附加到DOM事件,或在自己的内联事件处理程序中调用操作。

<button onclick={actions.down}>-</button>
<button onclick={actions.up}>+</button>

动作不会直接改变状态,而是会返回状态的新片段。 如果您尝试使操作中的状态发生变化然后返回它,则视图将不会像您期望的那样重新呈现。

const actions = {down: () => state => ({ count: state.count - 1 }),up: () => state => ({ count: state.count + 1 })
}

应用程序调用返回连接到状态更新视图-渲染周期的操作对象。 您还可以在视图函数内和操作内收到该对象。 将此对象暴露给外界非常有用,因为它使您可以从另一个程序,框架或原始JavaScript与您的应用程序对话。

const main = app(state, actions, view, document.body)setTimeout(main.up, 1000)

关于JSX的说明

为了熟悉本文,我将在整个本文档中使用JSX ,但是您不需要将JSX与Hyperapp一起使用。 替代方法包括内置的h函数, @ hyperapp / html , hyperx和t7 。

这是使用@ hyperapp / html的相同示例。

import { app } from "hyperapp"
import { div, h1, button } from "@hyperapp/html"const state = { count: 0 }const actions = {down: () => state => ({ count: state.count - 1 }),up: () => state => ({ count: state.count + 1 })
}const view = (state, actions) =>div([h1(state.count),button({ onclick: actions.down }, "–"),button({ onclick: actions.up }, "+")])app(state, actions, view, document.body)

虚拟DOM

虚拟DOM使用称为虚拟节点的嵌套JavaScript对象树来描述DOM的外观。

{name: "div",props: {id: "app"},children: [{name: "h1",props: null,children: ["Hi."]}]
}

应用程序的虚拟DOM树在每个渲染周期都从头开始创建。 这意味着我们每当状态更改时都调用view函数,并使用新计算的树来更新实际DOM。

通过将新的虚拟DOM与先前的虚拟DOM进行比较,我们尝试在尽可能少的DOM操作中做到这一点。 这导致了高效率,因为通常只需要更改一小部分节点,并且与重新计算虚拟DOM相比,更改实际DOM节点的成本很高。

为了帮助您以更紧凑的方式创建虚拟节点,Hyperapp提供了h函数。

import { h } from "hyperapp"const node = h("div",{id: "app"},[h("h1", null, "Hi.")]
)

创建虚拟节点的另一种方法是使用JSX 。 JSX是一种JavaScript语言扩展,用于表示动态HTML。

import { h } from "hyperapp"const node = (<div id="app"><h1>Hi.</h1></div>
)

浏览器不了解JSX,因此我们需要将其编译为h函数调用,因此需要导入h语句。 让我们看看如何使用babel进行此过程。

首先,安装依赖项:

npm i babel-cli babel-plugin-transform-react-jsx

然后创建一个.babelrc文件:

{"plugins": [["transform-react-jsx",{"pragma": "h"}]]
}

并从命令行编译代码:

npm run babel src/index.js > index.js

如果您不想使用构建系统,则还可以从CDN加载unappkg之类的Hyperapp ,它将通过window.hyperapp对象全局可用。

例子

Gif搜索框

在此示例中,我将向您展示如何使用Giphy API异步更新状态以构建Gif搜索框

为了产生副作用,我们在回调或承诺被解决时在其他动作中调用动作。

返回nullundefinedPromise对象的操作不会触发视图重新渲染。 如果操作返回了一个承诺,我们将把该承诺传递给调用方,使您可以像下面的示例一样创建异步操作。

现场例子

import { h, app } from "hyperapp"
// @jsx hconst GIPHY_API_KEY = "dc6zaTOxFJmzC"const state = {url: "",query: "",isFetching: false
}const actions = {downloadGif: query => async (state, actions) => {actions.toggleFetching(true)actions.setUrl(await fetch(`//api.giphy.com/v1/gifs/search?q=${query}&api_key=${GIPHY_API_KEY}`).then(data => data.json()).then(({ data }) => (data[0] ? data[0].images.original.url : "")))actions.toggleFetching(false)},setUrl: url => ({ url }),setQuery: query => ({ query }),toggleFetching: isFetching => ({ isFetching })
}const view = (state, actions) => (<div><input type="text"placeholder="Type here..."autofocusonkeyup={({ target: { value } }) =/> {if (value !== state.query) {actions.setQuery(value)if (!state.isFetching) {actions.downloadGif(value)}}}}/><div class="container"><img src={state.url}style={{display: state.isFetching || state.url === "" ? "none" : "block"}}/></div></div>
)app(state, actions, view, document.body)

该状态存储Gif URL的字符串,搜索查询和一个布尔标志,以了解浏览器何时获取新的Gif。

const state = {url: "",query: "",isFetching: false
}

当浏览器繁忙时, isFetching标志用于隐藏Gif。 没有它,最后一次下载的Gif将显示为请求另一个Gif。

<img src={state.url}style={{display: state.isFetching || state.url === "" ? "none" : "block"}}
/>

该视图由文本输入和显示Gif的img元素组成。

为了处理用户输入,使用了onkeyup事件,但是onkeydownoninput也可以工作。

在每个按键actions.downloadGif被称为一个新的GIF动画的要求,但只有在获取尚未挂起和文字输入不是空的。

if (value !== state.query) {actions.setQuery(value)if (!state.isFetching) {actions.downloadGif(value)}
}

actions.downloadGif内部,我们使用提取 API从Giphy请求Gif URL。

fetch完成后,我们将在promise中接收带有Gif信息的有效负载。

actions.toggleFetching(true)
actions.setUrl(await fetch(`//api.giphy.com/v1/gifs/search?q=${query}&api_key=${GIPHY_API_KEY}`).then(data => data.json()).then(({ data }) => (data[0] ? data[0].images.original.url : ""))
)
actions.toggleFetching(false)

接收到数据后,将调用actions.toggleFetching (这允许进行进一步的提取请求),并通过将获取的Gif URL传递给actions.setUrl来更新状态。

TweetBox克隆

在此示例中,我将向您展示如何创建自定义组件,以将UI组织成可重用的标记并构建简单的TweetBox克隆。

现场例子

import { h, app } from "hyperapp"
// @jsx hconst MAX_LENGTH = 140
const OFFSET = 10const OverflowWidget = ({ text, offset, count }) => (<div class="overflow"><h1>Whoops! Too long.</h1><p>...{text.slice(0, offset)}<span class="overflow-text">{text.slice(count)}</span></p></div>
)const Tweetbox = ({ count, text, update }) => (<div><div class="container"><ul class="flex-outer"><li><textarea placeholder="What's up?" value={text} oninput={update}></textarea></li><li class="flex-inner"><span class={count > OFFSET ? "overflow-count" : "overflow-count-alert"}>{count}</span><button onclick={() => alert(text)}disabled={count >= MAX_LENGTH || count < 0}>Tweet</button></li></ul>{count < 0 && (<OverflowWidgettext={text.slice(count - OFFSET)}offset={OFFSET}count={count}/>)}</div></div>
)const state = {text: "",count: MAX_LENGTH
}const view = (state, actions) => (<tweetbox text={state.text}count={state.count}update={e => actions.update(e.target.value)}/>
)const actions = {update: text => state => ({text,count: state.count + state.text.length - text.length})
}app(state, actions, view, document.body)

状态存储消息的文本和剩余字符count ,已初始化为MAX_LENGTH

const state = {text: "",count: MAX_LENGTH
}

该视图由我们的TweetBox组件组成。 我们使用属性/属性将数据传递到小部件中。

const view = (state, actions) => (</tweetbox><tweetbox text={state.text}count={state.count}update={e => actions.update(e.target.value)}/>
)

当用户输入输入内容时,我们调用actions.update()来更新当前文本并计算剩余字符。

update: text => state => ({text,count: state.count + state.text.length - text.length
})

从前一个文本的长度中减去当前文本的长度,可以告诉我们剩余字符的数量如何变化。 因此,剩余字符的新计数是旧计数加上上述差异。

输入为空时,此操作等于(MAX_LENGTH - text.length)

state.count小于0时,我们知道state.text必须大于MAX_LENGTH ,因此我们可以禁用tweet按钮并显示OverflowWidget组件。

<button onclick={() => alert(text)} disabled={count >= MAX_LENGTH || count < 0}>Tweet
</button>

state.count === MAX_LENGTH ,tweet按钮也被禁用,因为这意味着我们尚未输入任何字符。

OverflowWidget标记显示消息的不允许部分以及上下文的一些相邻字符。 常量OFFSET告诉我们有多少个额外的字符可以分割state.text

<overflowwidget text={text.slice(count - OFFSET)}offset={OFFSET}count={count}></overflowwidget>

通过将OFFSET传递给OverflowWidget,我们可以进一步分割text并将overflow-text类应用于特定的溢出部分。

<span class="overflow-text">{text.slice(count)}</span>

与React的比较

从概念上讲,Hyperapp和React有很多共同点。 这两个库都使用虚拟DOM,生命周期事件和基于密钥的协调。 Hyperapp的外观和感觉很像React和Redux,但样板更少。

React将视图的概念推广为状态的函数。 Hyperapp通过内置的,受Elm启发的状态管理解决方案使这一想法更进一步。

Hyperapp拒绝仅依赖纯功能组件的本地组件状态的想法。 这意味着高可重用性,廉价的备忘录和简单的测试。

最后的想法

由于Hyperapp是如此之小,因此与几乎任何其他替代方案相比,它在网络上的传输速度更快,解析速度也更快。 这意味着需要学习的概念更少,错误更少,框架稳定性更高。

我从来都不喜欢大型框架。 不是因为它们不好,而是因为我想编写自己的JavaScript,而不是框架要我使用的JavaScript。 我想要的是可转让的技能。 我想提高JavaScript的技能,而不是将技能提高到框架中。


要了解有关Hyperapp的更多信息,请查看官方文档,并在Twitter上关注我们以获取更新和公告。

From: https://www.sitepoint.com/hyperapp-1-kb-javascript-library/

HyperApp:用于构建前端应用程序的1 KB JavaScript库相关推荐

  1. 42个面向前端开发人员的很棒JavaScript 库和框架

    英文 | https://javascript.plainenglish.io/42-good-javascript-libraries-and-frameworks-for-front-end-de ...

  2. html getelementbyid 修改图片_如何使用HTML、CSS和JS轻松构建桌面应用程序

    HTML,CSS和JavaScript语言是否可以真正用于构建桌面应用程序? 答案是肯定的. 在这篇文章中,我们将主要关注Electron如何使用HTML.CSS和Javascript等网络技术来创建 ...

  3. 如何使用 JavaScript 构建计算器应用程序

    这个史诗般的教程通过描述如何使用该语言开发一个简单的计算器应用程序,为 JavaScript 新手提供了一个可靠的练习. 面向初学者的 javascript 项目(8 部分系列) 1 构建你的第一个 ...

  4. 用于构建集成式桌面应用程序的新指南和新工具(转载于MSDN)

    发布日期: 2006-10-30 | 更新日期: 2006-10-30 Christian Thilmany 和 Jim Keane 本文将介绍以下内容: • CAB 和 Smart Client S ...

  5. Skeljs – 用于构建响应式网站的前端开发框架

    skelJS 是一个轻量级的前端框架,用于构建响应式站点和应用程序.让设计人员和开发人员可能够使用四个强大的组件:CSS 网格系统,响应式处理程序,CSS 的快捷方式和插件系统. 您可能感兴趣的相关文 ...

  6. 前端复盘: knockout + require + director 构建单页面程序

    关注并将「趣谈前端」设为星标 每早08:30按时推送技术干货/优秀开源/技术思维 目前react,vue,angular等框架都支持单页面程序,最近在回顾一些知识,想起刚毕业的时候接触到knockou ...

  7. python PyQt5 QMainWindow类(Qt主窗口框架,主窗口提供了用于构建应用程序用户界面的框架)

    https://doc.qt.io/qtforpython/PySide2/QtWidgets/QMainWindow.html?highlight=qmainwindow#PySide2.QtWid ...

  8. Foundatio - .Net Core用于构建分布式应用程序的可插拔基础块

    简介 Foundatio - 用于构建分布式应用程序的可插拔基础块 •想要针对抽象接口进行构建,以便我们可以轻松更改实现.希望这些块对依赖注入友好.•缓存:我们最初使用的是开源 Redis 缓存客户端 ...

  9. 用于构建高级媒体应用程序的工具

    在前些天闭幕的//Build/大会上,微软媒体平台部的首席布道师Mike Downey检视了用于Windows 8应用程序开发的工具和框架,其特性包括高级媒体播放功能,像流媒体,DVR控制.广告和关闭 ...

最新文章

  1. 第11章 UART 串口通信(手把手教你学51单片机pdf部分)
  2. 苹果iOS 15发布:关机也能定位,ASMR重度用户狂喜,这波库克又“去苹果化”了...
  3. python【力扣LeetCode算法题库】46- 全排列
  4. 详解void 0与undefined区别
  5. go 并发安全map 分段锁实现
  6. linux7安装EMC的多路径,Oracle Linux 7.8 多路径(Multipath)+Udev绑定磁盘
  7. mysql+存储过程+模式,Mysql(7)---存储过程
  8. redis 缓存模式
  9. 数据结构学习(一)数组
  10. koa2 mysql项目教程_blogs: Node.js + Koa2 + MySQL + Vue.js 实战开发一套完整个人博客项目网站...
  11. java架构师之路-并发编程
  12. matlab中whos怎么用,【安富莱DSP教程】第3章 Matlab 简易使用(一)
  13. c4d流体插件_C4D常用最火14款插件合集,总有一款你想要的!
  14. 不用爬虫,也能写一个聚合搜索引擎
  15. 手机开USB热点给电脑使用失败
  16. uboot什么意思(uboot fastboot)
  17. python excel转csv两列互换,python excel转换csv代码实例
  18. 鸡尾酒排序算法c语言源代码,排序算法之鸡尾酒排序
  19. 基金的小尾巴ABCDEH介绍以及思考方法论
  20. python 做表格分析难么_Python处理分析128张Excel表格竟然不到3秒?

热门文章

  1. 基于滑膜控制的后轮主动(ARS)和DYC的协调稳定性控制,上层ARS产生期望后轮转角度
  2. 在kali中打开终端模拟器—使用命令行
  3. 三菱FX3U PLC如何开启外部输入中断
  4. 生产环境下nginx代理跨域解决
  5. Java项目:Springboot物流管理系统
  6. arm linux gige相机,Teledyne DALSA发布Linux系统下GigE开发包2.10V版本
  7. ARM V8 base instruction -- WFE
  8. Spring Boot实战,整合Prometheus实现应用监控
  9. Docker学习笔记1——Docker简介(幕布笔记)
  10. [JS逆向案例]诸葛找房Cookie之acw_sc__v2分析