快速开始

要创建项目,请确保已安装 Node.js 16.x 或更高版本,并运行

  1. npm create "@enhance" ./enhance-demo -y

安装完成后,运行以下命令安装依赖,并启动本地开发服务器

  1. cd enhance-demo
  2. npm install
  3. npm start

应用启动后,导航到http://localhost:3333
image.png

VSCode 插件

如果安装了 Babel JavaScript 插件需要禁用才能使语法突出显示正常工作

TypeScript 类型定义

添加对应的 TypeScript 类型提示

自定义元素

image.png

  1. /**
  2. * @type {import('@enhance/types').EnhanceElemFn}
  3. */

image.png

API

image.png

  1. /** @type {import('@enhance/types').EnhanceApiFn} */

image.png

HTML head

  1. /** @type {import('@enhance/types').EnhanceHeadFn} */
  2. export default function Head(state) {
  3. //...
  4. }

image.png

解决 eslint 的 Parsing error: Unexpected token 错误

缺乏对应的类型声明时编辑器的提示不够友好,存在标红提示,所以需要
image.png

安装后不在有标红提示,如果没有生效,需要刷新下窗口才会更新
image.png
crtl+shift+p 打开面板然后输入reload window
image.png

目录结构

  1. app
  2. ├── api ............... data routes
  3. └── index.mjs
  4. ├── elements .......... custom element pure functions
  5. └── my-header.mjs
  6. └── pages ............. file based routing
  7. └── index.html

pages 页面

基于文件的路由

pages页面文件夹启用基于文件的路由。要添加路由,只需添加一个 HTML 文件。

比如:添加app/pages/about.html即添加了/about路由

  1. <main>
  2. this is the "/about" page
  3. </main>

image.png
项目路由如下: :::info app/pages/index.html → https://yoursite.com/
app/pages/about.html → https://yoursite.com/about :::

elements 自定义元素

elements目录下创建可重用的定制元素,相当于添加Web Components,方便组件复用。

:::info app/elements/my-message.mjs <my-message></my-message>
app/elements/my-link<my-link></my-link> ::: 划分目录 :::info app/elements/blog/comment → <blog-comment></blog-comment>
app/elements/blog/comment-form → <blog-comment-form></blog-comment-form> :::

app 下创建elements目录,添加basic-layout.msj

  1. /**
  2. * @type {import('@enhance/types').EnhanceElemFn}
  3. */
  4. export default function BasicLayout({ html, state }) {
  5. const { attrs } = state;
  6. const headTitle = attrs?.headtitle || "Default System Title";
  7. return html`
  8. <div class="basic-layout">
  9. <header class="header-wrap">
  10. <main class="header-content">
  11. ${headTitle}
  12. <slot name="headNav"></slot>
  13. </main>
  14. </header>
  15. <main>
  16. <slot name="main"></slot>
  17. </main>
  18. <slot name="footer"></slot>
  19. </div>
  20. <style>
  21. .basic-layout {
  22. width: 100vw;
  23. height: 100vh;
  24. overflow: auto;
  25. background-color: #fff;
  26. }
  27. .header-wrap {
  28. width: 100%;
  29. min-width: 12rem;
  30. margin: 0;
  31. padding: 0;
  32. position: sticky;
  33. top: 0;
  34. background: rgba(255, 255, 255, 0.1);
  35. box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.15);
  36. backdrop-filter: blur(15px);
  37. -webkit-backdrop-filter: blur(15px);
  38. z-index: 100;
  39. }
  40. .header-content {
  41. display: flex;
  42. justify-content: space-between;
  43. align-items: center;
  44. box-sizing: border-box;
  45. max-width: 75rem;
  46. min-height: 4rem;
  47. overflow: hidden;
  48. margin: auto;
  49. padding: 0 2rem;
  50. }
  51. ::slotted([slot="footer"]) {
  52. background: #f3f3f3;
  53. }
  54. </style>
  55. `;
  56. }

about.html

  1. <basic-layout headTitle="my-enhance-app">
  2. <main slot="main">
  3. <div class="about">
  4. this is the "/about" page
  5. </div>
  6. </main>
  7. </basic-layout>
  8. <style>
  9. .about {
  10. height: 1000px;
  11. }
  12. </style>

image.png

html

html是一个纯函数,这意味着给定相同的输入,它们每次都返回相同的输出,最终返回 html 模板字符串。

state

image.png
state 下包含 attrs 和 store 两个参数,attrs 包含了在自定义元素上设置的 html 属性

attrs

在自定义元素上设置属性
image.png
在自定义元素内可以通过 attrs 获取到
image.png

多设置几个属性
image.png
打印查看
image.png
image.png
可以发现 attrs 是一个包含了自定义元素的 html 属性的一个对象。

store

映射到当前页面的 api 数据。

具体示例结合后面的 api 一起展示,需要从 api 中获取数据。

slot 插槽

api 数据接口

api文件夹预配置为基于文件的路由公开数据。api 文件夹用于向应用添加数据。若要将数据传递到页面,请创建与项目 pages 文件夹中的现有文件同名的文件。
例如:app/api/index.mjs对应app/pages/index.mjs页面路由的 REST api

  1. app
  2. ├── api ............... data routes
  3. └── index.mjs
  4. └── pages ............. file based routing
  5. └── index.html

基本使用

  1. 创建 app/api/about.mjs 接口,返回数据 ```javascript /* @type {import(‘@enhance/types’).EnhanceApiFn} /

export async function get(req) { console.log(“🚀 ~ file: about.mjs:4 ~ get ~ req”, req); return { json: { message: “欢迎来到 about 页面!”, data: { date: “2022/12/13”, }, }, }; }

  1. 2. 创建 app/elements/my-about.mjs 元素展示数据
  2. ```javascript
  3. export default function MyAbout({ html, state }) {
  4. console.log("🚀 ~ file: my-about.mjs:2 ~ MyMessage ~ state", state);
  5. const { store } = state;
  6. const { message = "", data = { date: "" } } = store;
  7. return html` <p class="my-message">${message} ${data.date}</p> `;
  8. }
  1. 将元素 添加到 app/pages/about.html ```javascript

this is the “/about” page

  1. 查看页面<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/351630/1670899838524-bf51962e-e944-48a7-88ea-80c6ed522807.png#averageHue=%23fefefe&clientId=u9c9ae987-9441-4&from=paste&height=230&id=u14b473a3&originHeight=230&originWidth=1521&originalType=binary&ratio=1&rotation=0&showTitle=false&size=13384&status=done&style=stroke&taskId=udfea1972-c56b-4e9c-93d3-c083a4be64d&title=&width=1521)
  2. 打印数据查看<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/351630/1670899683684-79079589-4872-469b-8e1f-85107195c5aa.png#averageHue=%23292f3d&clientId=u9c9ae987-9441-4&from=paste&height=75&id=u04cef11c&originHeight=75&originWidth=540&originalType=binary&ratio=1&rotation=0&showTitle=false&size=27531&status=done&style=stroke&taskId=u159bafc7-b406-4efd-9138-a6076065e48&title=&width=540)<br />查看 api 的 request <br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/351630/1670899950177-6526c47f-f324-4212-9f84-a5727368ae1f.png#averageHue=%232a2e3c&clientId=u9c9ae987-9441-4&from=paste&height=738&id=u8108ab2e&originHeight=738&originWidth=814&originalType=binary&ratio=1&rotation=0&showTitle=false&size=468514&status=done&style=stroke&taskId=u0cd89344-a0a4-473c-842d-f1663221f4a&title=&width=814)
  3. <a name="v6Z8q"></a>
  4. ## public 静态资源
  5. CSS、图像和脚本等静态资产是任何 Web 应用程序的重要组成部分。enhance 提供了一种约定,通过`/_public/`从根公共目录识别和提供资源。
  6. <a name="NUQmM"></a>
  7. ### 添加文件
  8. 只需将文件拖放到 enhance 项目的公共文件夹中即可。可以使用您想要的任何类型的目录结构进行组织
  9. ```javascript
  10. .
  11. ├── app/ ............... dynamic app features
  12. └── public ............. static assets
  13. ├── blog-comment.mjs
  14. ├── docs.css
  15. └── img
  16. └── logo.png

引用文件

基于上述结构,您的应用程序可以包含来自以下路径的资产:/_public/

  1. <script type="module">
  2. import BlogComment from '/_public/blog-comment.mjs'
  3. // ...
  4. </script>
  5. <link rel="stylesheet" href="/_public/docs.css">
  6. <img src="/_public/img/logo.png" />

HTML head 头

head 是应用的一个非常重要的自定义点。您将需要添加自定义标题,网站图标,社交开放图元等内容。
head 不能包含自定义元素。只有一部分现有的预定义 HTML 标签可以包含在 head 中 ,比如 meta、link等。

默认头部组件

enhance 附带了基本的默认头部内容

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1">
  6. <title></title>
  7. <link rel="stylesheet" href="/enhance-styles.css">
  8. <link rel="icon" href="/_public/favicon.svg">
  9. </head>

image.png

自定义 head

要提供您自己的自定义头部内容,将 /app/head.mjs 文件添加到您的项目中

  • store:映射到当前页面的 API 数据
  • req:标准请求对象
  • error:如果发生错误,则会显示错误消息,以便您可以向站点的用户发送消息
  • status:使您能够正确处理的状态代码 ```javascript import { getLinkTag } from ‘@enhance/arc-plugin-styles/get-styles’

export default function Head(state) { const { store, status, req, error } = state const { path } = req const title = My app — ${path} return <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>${title}</title> ${getLinkTag()} <link rel="icon" href="/_public/favicon.svg"> </head> }

  1. 添加`head.mjs`前<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/351630/1670901588790-31f25dbc-10f4-4903-b448-de7941293d4a.png#averageHue=%23e8e7e6&clientId=u9c9ae987-9441-4&from=paste&height=95&id=ymdGu&originHeight=95&originWidth=290&originalType=binary&ratio=1&rotation=0&showTitle=false&size=5584&status=done&style=stroke&taskId=ubfa4a4b2-c05e-4682-93d8-bbeff27e460&title=&width=290)<br />添加后<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/351630/1670901710407-715a1f94-0943-4e98-9da9-d5e3c2935b06.png#averageHue=%23ebeae9&clientId=u9c9ae987-9441-4&from=paste&height=85&id=u8a95c85c&originHeight=85&originWidth=292&originalType=binary&ratio=1&rotation=0&showTitle=false&size=5864&status=done&style=stroke&taskId=udf5194ab-d169-4857-94e5-921c8b68914&title=&width=292)
  2. <a name="Hzsl9"></a>
  3. ### templates 非自定义元素模板
  4. 可以为预定义的 HTML 标记定义模板,添加`/app/templates/twitter-meta.mjs`如下所示:
  5. ```javascript
  6. export default function TwitterMeta(state) {
  7. const { title, description, image, card } = state
  8. return `
  9. <meta name="twitter:title" content="${title}">
  10. <meta name="twitter:description" content="${description}">
  11. <meta name="twitter:image" content="${image}">
  12. <meta name="twitter:card" content="${card}">
  13. `
  14. }

head.mjs中使用此元内容模板:

  1. import { getLinkTag } from "@enhance/arc-plugin-styles/get-styles";
  2. import TwitterMeta from "./templates/twitter-meta.mjs";
  3. /** @type {import('@enhance/types').EnhanceHeadFn} */
  4. export default function Head(state) {
  5. const { store, status, req, error } = state;
  6. const { path } = req;
  7. const title = `My app ${path}`;
  8. return `
  9. <!DOCTYPE html>
  10. <html lang="en">
  11. <head>
  12. <meta charset="utf-8">
  13. <meta name="viewport" content="width=device-width, initial-scale=1">
  14. ${TwitterMeta(store)}
  15. <title>${title}</title>
  16. ${getLinkTag()}
  17. <link rel="icon" href="/_public/favicon.svg">
  18. </head>
  19. `;
  20. }

404 和 500 错误页

pages添加 404.html404.mjs500.html500.mjs/

app/pages/404.mjs

  1. export default function FourOhFour({ html, state }) {
  2. console.log("🚀 ~ file: 404.mjs:2 ~ FourOhFour ~ state", state);
  3. const { error } = state.attrs;
  4. return html`
  5. <main>
  6. <h1>Not Found - 404</h1>
  7. <h2>Sorry we can't find that.</h2>
  8. <p>${error && error}</p>
  9. </main>
  10. `;
  11. }

image.png
image.png

style 样式

默认情况下,样式的范围限定为自定义元素,可以添加