介绍

对于一个App而言,App Menu是必须要提供的布局组件。一般而言,App Menu用于显示与App相关的菜单清单。当然,我们也可以完全定制App Menu页面的显示内容和显示风格

演示

1. 默认风格

系统App(appKey = a-appbooster:appSystem)按默认风格显示系统菜单

1

2. 自定义风格:显示App清单

Default App(appKey = a-app:appDefault)显示所有App,方便我们切换到指定的App

  • 如果一个App声明为独立App,那么就不显示在App列表当中

2

3. 自定义风格:定制企业微信H5页面

企业微信演示App(appKey = test-wxwork:appTest)一般使用在手机端的企业微信客户端中,因此,我们可以完全定制页面内容,而不仅仅是显示一些菜单项,从而提升用户体验

因此,企业微信演示App被设置为独立App,也就是说不会显示在App列表当中。那么,我们如何使用此App呢?

直接通过页面的query string指定appKey即可,比如:https://test.cabloy.com/?appKey=test-wxwork:appTest

  • PC端显示效果

3

  • Mobile端显示效果

4

设置

1. 默认风格

对于一个App应用而言,App Menu页面是必备组件。因此,我们不需要在App配置中做任何设置,系统会自动从后端获取App的菜单资源并渲染成默认的风格

因此,我们仅仅需要在菜单资源的定义当中设置两个字段即可,参见:静态资源

  • resourceIcon:菜单资源的图标

  • appKey:菜单资源归属的App应用

2. 自定义风格

如果要自定义菜单页面的显示内容或者显示风格,就需要设置Appmenu.layout

下面以企业微信演示App(appKey = test-wxwork:appTest)为例:

2.1 App配置

menu.layout设置为test-wxwork:layoutAppMenuTest

src/suite/test-party/modules/test-wxwork/backend/src/config/static/app/appTest.js

  1. 1module.exports = app => {
  2. 2 const content = {
  3. 3 presets: {
  4. 4 authenticated: {
  5. 5 mobile: {
  6. 6 menu: {
  7. 7 layout: 'test-wxwork:layoutAppMenuTest',
  8. 8 },
  9. 9 },
  10. 10 pc: {
  11. 11 menu: {
  12. 12 layout: 'test-wxwork:layoutAppMenuTest',
  13. 13 },
  14. 14 },
  15. 15 },
  16. 16 },
  17. 17 };
  18. 18 const _app = {
  19. 19 atomName: 'Test(Wechat Work)',
  20. 20 atomStaticKey: 'appTest',
  21. 21 atomRevision: 1,
  22. 22 atomCategoryId: 'Demonstration',
  23. 23 description: '',
  24. 24 appIcon: ':auth:wxwork-outline',
  25. 25 appIsolate: true,
  26. 26 content: JSON.stringify(content),
  27. 27 resourceRoles: 'authenticated',
  28. 28 appSorting: 0,
  29. 29 };
  30. 30 return _app;
  31. 31};

2.2 Layout配置

新建一个LayoutLayout本质就是通过定义多个block(区块)来组合成一个页面。App Menu页面由titleitems两个区块组成

  • title区块:如果不指定,就会使用系统默认的实现

  • items区块:指定为自定义组件,就会使用该组件渲染内容

src/suite/test-party/modules/test-wxwork/backend/src/config/static/layout/layoutAppMenuTest.js

  1. 1module.exports = app => {
  2. 2 const moduleInfo = app.meta.mockUtil.parseInfoFromPackage(__dirname);
  3. 3 const content = {
  4. 4 layouts: {
  5. 5 list: {
  6. 6 blocks: {
  7. 7 items: {
  8. 8 component: {
  9. 9 module: moduleInfo.relativeName,
  10. 10 name: 'appTestMenuLayoutBlockListItems',
  11. 11 },
  12. 12 },
  13. 13 },
  14. 14 },
  15. 15 },
  16. 16 };
  17. 17 const layout = {
  18. 18 atomName: 'Test App Menu Layout(Wechat Work)',
  19. 19 atomStaticKey: 'layoutAppMenuTest',
  20. 20 atomRevision: 0,
  21. 21 description: '',
  22. 22 layoutTypeCode: 13,
  23. 23 content: JSON.stringify(content),
  24. 24 resourceRoles: 'root',
  25. 25 };
  26. 26 return layout;
  27. 27};

2.3 自定义渲染组件

新建自定义渲染组件,本质上就是Vue组件,参见:Component

src/suite/test-party/modules/test-wxwork/front/src/components/appTestMenuLayoutList/appTestMenuLayoutBlockListItems.jsx

  1. 1// export
  2. 2export default {
  3. 3 installFactory,
  4. 4};
  5. 5
  6. 6// installFactory
  7. 7function installFactory(_Vue) {
  8. 8 const Vue = _Vue;
  9. 9 const ebAppMenuLayoutBlockListItemsBase =
  10. 10 Vue.prototype.$meta.module.get('a-app').options.mixins.ebAppMenuLayoutBlockListItemsBase;
  11. 11 return {
  12. 12 mixins: [ebAppMenuLayoutBlockListItemsBase],
  13. 13 data() {
  14. 14 return {
  15. 15 ...
  16. 16 };
  17. 17 },
  18. 18 methods: {
  19. 19 ...
  20. 20 _renderCardSendAppMessage() {
  21. 21 return (
  22. 22 <f7-card>
  23. 23 ...
  24. 24 </f7-card>
  25. 25 );
  26. 26 },
  27. 27 _renderCardTools() {
  28. 28 return (
  29. 29 <f7-card>
  30. 30 ...
  31. 31 </f7-card>
  32. 32 );
  33. 33 },
  34. 34 },
  35. 35 render() {
  36. 36 if (!this.ready) return null;
  37. 37 return (
  38. 38 <div>
  39. 39 {this._renderCardSendAppMessage()}
  40. 40 {this._renderCardTools()}
  41. 41 </div>
  42. 42 );
  43. 43 },
  44. 44 };
  45. 45}
  • export default

首先,我们并不像一般的Vue组件那样直接导出Options对象,而是像Vue插件一样导出一个带installFactory方法的对象

  • mixins: [ebAppMenuLayoutBlockListItemsBase]

ebAppMenuLayoutBlockListItemsBase是模块a-app提供的基类,包含一些基础的逻辑,方面我们在此基础之上进行二次开发

这里我们就可以解释为什么不能直接导出Options对象。因为模块a-app是异步加载的模块,而自定义组件又必须继承ebAppMenuLayoutBlockListItemsBase。如果直接导出Options对象,那么在编译期获取不到该基类,从而导致mixin失败