基于H5框架的多设备开发指导

fox280
发布于 2025-1-22 15:27
浏览
0收藏

概述

应用使用H5开发的历史页面多且冗杂,同时H5相较于ArkUI一多缺乏拿来即用的适配方案。为达到HarmonyOS原生一多体验,所有页面进行一多适配复杂且工作量大。针对此问题,本文将主要提供一套H5多设备断点和响应式组件方案,实现页签栏响应式、网格响应式、类挪移布局等效果,提升H5一多适配的开发效率。首先介绍多设备断点能力,然后分别介绍组件的使用说明,结合组件效果提供对应场景的开发案例,最终提供示例代码指导实际开发。

以下是使用组件库的一些前置要求:

组件库安装

根据您使用的包管理器和web框架,请选择对应的安装命令。

Npm

// Vue2
npm install web-multidevice-advanced-vue2
// Vue3
npm install web-multidevice-advanced-vue3
// React
npm install web-multidevice-advanced-react
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

Yarn

// Vue2
yarn add web-multidevice-advanced-vue2
// Vue3
yarn add web-multidevice-advanced-vue3
// React
yarn add web-multidevice-advanced-react
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

多设备断点

断点设计原理

H5断点是基于鸿蒙多设备封装的一套断点机制,通过设置断点,让开发者可以结合窗口宽度去实现不同的页面布局效果。

断点以应用窗口宽度为基准,将应用窗口在宽度维度上分成了几个不同的区间即不同的断点,默认提供的断点区间如下所示。


断点名称

取值范围(px)

xs

[0, 320)

sm

[320, 600)

md

[600, 840)

lg

[840, 1440)

xl

[1440, +∞)

开发者可以根据实际需要调整默认的断点区间,也可以在xl后面新增xxl断点以适配更复杂的布局场景。

多设备适配指导

在具体开发过程中,使用breakpointManager需先从web-multidevice-advanced-ui/hookInput引用BreakpointManager这个类,然后创建BreakpointManager实例。建议创建BreakpointManager实例放在公共文件里,然后导出。这样的话,设备断点值变更时就只需要调整一个地方。使用breakpointManager时,需调用subscribeToBreakpoint方法订阅断点变化,然后在回调函数里使用useBreakpointValue方法来获取不同断点下属性的不同值。最后在页面销毁前需要取消断点订阅并销毁实例。

具体示例如下所示:

创建断点管理公共实例并导出

// utils/breakpointInit.ts
import { BreakpointManager } from "web-multidevice-advanced-ui/src/hookInput";

// 实例化断点管理类,断点区间支持自定义
export const breakpointManager = new BreakpointManager({
  xs: 0,
  sm: 320,
  md: 600,
  lg: 840,
  xl: 1440,
});
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

订阅断点变化并获取不同断点下的属性值

// xxx.vue
import { breakpointManager } from "./utils/breakpointInit";

const contentCols = ref("12");
// 订阅断点变化
const unsubscribe = breakpointManager.subscribeToBreakpoint((bp) => {
  // bp:实时的断点值
  // 根据当前断点区间,返回对应的属性值
  contentCols.value = breakpointManager.useBreakpointValue({
    xs: "12",
    sm: "12",
    md: "6",
    lg: "6",
    xl: "6",
  });
  // 获取当前的断点值
  breakpointManager.getCurrentBreakpoint();
  // 获取当前的内置断点类型和区间
  breakpointManager.getBreakpoints();
});
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

页面销毁前取消断点订阅并销毁实例

// xxx.vue
onUnmounted(() => {
  // 取消订阅
  unsubscribe();
  // 销毁实例,移除监听器,清空回调函数集合
  breakpointManager.destroy();
});
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

页签栏响应式组件实现多设备适配

组件使用说明

H5页签栏响应式组件MultiTabBar,包含父组件TabBar和子组件TabBarItem两部分,主要用于实现内容视图切换的布局效果。组件结合多设备断点能力,能够适配不同类型的布局场景。

组件导入方式

  • Vue2
// xxx.vue
import { TabBarVue, TabBarItemVue } from "web-multidevice-advanced-vue2/src";
  • 1.
  • 2.
  • Vue3
// xxx.vue
import { TabBarVue, TabBarItemVue } from "web-multidevice-advanced-vue3/src";
  • 1.
  • 2.
  • React
// xxx.tsx
import { TabBarReact, TabBarItemReact } from "web-multidevice-advanced-react/dist/index";
  • 1.
  • 2.

默认布局效果

MultiTabBar组件基于默认断点区间,内置了一套多设备布局效果,如下图所示


sm

md

lg

基于H5框架的多设备开发指导-鸿蒙开发者社区

基于H5框架的多设备开发指导-鸿蒙开发者社区

基于H5框架的多设备开发指导-鸿蒙开发者社区

TabBar父组件 API

  1. Attribute


属性

说明

类型

可选值

默认值

vertical

设置组件是否为纵向Tab

Boolean

true:纵向Tab

false:横向Tab

xs:false

sm:false

md:false

lg:true

xl:true

barPosition

设置组件的位置

String

start

vertical属性设置为true时,Tab位于容器左侧;

vertical属性设置为false时,Tab位于容器顶部。

end

vertical属性设置为true时,Tab位于容器右侧;

vertical属性设置为false时,Tab位于容器底部。

xs:bottom

sm:bottom

md:bottom

lg:left

xl:left

width

设置组件的宽度

String / Number

xs:100%

sm:100%

md:100%

lg:58px

xl:58px

height

设置组件的高度

String / Number

xs:78px

sm:78px

md:78px

lg:100%

xl:100%

unselectedColor

设置子组件文本未选中时的颜色

String

#aaacab

selectedColor

设置子组件文本选中时的颜色

String

#0b59f7

layoutMode

设置子组件内部元素的排布方式

String

vertical:元素垂直排布

horizontal:元素水平排布

xs:vertical

sm:vertical

md:horizontal

lg:vertical

xl:vertical

verticalAlign

设置子组件内部元素在垂直方向上的对齐方式

String

top:顶部对齐

center:居中对齐

bottom:底部对齐

center

horizontalAlign

设置子组件内部元素在水平方向上的对齐方式

String

start:起始端对齐

center:居中对齐

end:末端对齐

center

bgColor

设置子组件容器未选中时的背景颜色

String

#ffffff

selectedBgColor

设置子组件容器选中时的背景颜色

String

#f1f5ff

  1. Event


事件名

说明

参数

onTabItemClick

点击页签栏子组件容器时触发的自定义事件

Function({index, name})

index:选中子组件的索引值

name:选中子组件的name标识名称

TabBarItem子组件 API


属性

说明

类型

可选值

默认值

name

子组件的唯一标识名称(必填)

String

推荐使用方式(以Vue3为例)

MultiTabBar组件在使用时建议封装为一个独立的组件,置于嵌套路由RouterView外层,以确保页面切换时组件不会刷新。同时,需要借助断点能力实现路由视图的页签栏避让。

// APP.vue
<template>
  <div>
    <TabBar />
    <div class="template-main">
      <router-view />
    </div>
  </div>
</template>

<script setup>
import { ref, onUnmounted } from "vue";
// 导入封装后的MultiTabBar组件
import TabBar from "./components/TabBar/index.vue";
// 导入断点公共实例
import { breakpointManager } from "./utils/breakpointInit";

const marginLeft = ref("0");
const marginBottom = ref("0");
// 订阅断点变化
const unsubscribe = breakpointManager.subscribeToBreakpoint(() => {
  // 传入不同断点下的属性值,根据当前断点返回对应的值
  marginLeft.value = breakpointManager.useBreakpointValue({
    xs: 0,
    sm: 0,
    md: 0,
    lg: "96px",
    xl: "96px",
  });
  marginBottom.value = breakpointManager.useBreakpointValue({
    xs: "78px",
    sm: "78px",
    md: "78px",
    lg: 0,
    xl: 0,
  });
  // 设置CSS变量
  document.documentElement.style.setProperty("--marginLeft", marginLeft.value);
  document.documentElement.style.setProperty("--marginBottom", marginBottom.value);
});
onUnmounted(() => {
  // 取消订阅断点变化
  unsubscribe();
  // 销毁实例,移除监听器,清空回调函数集合
  breakpointManager.destroy();
});
</script>

<style lang="less" scoped>
.template-main {
  // 设置margin样式,实现页签栏避让
  margin-left: var(--marginLeft);
  margin-bottom: var(--marginBottom);
  overflow: scroll;
}
</style>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.

MultiTabBar组件封装示例代码如下所示:

// TabBar/index.vue
<template>
  <TabBarVue :onTabItemClick="tabItemClick"
             :vertical="vertical">
    <TabBarItemVue v-for="item in tabItems" 
                   :name="item.name" 
                   :key="item.key">
      <img :src="item.imgSrc" />
      <span>{{ item.name }}</span>
    </TabBarItemVue>
  </TabBarVue>
</template>

<script setup>
import { ref, onUnmounted } from "vue";
import { TabBarVue, TabBarItemVue } from "web-multidevice-advanced-vue3/src";
import { breakpointManager } from "../../utils/breakpointInit";

const vertical = ref(false);
const tabItems = ref([
  { key: "first", name: "首页", imgSrc: "../assets/tab_home_selected.svg", urlName: "/" },
  { key: "second", name: "分类", imgSrc: "../assets/tab_classification.svg", urlName: "/classify" },
  { key: "third", name: "发现", imgSrc: "../assets/tab_discovery.svg", urlName: "/discovery" },
]);
// 订阅断点变化
const unsubscribe = breakpointManager.subscribeToBreakpoint(() => {
  // 传入不同断点下的vertical属性值,根据当前断点返回对应的值
  vertical.value = breakpointManager.useBreakpointValue({
    xs: false,
    sm: false,
    md: false,
    lg: true, 
    xl: true,
  });
});
// 定义自定义事件
const tabItemClick = ({ index, name }) => {
  // 添加点击事件逻辑
};
onUnmounted(() => {
  // 取消订阅断点变化
  unsubscribe();
});
</script>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.

场景案例

实现效果

基于H5框架的多设备开发指导-鸿蒙开发者社区

注意:

实现效果中的红色框仅表示组件位置,不代表对应组件的边框。


sm

md

lg

基于H5框架的多设备开发指导-鸿蒙开发者社区

基于H5框架的多设备开发指导-鸿蒙开发者社区

基于H5框架的多设备开发指导-鸿蒙开发者社区

关键代码(以vue3为例)

  • onTabItemClick为组件绑定的点击事件,可以在这里实现点击切换图片的效果已及点击进行路由跳转的功能。
  • vertical属性可以设置页签栏是否为纵向,true表示纵向左边tab,false为横向底部tab。(暂不支持其他位置的tab)。

更多属性及参数参考 ​​页签栏组件MultiTabBar​

代码示例如下:

// web_advanced_ui_sample\vue3_sample\src\App.vue
<template>
  <div>
    <TabBar />
    <div class="template-main">
      <router-view />
    </div> 
  </div>
</template>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
// web_advanced_ui_sample\vue3_sample\src\components\TabBar\index.vue
<template>
  <TabBarVue :onTabItemClick="tabItemClick" 
             :vertical="vertical" 
             :selectedBgColor="selectedBgColor" 
             :bgColor="defaultBgColor"
             :selectedColor="selectedColor" 
             :width="barWidth"
             :layoutMode="layoutMode" >
    <TabBarItemVue v-for="item in tabItems" 
                   :name="item.key" 
                   :key="item.key">
      <img :src="item.imgSrc" />
      <span>{{ item.name }}</span>
    </TabBarItemVue>
  </TabBarVue>
</template>

<script setup>
import { ref, onUnmounted } from "vue";
import { TabBarVue, TabBarItemVue } from "web-multidevice-advanced-vue3/src";
import { breakpointManager } from "../../utils/breakpointInit";
import { useRouter } from "vue-router";

const router = useRouter();
// 导航栏文本图片信息
const tabItems = ref([
  { key: "first", name: "首页", imgSrc: "../assets/tab_home_selected.svg", urlName: "/" },
  { key: "second", name: "分类", imgSrc: "../assets/tab_classification.svg", urlName: "/classify" },
  { key: "third", name: "发现", imgSrc: "../assets/tab_discovery.svg", urlName: "/discovery" },
  { key: "forth", name: "购物袋", imgSrc: "../assets/tab_shopping_bag.svg", urlName: "/shoppingBag" },
  { key: "fivth", name: "我的", imgSrc: "../assets/tab_mine.svg", urlName: "/mine" },
]);
const vertical = ref(false);
const selectedBgColor = ref("#f1f3f5");
const defaultBgColor = ref("#f1f3f5");
const barWidth = ref("100%");
const selectedColor = ref("#d20a2c");
const layoutMode = ref("vertical");
// 订阅断点变化
const unsubscribe = breakpointManager.subscribeToBreakpoint(() => {
  vertical.value = breakpointManager.useBreakpointValue({
    xs: false,
    sm: false,
    md: false,
    lg: true, 
    xl: true,
  });
  barWidth.value = breakpointManager.useBreakpointValue({
    xs: "100%",
    sm: "100%",
    md: "100%",
    lg: "98px",
    xl: "98px",
  });
});
// 页签栏点击事件:切换路由,更换icon图标
const tabItemClick = ({ index }) => {
  let item = tabItems.value[index];
  router.push(item.urlName);
  for (let i = 0; i < tabItems.value.length; i++) {
    let curItem = tabItems.value[i];
    if (curItem.imgSrc.endsWith("_selected.svg")) {
      curItem.imgSrc = curItem.imgSrc.replace("_selected.svg", ".svg");
    }
    if (index === i && !curItem.imgSrc.endsWith("_selected.svg")) {
      curItem.imgSrc = curItem.imgSrc.replace(".svg", "_selected.svg");
    }
  }
};
// 取消订阅,销毁断点实例
onUnmounted(() => {
  unsubscribe();
  breakpointManager.destroy();
});
</script>

<style lang="less" scoped>
@import './index.less';
</style>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.

网格布局响应式组件实现多设备适配

组件使用说明

H5网格布局响应式组件MultiGrid,包含父组件MultiGrid和子组件MultiGridItem两部分,主要用于提供精确的行和列控制,实现复杂的二维布局效果。组件结合多设备断点能力,能够适配不同类型的布局场景。

组件导入方式

  • Vue2
// xxx.vue
import { MultiGridVue, GridItemVue } from "web-multidevice-advanced-vue2/src";
  • 1.
  • 2.
  • Vue3
// xxx.vue
import { MultiGridVue, GridItemVue } from "web-multidevice-advanced-vue3/src";
  • 1.
  • 2.
  • React
// xxx.tsx
import { MultiGridReact, GridItemReact } from "web-multidevice-advanced-react/dist/index";
  • 1.
  • 2.

默认布局效果

MultiGrid组件基于默认断点区间,内置了一套多设备布局效果,如下图所示


sm

md

lg

基于H5框架的多设备开发指导-鸿蒙开发者社区

基于H5框架的多设备开发指导-鸿蒙开发者社区

基于H5框架的多设备开发指导-鸿蒙开发者社区

MultiGrid父组件 API

  1. Attribute


属性

说明

类型

可选值

默认值

columnsTemplate

设置组件每一列的列宽

String / Number

1. 绝对单位

2. 百分比

3. repeat(),接受两个参数:

(1) 参数1:重复的次数,参数2:需要重复的值

(2) 参数1:auto-fill关键字表示自动填充,参数2:每列宽度

(3) 参数1:auto-fit关键字表示自动填充,宽度不够时会缩小

3. fr关键字:表示比例关系

4. minmax():接受最小值和最大值两个参数

5. auto关键字:浏览器自己决定长度

xs:1fr 1fr 1fr 1fr

sm:1fr 1fr 1fr 1fr

md:1fr 1fr 1fr 1fr 1fr 1fr

lg:1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr

xl:1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr

rowsTemplate

设置组件每一行的行高

String / Number

同columnsTemplate

auto

gridRowGap

设置网格行与行的间隔

String / Number

0

gridColumnGap

设置网格列与列的间隔

String / Number

0

justifyItems

设置网格项内容的水平位置

String

stretch:拉伸以填充网格项

start:网格项起点位置对齐

end:网格项终点位置对齐

center:网格项中间位置对齐

stretch

alignItems

设置网格项内容的垂直位置

String

stretch:拉伸以填充网格项

start:网格项起点位置对齐

end:网格项终点位置对齐

center:网格项中间位置对齐

stretch

justifyContent

设置整个内容区域在容器里的水平位置

String

stretch:未指定大小时拉伸填充容器

start:对齐容器的起始边框

end:对齐容器的结束边框

center:容器内容居中

space-around:子项两侧间隔相等

space-between:子项间间隔相等,与容器边框无间隔

space-evenly:子项间间隔相等

stretch

alignContent

设置整个内容区域在容器里的垂直位置

String

同justifyContent,方向为垂直方向

stretch

  1. Event


事件名

说明

参数

onGridItemClick

点击网格子组件容器时触发的自定义事件

Function({index, name})

index:选中子组件的索引值

name:选中子组件的name标识名称

MultiGridItem子组件 API


属性

说明

类型

可选值

默认值

name

子组件的唯一标识名称(必填)

String

gridColumnStart

设置子组件左边框所在的起始列号

String / Number

auto

gridColumnEnd

设置子组件右边框所在的终点列号

String / Number

auto

gridRowStart

设置子组件上边框所在的起始行号

String / Number

auto

gridRowEnd

设置子组件下边框所在的终点行号

String / Number

auto

label

设置网格项的文本内容(不支持断点)

String

icon

设置网格项的图标链接(不支持断点,只支持网络链接)

String

推荐使用方式(以Vue3为例)

// MultiGrid/index.vue
<template>
  <MultiGridVue :onGridItemClick="gridItemClick"
                :columnsTemplate="columnsTemplate">
    <GridItemVue v-for="item in gridItems" 
                 :name="item.name" 
                 :key="item.id">
      <img :src="item.imgSrc" />
      <span>{{ item.name }}</span>
    </GridItemVue>
  </MultiGridVue>
</template>

<script setup>
import { ref, onUnmounted } from "vue";
import { MultiGridVue, GridItemVue } from "web-multidevice-advanced-vue3/src";
import { breakpointManager } from "../../utils/breakpointInit";

const columnsTemplate = ref("1fr 1fr 1fr 1fr 1fr");
const gridItems = ref([
  { id: 1, name: "智慧办公", imgSrc: require("../../assets/categories_1.png") },
  { id: 2, name: "智慧家居", imgSrc: require("../../assets/categories_2.png") },
  { id: 3, name: "智能手机", imgSrc: require("../../assets/categories_3.png") },
]);
// 订阅断点变化
const unsubscribe = breakpointManager.subscribeToBreakpoint(() => {
  // 传入不同断点下的columnsTemplate属性值,根据当前断点返回对应的值
  columnsTemplate.value = breakpointManager.useBreakpointValue({
    xs: "1fr 1fr 1fr 1fr 1fr",
    sm: "1fr 1fr 1fr 1fr 1fr",
    md: "1fr 1fr 1fr 1fr 1fr 1fr 1fr",
    lg: "1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr", 
    xl: "1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr",
  });
});
// 定义自定义事件
const gridItemClick = ({ index, name }) => {
  // 添加点击事件逻辑
};
onUnmounted(() => {
  // 取消订阅断点变化
  unsubscribe();
  // 销毁实例,移除监听器,清空回调函数集合
  breakpointManager.destroy();
});
</script>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.

场景案例

实现效果

基于H5框架的多设备开发指导-鸿蒙开发者社区

注意:

实现效果中的红色框仅表示组件位置,不代表对应组件的边框。


sm

md

lg

基于H5框架的多设备开发指导-鸿蒙开发者社区

基于H5框架的多设备开发指导-鸿蒙开发者社区

基于H5框架的多设备开发指导-鸿蒙开发者社区

关键代码(以vue3为例)

  • 网格列数通过columnsTemplate设置,结合breakpointManager断点管理即可实现在不同设备上展示不同的列数。本示例中以fr关键字设置列数。
  • onGridItemClick为组件MultiGridVue自带的点击事件,在vue3中也可以在GridItemVue里添加@click点击事件,但是在vue2中建议使用onGridItemClick实现子组件的点击事件。-

其他设置方式及其他属性参考​​ 网格组件multigrid。​

具体示例如下:

// web_advanced_ui_sample\vue3_sample\src\components\Categories\index.vue
<template>
  <div class="categories">
    <MultiGridVue :columnsTemplate="columnsTemplate" 
                  gridRowGap="10px" 
                  gridColumnGap="10px"
                  onGridItemClick="pageJump">
      <GridItemVue class="categories-item"
                   v-for="item in categoriesItems" 
                   :name="item.key" 
                   :key="item.key">
        <img :src="item.imgSrc" />
        <span>{{ item.name }}</span>
      </GridItemVue>
    </MultiGridVue>
  </div>
</template>

<script setup>
import { ref, onUnmounted } from "vue";
import { MultiGridVue, GridItemVue } from "web-multidevice-advanced-vue3/src";
import { breakpointManager } from "../../utils/breakpointInit";
import { useRouter } from "vue-router";

const router = useRouter();
// 网格项点击事件:路由跳转
const pageJump = () => {
  router.push("detail_pay");
};
// 网格组件元素
const categoriesItems = [
  { id: 1, name: "智慧办公", imgSrc: require("../../assets/categories_1.png") },
  { id: 2, name: "华为手机", imgSrc: require("../../assets/categories_2.png") },
  { id: 3, name: "运动健康", imgSrc: require("../../assets/categories_3.png") },
  { id: 4, name: "华为智选", imgSrc: require("../../assets/categories_4.png") },
  { id: 5, name: "企业商用", imgSrc: require("../../assets/categories_5.png") },
  { id: 6, name: "智慧家居", imgSrc: require("../../assets/categories_6.png") },
  { id: 7, name: "影音娱乐", imgSrc: require("../../assets/categories_7.png") },
  { id: 8, name: "AITO汽车", imgSrc: require("../../assets/categories_8.png") },
  { id: 9, name: "鸿蒙智联", imgSrc: require("../../assets/categories_9.png") },
  { id: 10, name: "全屋智能", imgSrc: require("../../assets/categories_10.png") },
];
const columnsTemplate = ref("1fr 1fr 1fr 1fr 1fr");
// 订阅断点变化
const unsubscribe = breakpointManager.subscribeToBreakpoint(() => {
  columnsTemplate.value = breakpointManager.useBreakpointValue({
    xs: "1fr 1fr 1fr 1fr 1fr",
    sm: "1fr 1fr 1fr 1fr 1fr",
    md: "1fr 1fr 1fr 1fr 1fr 1fr 1fr",
    lg: "1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr",
    xl: "1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr",
  });
});
// 取消订阅,销毁断点实例
onUnmounted(() => {
  unsubscribe();
  breakpointManager.destroy();
});
</script>

<style lang="less" scoped>
@import './index.less';
</style>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.

类挪移布局响应式组件实现多设备适配

组件使用说明

H5类挪移布局响应式组件MultiDiversion,包含父组件MultiDiversion和子组件MultiDiversionItem两部分,主要用于根据布局的宽度选择是上下布局还是左右布局效果。组件结合多设备断点能力,能够适配不同类型的布局场景。

组件导入方式

  • Vue2
// xxx.vue
import { MultiDiversionVue, DiversionItemVue } from "web-multidevice-advanced-vue2/src";
  • 1.
  • 2.
  • Vue3
// xxx.vue
import { MultiDiversionVue, DiversionItemVue } from "web-multidevice-advanced-vue3/src";
  • 1.
  • 2.
  • React
// xxx.tsx
import { MultiDiversionReact, DiversionItemReact } from "web-multidevice-advanced-react/dist/index";
  • 1.
  • 2.

默认布局效果

MultiDiversion组件基于默认断点区间,内置了一套多设备布局效果,如下图所示


sm

md

lg

基于H5框架的多设备开发指导-鸿蒙开发者社区

基于H5框架的多设备开发指导-鸿蒙开发者社区

基于H5框架的多设备开发指导-鸿蒙开发者社区

MultiDiversion父组件 API

  1. Attribute


属性

说明

类型

可选值

默认值

direction

设置组件的排列方向

String

horizontal:横向排列

vertical:纵向排列

xs:vertical

sm:vertical

md:horizontal

lg:horizontal

xl:horizontal

splitLine

设置是否显示子组件分割线

Boolean

true

false

false

splitLineMode

设置子组件分割线的类型

String

solid:实线

dashed:虚线

dotted:点线

dotted

MultiDiversionItem子组件 API


属性

说明

类型

可选值

默认值

name

子组件的唯一标识名称(必填)

String

diversionCols

设置子组件占据的栅格列数,最大值为12。

子组件横向排列且栅格总和大于12时,按照栅格比例分配父容器宽度。

String / Number

12

diversionGap

设置子组件内容的左右内边距和

String / Number

0

推荐使用方式(以Vue3为例)

// MultiDiversion/index.vue
<template>
  <MultiDiversionVue :direction="diversionDirection">
    <DiversionItemVue name="firstContent" >
      // 内容区1
    </DiversionItemVue>
    <DiversionItemVue name="secondContent" >
      // 内容区2
    </DiversionItemVue>
  </MultiDiversionVue>
</template>

<script setup>
import { ref, onUnmounted } from "vue";
import { MultiDiversionVue, DiversionItemVue } from "web-multidevice-advanced-vue3/src";
import { breakpointManager } from "../../utils/breakpointInit";

const diversionDirection = ref("vertical");
// 订阅断点变化
const unsubscribe = breakpointManager.subscribeToBreakpoint(() => {
  // 传入不同断点下的diversion属性值,根据当前断点返回对应的值
  diversionDirection.value = breakpointManager.useBreakpointValue({
    xs: "vertical",
    sm: "vertical",
    md: "horizontal",
    lg: "horizontal", 
    xl: "horizontal",
  });
});
onUnmounted(() => {
  // 取消订阅断点变化
  unsubscribe();
  // 销毁实例,移除监听器,清空回调函数集合
  breakpointManager.destroy();
});
</script>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.

场景案例

实现效果

基于H5框架的多设备开发指导-鸿蒙开发者社区

注意:

实现效果中的红色框仅表示组件位置,不代表对应组件的边框。


sm

md

lg

基于H5框架的多设备开发指导-鸿蒙开发者社区

基于H5框架的多设备开发指导-鸿蒙开发者社区

基于H5框架的多设备开发指导-鸿蒙开发者社区

关键代码(以vue3为例)

  • 子组件name属性必填,且一个项目中子组件name属性不能重复。
  • direction为类挪移组件里两个组件的排列方式,"horizontal":横向排列,"vertical":纵向排列。结合breakpointManager断点管理即可实现在不同设备上展示不同的布局方式。
  • diversionCols为类挪移子组件里两个组件所占的比例,类挪移组件默认宽度为12。子组件设置大于12时会占满整个类挪移组件的宽度。

更多属性及设置参考 ​​类挪移布局组件multidiversion​

具体代码如下:

// web_advanced_ui_sample\vue3_sample\src\components\PageHeader\index.vue
<template>
  <div class="home-header">
    <MultiDiversionVue :direction="multiDiversionDirection">
      <DiversionItemVue name="firstTitle" 
                        :diversionCols="tabBarCols" 
                        :diversionGap="barGap">
        <div class="top-tab-bar">
          <span class="top-tab-bar-text-selected">华为</span>
          <span class="top-tab-bar-text">AITO汽车</span>
          <span class="top-tab-bar-text">华为智选</span>
          <span class="top-tab-bar-text">生态周边</span>
        </div>
      </DiversionItemVue>
      <DiversionItemVue name="secondTitle" 
                        :diversionCols="searchBarCols" 
                        :diversionGap="barGap">
        <div class="search-bar">
          <input type="search-bar-text" 
                 class="search-bar-input" 
                 placeholder="搜索..." />
          <img class="search-bar-image" 
               src="../../assets/line_viewfinder.svg" />
          <img class="search-bar-image" 
               src="../../assets/msg_big.png" />
        </div>
      </DiversionItemVue>
    </MultiDiversionVue>
  </div>
</template>

<script setup>
import { onUnmounted, ref } from "vue";
import { MultiDiversionVue, DiversionItemVue } from "web-multidevice-advanced-vue3/src";
import { breakpointManager } from "../../utils/breakpointInit";

const multiDiversionDirection = ref("vertical");
const tabBarCols = ref("7");
const searchBarCols = ref("5");
const barGap = ref("10px");
// 订阅断点变化
const unsubscribe = breakpointManager.subscribeToBreakpoint(() => {
  multiDiversionDirection.value = breakpointManager.useBreakpointValue({
    xs: "vertical",
    sm: "vertical",
    md: "horizontal",
    lg: "horizontal",
    xl: "horizontal",
  });
  tabBarCols.value = breakpointManager.useBreakpointValue({
    xs: "12",
    sm: "12",
    md: "7",
    lg: "8",
    xl: "8",
  });
  searchBarCols.value = breakpointManager.useBreakpointValue({
    xs: "12",
    sm: "12",
    md: "5",
    lg: "4",
    xl: "8",
  });
});
// 取消订阅,销毁断点实例
onUnmounted(() => {
  unsubscribe();
  breakpointManager.destroy();
})

</script>
<style lang="less" scoped>
@import './index.less';
</style>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.

示例代码

基于H5框架的多设备开发​​sample示例代码地址​

分类
标签
收藏
回复
举报


回复
    相关推荐