From dd7fc7810935301cd72e0b3c088cd4dfbb51637e Mon Sep 17 00:00:00 2001 From: bailicangdu <1264889788@qq.com> Date: Fri, 10 Dec 2021 20:21:54 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dev/children/react16/src/index.js | 46 +++++----- docs/sidebar.md | 1 + docs/zh-cn/configure.md | 8 ++ docs/zh-cn/data.md | 4 +- docs/zh-cn/keep-alive.md | 142 ++++++++++++++++++++++++++++++ docs/zh-cn/life-cycles.md | 56 ++++++++---- 6 files changed, 216 insertions(+), 41 deletions(-) create mode 100644 docs/zh-cn/keep-alive.md diff --git a/dev/children/react16/src/index.js b/dev/children/react16/src/index.js index 0b6f67525..8212bc09e 100644 --- a/dev/children/react16/src/index.js +++ b/dev/children/react16/src/index.js @@ -1,12 +1,12 @@ -import "./public-path"; +import './public-path'; import 'babel-polyfill' // import '@babel/polyfill' -import React from "react"; -import ReactDOM from "react-dom"; -import "antd/dist/antd.css"; -import "./index.css"; -import Router from "./router"; -import { Modal, notification } from "antd"; +import React from 'react'; +import ReactDOM from 'react-dom'; +import 'antd/dist/antd.css'; +import './index.css'; +import Router from './router'; +import { Modal, notification } from 'antd'; import subMicroApp from '@micro-zoe/micro-app' // 循环内嵌 @@ -16,9 +16,9 @@ subMicroApp.start({ // 数据监听 window.microApp?.addDataListener((data) => { - console.log("react16 来自基座应用的数据", data) + console.log('react16 来自基座应用的数据', data) notification.open({ - message: "来自基座应用的数据", + message: '来自基座应用的数据', description: JSON.stringify(data), duration: 1, }) @@ -27,7 +27,7 @@ window.microApp?.addDataListener((data) => { function handleGlobalData(data) { console.log('react16: 来自全局数据') Modal.info({ - title: "react16: 来自全局数据", + title: 'react16: 来自全局数据', content: (

{JSON.stringify(data)}

@@ -41,7 +41,7 @@ function handleGlobalData(data) { window.microApp?.addGlobalDataListener(handleGlobalData); // 监听keep-alive模式下的app状态 -window.addEventListener("appstate-change", function (e) { +window.addEventListener('appstate-change', function (e) { console.log('子应用内部console.log -- keep-alive app 状态:', e.detail.appState); }) @@ -50,16 +50,16 @@ ReactDOM.render( , - document.getElementById("root") + document.getElementById('root') ); // 监听卸载 -window.addEventListener("unmount", function () { - ReactDOM.unmountComponentAtNode(document.getElementById("root")); - console.log("微应用react16卸载了 -- 自定义事件unmount"); +window.addEventListener('unmount', function () { + ReactDOM.unmountComponentAtNode(document.getElementById('root')); + console.log('微应用react16卸载了 -- 自定义事件unmount'); }) -console.timeEnd("react#16"); +console.timeEnd('react#16'); // ----------------------分割线-umd模式--------------------- // // function mount () { @@ -67,18 +67,18 @@ console.timeEnd("react#16"); // // // , -// document.getElementById("root") +// document.getElementById('root') // ); -// console.log("微应用react16渲染了 -- 来自umd-mount"); -// console.timeEnd("react#16"); +// console.log('微应用react16渲染了 -- 来自umd-mount'); +// console.timeEnd('react#16'); // } // function unmount () { -// console.log("微应用react16卸载了 -- 来自umd-unmount"); +// console.log('微应用react16卸载了 -- 来自umd-unmount'); // // 卸载时关闭弹窗 // notification.destroy() // // 卸载应用 -// ReactDOM.unmountComponentAtNode(document.getElementById("root")); +// ReactDOM.unmountComponentAtNode(document.getElementById('root')); // } // // 微前端环境下,注册mount和unmount方法 @@ -109,7 +109,7 @@ console.timeEnd("react#16"); // const dynamicScript1 = document.createElement('script') // // dynamicScript1.setAttribute('type', 'module') -// // dynamicScript1.textContent = 'console.warn("inline module")' +// // dynamicScript1.textContent = 'console.warn('inline module')' // dynamicScript1.setAttribute('src', 'http://127.0.0.1:8080/test.js') // dynamicScript1.onload = () => { // console.log('动态module加载完成了') @@ -136,7 +136,7 @@ console.timeEnd("react#16"); //
// ` -// const doc = parser.parseFromString(htmlString, "text/html") +// const doc = parser.parseFromString(htmlString, 'text/html') // console.log( // 'DOMParser querySelector', diff --git a/docs/sidebar.md b/docs/sidebar.md index 8c86b9999..2ccc42ba4 100755 --- a/docs/sidebar.md +++ b/docs/sidebar.md @@ -14,6 +14,7 @@ - [预加载](zh-cn/prefetch) - [插件系统](zh-cn/plugins) - [多层嵌套](zh-cn/nest) + - [keep-alive](zh-cn/keep-alive) - [高级功能](zh-cn/advanced) - [API](zh-cn/api) - [路由](zh-cn/route) diff --git a/docs/zh-cn/configure.md b/docs/zh-cn/configure.md index 18cb109f0..6cea666d5 100644 --- a/docs/zh-cn/configure.md +++ b/docs/zh-cn/configure.md @@ -101,6 +101,14 @@ shadowDOM具有更强的样式隔离能力,开启后,``标签会 当子应用是ssr应用时,需要设置ssr属性,此时micro-app会根据ssr模式加载子应用。 +## keep-alive +- Desc: `是否开启keep-alive模式` +- Type: `string(boolean)` +- Default: `false` +- 使用方式: `` + +开启keep-alive后,应用卸载时会进入缓存,而不是销毁它们,以便保留应用的状态和提升重复渲染的性能。 + ## 全局配置 全局配置会影响每一个子应用,请小心使用! diff --git a/docs/zh-cn/data.md b/docs/zh-cn/data.md index 6c25a749c..50af716d1 100644 --- a/docs/zh-cn/data.md +++ b/docs/zh-cn/data.md @@ -90,6 +90,7 @@ export default { } } } + ``` @@ -146,8 +147,8 @@ vue中监听方式和普通事件一致。 @datachange='handleDataChange' /> - ``` diff --git a/docs/zh-cn/keep-alive.md b/docs/zh-cn/keep-alive.md new file mode 100644 index 000000000..c5a594945 --- /dev/null +++ b/docs/zh-cn/keep-alive.md @@ -0,0 +1,142 @@ +在应用之间切换时,你有时会想保留这些应用的状态,以便恢复用户的操作行为和提升重复渲染的性能,此时开启keep-alive模式可以达到这样的效果。 + +开启keep-alive后,应用卸载时不会销毁,而是推入后台运行。 + +## 使用方式 +```html + +``` + +## 生命周期 +keep-alive模式与普通模式最大的不同是生命周期,因为它不会被真正的卸载,也就不会触发 `unmount` 事件。 + +在基座和子应用中的生命周期如下: + +### 基座应用 + +#### 1. created +``标签初始化后,加载资源前触发。 + +#### 2. beforemount +加载资源完成后,开始渲染之前触发`(只在初始化时执行一次)`。 + +#### 3. mounted +子应用渲染结束后触发`(只在初始化时执行一次)`。 + +#### 4. error +子应用渲染出错时触发,只有会导致渲染终止的错误才会触发此生命周期。 + +#### 5. afterhidden +子应用卸载时触发。 + +#### 6. beforeshow +子应用再次渲染之前触发`(初始化时不执行)`。 + +#### 7. aftershow +子应用再次渲染之后触发`(初始化时不执行)`。 + + +#### 监听生命周期 + + +#### ** React ** +因为React不支持自定义事件,所以我们需要引入一个polyfill。 + +`在标签所在的文件顶部`添加polyfill,注释也要复制。 +```js +/** @jsxRuntime classic */ +/** @jsx jsxCustomEvent */ +import jsxCustomEvent from '@micro-zoe/micro-app/polyfill/jsx-custom-event' +``` + +**开始使用** +```js + console.log('micro-app元素被创建')} + onBeforemount={() => console.log('即将被渲染,只在初始化时执行一次')} + onMounted={() => console.log('已经渲染完成,只在初始化时执行一次')} + onAfterhidden={() => console.log('已卸载')} + onBeforeshow={() => console.log('即将重新渲染,初始化时不执行')} + onAftershow={() => console.log('已经重新渲染,初始化时不执行')} + onError={() => console.log('渲染出错')} +/> +``` + +#### ** Vue ** +vue中监听方式和普通事件一致。 +```html + + + +``` + + +### 子应用 +keep-alive模式下,在子应用卸载、重新渲染时,micro-app都会向子应用发送名为`appstate-change`的自定义事件,子应用可以通过监听该事件获取当前状态,状态值可以通过事件对象属性`e.detail.appState`获取。 + +`e.detail.appState`的值有三个:afterhidden、beforeshow、aftershow,分别对应卸载、即将渲染、已经渲染。 + +```js +// 监听keep-alive模式下的应用状态 +window.addEventListener('appstate-change', function (e) { + if (e.detail.appState === 'afterhidden') { + console.log('已卸载') + } else if (e.detail.appState === 'beforeshow') { + console.log('即将重新渲染') + } else if (e.detail.appState === 'aftershow') { + console.log('已经重新渲染') + } +}) +``` + +应用初始化时不会触发`appstate-change`事件。 + + +## 常见问题 +#### 1、再次渲染时url和页面不匹配 +keep-alive的应用在卸载时会保留页面状态,再次渲染时直接恢复,当应用再次渲染时的url与离开时不一致,则出现url和页面不匹配的问题。 + +如果这个问题对你造成了困扰,可以通过监听`appstate-change`事件,在`beforeshow`时进行修复,根据url跳转对应的页面。 + +#### 2、如何恢复页面滚动位置? +micro-app不会记录页面滚动位置,应用再次渲染时也不会进行恢复,需要开发者进行记录和恢复。 diff --git a/docs/zh-cn/life-cycles.md b/docs/zh-cn/life-cycles.md index 6fe4ff106..d8a62c959 100644 --- a/docs/zh-cn/life-cycles.md +++ b/docs/zh-cn/life-cycles.md @@ -3,24 +3,22 @@ ## 生命周期列表 #### 1. created -在``标签初始化后,加载资源前触发。 +``标签初始化后,加载资源前触发。 #### 2. beforemount -在加载资源完成后,开始渲染之前触发。 +加载资源完成后,开始渲染之前触发。 #### 3. mounted -在子应用渲染结束后触发。 +子应用渲染结束后触发。 #### 4. unmount -在子应用被卸载时触发。 +子应用卸载时触发。 #### 5. error 子应用渲染出错时触发,只有会导致渲染终止的错误才会触发此生命周期。 ## 监听生命周期 -我们通过micro-app元素的自定义事件发送生命周期。 - #### ** React ** @@ -41,23 +39,47 @@ import jsxCustomEvent from '@micro-zoe/micro-app/polyfill/jsx-custom-event' onCreated={() => console.log('micro-app元素被创建')} onBeforemount={() => console.log('即将被渲染')} onMounted={() => console.log('已经渲染完成')} - onUnmount={() => console.log('被卸载')} + onUnmount={() => console.log('已经卸载')} onError={() => console.log('渲染出错')} /> ``` #### ** Vue ** vue中监听方式和普通事件一致。 -```vue - +```html + + + ``` #### ** 自定义 ** 我们可以手动监听生命周期事件。