cyra
Version:
single page application view engine
319 lines (194 loc) • 11.1 kB
Markdown
# Cyra
## 1. 如何开始
```js
// main.js
import { Cyra } from 'cyra';
import home from './view/home';
Cyra.initApp({
root: 'body', // 项目跟容器
default: 'home' // 默认视图
routes: { // 视图路由设置
home: home
}
});
// home.js
import { Page } from 'cyra';
class HomePage extends Page {
// 定义了该函数后可以在进入视图时候改变页面title
title () {
return 'HOME-TITLE';
}
// 以下函数如若未做任何事,可以省略不写
initialize (next) {
next();
}
willAppear (next) {
this.container.innerHTML = 'Hello World';
next();
}
didAppear (next) {
next();
}
willDisappear (next) {
next();
}
}
export default HomePage;
```
## 2. 基础思想
Cyra 设计三个简单的概念 **Page**, **Route** 和 **AppStorage** 来帮助开发者处理复杂的视图切换逻辑、数据传递及视图生命周期管理。
在移动端 SPA 架构中,有以下几个重要的模块:
### 2.2 视图导航
所有导航动作被封装成在 Page.switchRoute 中,你可以在该方法中传递参数。
使用 Cyra 的单页应用可以在任何情况下刷新,Cyra 的框架设计会帮助你处理任何复杂的产品逻辑。
### 2.3 视图管理及内容布局
Cyra 会管理所有视图的生命周期,你可以轻松获悉每一个视图的执行阶段,并针对阶段进行操作。
Cyra 为每一个视图提供一个容器,用户可以在这个容器内自由发挥。
### 2.4 视图之间数据交互
数据传递在使用 Cyra 后会变得无比简单,我们提供 URL 传递及**弱数据**传递, 我们会在后面详细介绍。
### 2.5 服务器数据交互
关于服务器数据交互我们什么都不会做,完全由用户自由发挥。
### 2.6 兼容性
在 Cyra 的设计中,我们考虑了最大的兼容性,您可以通过配置使用 **History API** + **多页降级** 作为路由方式,也可以使用 **Hash** 作为路由方式。
## 3. 视图生命周期
### 3.1 周期图说明
1. 橙色的 entering,leaving 代表视图两大过程, 进入和离开。
2. 最左边的 disappeared,appeared 代表两大状态,显示和隐藏。
3. 其中 initialize, willAppear, didAppear, willDisappear 是用户可以自定义的钩子函数。
4. appearing,disappearing是系统内部的函数过程,主要控制视图的隐藏和展现。如果想要在视图展现和隐藏时添加动画,可改写这两个方法的默认控制,请参见的转场动画。
### 3.2 生命周期
1. 当 url 的 view 部分值(默认路径为 initApp 中传入的 default)匹配到相关的route,其对应的视图开始执行 entering 过程。
2. 视图第一次执行 entering 过程时,依次执行 initialize, willAppear, (appearing), didAppear,若未定义则跳过,若在这其中某一步未调用 next() 也会中断执行。
3. 当视图第二次执行 entering 过程,默认不再执行 initialize, willAppear,如若更改该行为请参见的如何控制重新加载。
5. 当一个页面开始执行 entering 过程,则上一个页面开始执行 leaving 过程,即 willDisappear(disappearing)。
## 4. 使用指导
* 提倡组件层面抽象,减少视图抽象。
* 将视图渲染、数据获取等操作放到视图中最合适的阶段中。
* 强数据传递尽量传递查询参数以保持视图独立,并保证 URL 不会太长。
* 弱数据传递需要做好足够的判断,以保证逻辑的健壮。
# API 文档
## 1. Cyra
#### Cyra.initApp (obj: InitAppObject): void
初始化 Cyra 环境,参数配置如下。
`index: string (required)` 指定默认路由
`root: string (required)` 容器 DOM id
`routes: RouteData (required)` 路由信息
`mode: string (optional)` 路由模式,默认为`'history'`(会自动降级为`'multipage'`),可选`'hash'`
`appRoot: string (optional)` 配合 History API 方式设置的项目虚拟目录,如`'/resource/wa/oneyuan/'`
`paramPrefix: string (optional)` 强数据在 URL 中的前缀,默认为`''`
`alwaysReload: boolean (optional)` 强制每次进入视图刷新,默认为`false`
`dataSplit: (optional)` 'hash' 模式下强数据传参格式
`copyIndex: string (optional)` copyIndex 在 URL 中的前缀,默认为`cpx`
`animation: boolean (optional)` 是否开启视图切换动画,默认为`false`
`animationPrefix: string (optional)` 视图切换动画所加载 CSS class 的前缀,默认为`''`
`animationFunc: string (optional)` 视图切换动画的`timing-function`,默认为`''`
`switchDuration: number (optional)` 视图切换动画持续时间,默认`320`毫秒
#### router: Router
获取 Cyra 上的 router 实例
## 2. Page
和 Page 相关的主要是一个视图的生命周期函数,以及一些简单的 helper 用来设置页面环境。
### 2.1 钩子函数
#### initialize (next: Function): void
视图所属容器显示之前(`display: none`)调用,需要执行`next()`进入下一个生命周期。
#### willAppear (next: Function): void
功能同`initialize`,遗留问题,建议视图展示之前的业务逻辑都写在`willAppear`中,和业务相关的独立逻辑建议拆分成 Page 的实例方法,而不要分散在`initialize`和`willAppear`中。
#### didAppear (next: Function): void
视图所属容器显示之后(`display: block`)调用。
#### beforeEntering (next: Function): void
`initialize`和`willAppear`在 Page 的`shouldReload()`返回`false`时不会再次执行,也就是第二次进入相同视图时不会重复执行,如果需要在页面展示前,无论`shouldReload()`返回结果如何都要执行,可以将代码写在下面的钩子函数中:
### 2.2 helper 函数
#### title (): string
用来设置视图的 title
#### shouldReload (previousPath: string): boolean
用来指定视图第二次之后进入时,是否执行`initialize`和`willAppear`两个钩子函数。
#### switchRoute (path: string, data?: any, copyIndex?: number): void
指向`Cyra.router.switchRoute`,具体用法见对应词条。
#### popAndSwitchRoute (popValue: number, path: string, data?: any, copyIndex?: number): void
指向`Cyra.router.popAndSwitchRoute`,具体用法见对应词条。
#### reload (): void
重新加载当前视图,并且会执行`initialize`和`willAppear`两个钩子函数。
#### prepareForSwitch (next: Function, toPath: string, destinationPagePerform: Function): void
在视图执行`switchRoute()`跳转前执行,弱数据实现方式,可以通过`destinationPagePerform`执行目标视图中的方法,`toPath`指示下一个视图的`path`。执行`next()`来完成跳转,否则停留在当前视图。
#### beforeLeaving (next: Function, cancel: Function, toPath: string): void
离开视图时执行,`toPath`指示即将进入的视图,执行`next()`进入下一视图,执行`cancel()`取消此次跳转。
### 2.3 helper 属性
#### context: ContextType
指向`Cyra.router.context`,详见对应词条。
## 3. Router
Router 主要负责页面间的跳转,初始化 Cyra 后,可以通过 Cyra.router 来完成视图见跳转相关操作。
#### switchRoute (path: string, data?: any, copyIndex?: number, isShadow: boolean = false): void
执行视图跳转,`path`为即将进入的视图的`path`,`data`为传递的强数据,`copyIndex`指示 Mix 页的索引。为了方便,在 Page 中添加同名 helper,这样在视图中,只要执行`this.switchRoute`即可完成跳转,在非视图代码中,还是可以通过`Cyra.router.switchRoute`进行跳转。`isShadow`表示此次跳转是否使用`replace`模式,也就是用新的视图提前当前视图,从而将当前视图从 WebView 中清除(new in v2.1.2)。
**注意:**`isShadow`参数作用和`popAndSwitchRoute`作用类似,都是从 WebView 历史中清除1项或若干项,然后执行跳转;但`popAndSwitchRoute`不适用于项目第1个视图的此类跳转,因为先返回会使得退出当前项目,所以需要使用`replace`(对应 History API 中的`replaceState`和多页/Hash 中的`window.location.replace`)来替换当前历史。但`isShadow`无法清除多条历史记录,而后者可以。
#### popAndSwitchRoute (popValue: number, path: string, data?: any, copyIndex?: number): void
功能类似`switchRoute`,但会在跳转前先后退`popValue`个页面。
#### context: ContextType
当前程序中的环境变量信息。
* `rootContainer: HTMLElement`:Cyra 根容器 DOM id;
* `useSwitch: boolean`:指示当前一次跳转是否为执行`switchRoute`跳转;
* `currentRoute: Route`:当前视图对应的`Route`对象;
* `currentPage: Page`:当前视图所属的`Page`对象;
* `currentContainer: HTMLElement`:当前展示视图的 DOM 容器;
* `previousPage: Page`:上一视图所属的`Page`对象。
## 4. 视图切换动画
视图间切换动画需要按照如下步骤:
1. 在`Cyra.initApp`中设置`animation`为`true`
2. 可添加以下可选参数进行动画配置,动画基于`CSS Animation`:
* `switchDuration: number`:指示动画切换持续时间,单位`ms`,默认`320`
* `animationPrefix: string`:自定义动画`keyframes`前缀,默认`''`
* `animationFunc: string`:自定义动画`timing-function`,默认为`''`
3. 在页面中添加以下4个 CSS keyframes:
* `left-move-in`:视图从屏幕左侧进入并显示的动画
* `left-move-out`:视图向屏幕左侧滑出并隐藏的动画
* `right-move-in`:视图从屏幕右侧进入并显示的动画
* `right-move-out`:视图向屏幕右侧滑出并隐藏的动画
4. 为了方便,给出一个示例:
```html
<style>
@keyframes left-move-in {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
@keyframes left-move-out {
from {
transform: translateX(0);
}
to {
transform: translateX(-100%);
}
}
@keyframes right-move-in {
from {
transform: translateX(100%);
}
to {
transform: translateX(0);
}
}
@keyframes right-move-out {
from {
transform: translateX(0);
}
99% {
transform: translateX(100%);
}
to {
transform: translateX(-100%);
}
}
</style>
```
**注意:**`right-move-out`比较重要,视图向右侧滑出时,需要在动画完成之前全部滑出,并在最后将视图重新置在屏幕可视区域左侧隐藏。
## 5. Nginx 配置
当采用`History API`路由模式时,也就是`mode`设置为`'history'`或`''`时,Nginx 需要做相应的配置,以保证直接访问视图的 URL 时可以正常找到 HTML 资源并正确路由。具体配置如下:
```nginx
# match img resource
location ~* ^/resource/wa/([\w-.]+)/([\w-.]+)(/.*)?$ {
root /resource_static/;
try_files /resource/$1/$2/$3 /resource/$1/$2 /resource/$1/$3 /resource/$1/$2.html =404;
}
```
其中`/resource/wa/`和`Cyra.initApp`中传入的`appRoot`属性对应。