Skip to content
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

feat: 🎸 appHistory and <Link /> can both take state #477

Merged
merged 9 commits into from
Dec 8, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions packages/icestark-app/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# Changelog

## 1.4.3
## 1.5.0

- [feat] `appHistory` and `<Link />` can both take state. ([#478](https://github.com/ice-lab/icestark/pull/428))
- [fix] add missing props for `registerAppEnter` & `registerAppLeave`.

## 1.4.2

- [fix] Bind history to window when using `AppLink`. ([#428](https://github.com/ice-lab/icestark/pull/428))
- [fix] bind history to window when using `AppLink`. ([#428](https://github.com/ice-lab/icestark/pull/428))

## 1.4.1

Expand Down
2 changes: 1 addition & 1 deletion packages/icestark-app/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ice/stark-app",
"version": "1.4.3",
"version": "1.5.0",
"description": "icestark-app is a JavaScript library for icestark, used by sub-application.",
"scripts": {
"build": "rm -rf lib && tsc",
Expand Down
26 changes: 23 additions & 3 deletions packages/icestark-app/src/AppLink.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
import * as React from 'react';
import formatUrl from './util/formatUrl';
import removeTrailingSlash from './util/removeTrailingSlash';

interface To {
/**
* A string representing the path link to
*/
pathname: string;
/**
* A string representing the url search to
*/
search?: string;
/**
* A string representing the url state to
*/
state?: object;
}

export type AppLinkProps = {
to: string;
to: string | To;
hashType?: boolean;
replace?: boolean;
message?: string;
Expand All @@ -11,7 +27,11 @@ export type AppLinkProps = {

const AppLink = (props: AppLinkProps) => {
const { to, hashType, replace, message, children, ...rest } = props;
const linkTo = formatUrl(to, hashType);

const _to = typeof to === 'object' ? removeTrailingSlash(to.pathname) + to.search : to;
const _state = typeof to === 'object' ? to.state : {};

const linkTo = formatUrl(_to, hashType);
return (
<a
{...rest}
Expand All @@ -28,7 +48,7 @@ const AppLink = (props: AppLinkProps) => {
*/
const changeState = window.history[replace ? 'replaceState' : 'pushState'].bind(window);

changeState({}, null, linkTo);
changeState(_state ?? {}, null, linkTo);
}}
>
{children}
Expand Down
13 changes: 8 additions & 5 deletions packages/icestark-app/src/appHistory.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import formatUrl from './util/formatUrl';
import normalizeArgs from './util/normalizeArgs';

const appHistory = {
push: (url: string, hashType?: boolean) => {
push: (url: string, state?: object | boolean, hashType?: boolean) => {
const [_state, _hashType] = normalizeArgs(state, hashType);
window.history.pushState(
{},
_state ?? {},
null,
formatUrl(url, hashType),
formatUrl(url, _hashType),
);
},
replace: (url: string, hashType?: boolean) => {
replace: (url: string, state?: object | boolean, hashType?: boolean) => {
const [_state, _hashType] = normalizeArgs(state, hashType);
window.history.replaceState(
{},
state ?? {},
maoxiaoke marked this conversation as resolved.
Show resolved Hide resolved
null,
formatUrl(url, hashType),
);
Expand Down
14 changes: 14 additions & 0 deletions packages/icestark-app/src/util/normalizeArgs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// `hashType' was relocated to the third argument.
const normalizeArgs = (state?: object | boolean, hashType?: boolean): [object, boolean] => {
if (typeof state === 'boolean') {
console.warn('[icestark]: hashType was relocated to the third argument.');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

建议仅在 dev 环境输出

return [{}, hashType ?? state];
}
if (typeof state === 'object') {
return [state, hashType];
}

return [{}, hashType];
};

export default normalizeArgs;
5 changes: 5 additions & 0 deletions packages/icestark-app/src/util/removeTrailingSlash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const removeTrailingSlash = (str: string) => {
return str.charAt(str.length - 1) === '/' ? str.slice(0, -1) : str;
};

export default removeTrailingSlash;
27 changes: 26 additions & 1 deletion packages/icestark-app/tests/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
} from '../src/index';
import { setCache, getCache } from '../src/cache';
import formatUrl from '../src/util/formatUrl';
import normalizeArgs from '../src/util/normalizeArgs';
import removeTrailingSlash from '../src/util/removeTrailingSlash';

const namespace = 'ICESTARK';

Expand Down Expand Up @@ -146,4 +148,27 @@ describe('formatUrl', () => {

expect(formatUrl('/seller', true)).toBe('#/seller');
})
})
});

describe('normalizeArgs', () => {
test('normalizeArgs', () => {
expect(normalizeArgs(true)).toEqual([{}, true]);
expect(normalizeArgs(false, true)).toEqual([{}, true]);

expect(normalizeArgs({ framework: 'icestark' })).toEqual([{ framework: 'icestark' }, undefined]);
expect(normalizeArgs({ framework: 'icestark' }, true)).toEqual([{ framework: 'icestark' }, true]);
expect(normalizeArgs({ framework: 'icestark' }, false)).toEqual([{ framework: 'icestark' }, false]);

expect(normalizeArgs()).toEqual([{}, undefined]);
})
});

describe('removeTrailingSlash', () => {
test('removeTrailingSlash', () => {
expect(removeTrailingSlash('/seller/detail')).toBe('/seller/detail');
expect(removeTrailingSlash('/seller/detail/')).toBe('/seller/detail');

expect(removeTrailingSlash('/')).toBe('');
})
});

61 changes: 52 additions & 9 deletions website/docs/api/ice-stark-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ import isInIcestark from '@ice/stark-app/lib/isInIcestark';

#### appHistory.push

- 类型:`function`
- 代码示例:
- 类型定义:` (url: string, state?: object, hashType?: boolean) => void`

代码示例一:跳转 url 页面

```js
import React from 'react';
Expand All @@ -62,7 +63,7 @@ export default class SelfLink extends React.Component {
return (
<span
onClick={() => {
appHistory.push('/home');
appHistory.push('/home?name=ice');
}}
>
selfLink
Expand All @@ -72,20 +73,33 @@ export default class SelfLink extends React.Component {
}
```

代码示例二:传递 `state`

```js
appHistory.push('/home?name=ice', { framework: 'icestark' });
```

代码示例三:设置为 hash 路由模式

```js
appHistory.push('/home?name=ice', {}, true);
}
```

#### appHistory.replace

- 类型:`function`
- 函数类型定义:- 类型定义:` (url: string, state?: object, hashType?: boolean) => void`
- 代码示例参考 `appHistory.push`

## AppLink

提供声明式的,可访问的导航,表示本次跳转需要重新加载静态资源。微应用内部跳转仍然使用 `Link`
提供声明式的,可访问的导航,表示本次跳转需要重新加载静态资源。微应用内部跳转仍然使用 `Link`

#### to

目标路径,同 `Link` 中的 `to` 保持一致 ,必填

- 类型:`string`
- 类型:`string | object`
- 默认值:`-`

#### replace
Expand All @@ -109,26 +123,55 @@ export default class SelfLink extends React.Component {
- 类型:`boolean`
- 默认值:`false`

代码示例:
代码示例一:`to` 为字符串,传递 query 参数

```js
import React from 'react';
import { Link } from 'react-router-dom';
import { AppLink } from '@ice/stark';

export default class SelfLink extends React.Component {
render() {
return (
<div>
// 应用间路由跳转,并携带 query 查询参数
<AppLink to="/waiter/list?name=ice">使用 AppLink 跳转到小二平台的列表页</AppLink>
<Link to="/detail">跳转到商家平台详情页</Link>
</div>
);
}
}
```

代码示例二:`to` 为简单对象,传递 state

```js
import React from 'react';
import { Link } from 'react-router-dom';
import { AppLink } from '@ice/stark';

export default class SelfLink extends React.Component {
// 商家平台代码
render() {
return (
<div>
<AppLink to="/waiter/list">使用 AppLink 跳转到小二平台的列表页</AppLink>
// 应用间路由跳转,并传递 state、query
<AppLink
to={{
pathname: '/waiter/list',
search: '?name=ice',
state: {
framework: 'icestark'
}
}}
>使用 AppLink 跳转到小二平台的列表页</AppLink>
<Link to="/detail">跳转到商家平台详情页</Link>
</div>
);
}
}
```


## registerAppEnter

提供快速注册当前应用加载前的回调事件
Expand Down