【HarmonyOS开发】通过媒体查询,实现一次开发,多端部署

 媒体查询(Media Queries)是一种在CSS中使用的技术,用于根据设备的特性和属性(如屏幕宽度、设备类型等)来应用不同的样式规则。通过媒体查询,可以根据不同的设备或屏幕尺寸为用户提供优化的布局和样式。

1、Web中CSS的媒体查询

1.1 根据屏幕宽度应用样式

@media screen and (max-width: 768px) {
  /* 当屏幕宽度小于等于 768px 时应用的样式 */
  /* 适用于移动设备或小屏幕 */
}

@media screen and (min-width: 769px) and (max-width: 1024px) {
  /* 当屏幕宽度在 769px 到 1024px 之间时应用的样式 */
  /* 适用于平板设备或中等屏幕 */
}

@media screen and (min-width: 1025px) {
  /* 当屏幕宽度大于等于 1025px 时应用的样式 */
  /* 适用于桌面设备或大屏幕 */
}

1.2 根据设备类型应用样式

@media screen and (orientation: landscape) {
  /* 当设备处于横向(landscape)方向时应用的样式 */
}

@media screen and (orientation: portrait) {
  /* 当设备处于纵向(portrait)方向时应用的样式 */
}

@media print {
  /* 在打印时应用的样式 */
}

1.3 组合多个条件的媒体查询

@media screen and (min-width: 768px) and (max-width: 1024px),
       (orientation: portrait) {
  /* 当屏幕宽度在 768px 到 1024px 之间或设备处于纵向方向时应用的样式 */
}

2、Web中JS的媒体查询

可以使用window.matchMedia()方法来执行媒体查询,并根据查询结果执行相应的操作。这个方法返回一个MediaQueryList对象,该对象具有matches属性,表示查询是否匹配。将查询的结果存储在Window全局变量即可。

// 创建一个媒体查询对象
var mediaQuery = window.matchMedia('(max-width: 768px)');

// 检查媒体查询的匹配状态
if (mediaQuery.matches) {
  // 当媒体查询匹配时执行的操作
  // 适用于移动设备或小屏幕
  console.log('Media query matches!');
} else {
  // 当媒体查询不匹配时执行的操作
  // 适用于平板设备或大屏幕
  console.log('Media query does not match!');
}

// 添加一个媒体查询监听器
mediaQuery.addListener(function(mediaQueryList) {
  if (mediaQueryList.matches) {
    // 当媒体查询匹配时执行的操作
    console.log('Media query matches!');
  } else {
    // 当媒体查询不匹配时执行的操作
    console.log('Media query does not match!');
  }
});

3、Vue/React中的媒体查询

3.1 Vue中使用媒体查询

3.1.1 计算属性

<template>
  <div :class="containerClass">
    <p>Content goes here</p>
  </div>
</template>

<script>
import { ref, onMounted, onUnmounted } from 'vue';

export default {
  setup() {
    const containerClass = ref('');

    const updateContainerClass = () => {
      containerClass.value = window.innerWidth < 768 ? 'small-screen' : 'large-screen';
    };

    onMounted(() => {
      updateContainerClass();
      window.addEventListener('resize', updateContainerClass);
    });

    onUnmounted(() => {
      window.removeEventListener('resize', updateContainerClass);
    });

    return {
      containerClass
    };
  }
};
</script>

<style>
.small-screen {
  /* 在小屏幕上应用的样式 */
}

.large-screen {
  /* 在大屏幕上应用的样式 */
}
</style>

3.1.2 三方库(vue-mq)

  • vue-mq(以这个为例)
  • vue-breakpoint-component
  • vue-responsive
  • vue-media-query-mixin
npm install vue-mq
// main.js中配置
import { createApp } from 'vue';
import App from './App.vue';
import VueMq from 'vue-mq';

const app = createApp(App);

app.use(VueMq, {
  breakpoints: {
    mobile: 768,
    tablet: 1024,
    desktop: 1280,
    // 根据需要添加其他断点
  }
});

app.mount('#app');
// 使用
<template>
  <div :class="$mq">
    <p>Content goes here</p>
  </div>
</template>

<style>
.mobile {
  /* 在移动设备上应用的样式 */
}

.tablet {
  /* 在平板设备上应用的样式 */
}

.desktop {
  /* 在桌面设备上应用的样式 */
}
</style>

3.2 React中使用媒体查询(三方库)

  • react-responsive(以这个为主)
  • react-responsive-hooks
  • react-media
  • react-match-media
import React from 'react';
import styles from './MyComponent.module.css';
import { useMediaQuery } from 'react-responsive';

const MyComponent = () => {
  const isSmallScreen = useMediaQuery({ maxWidth: 768 });
  const isMediumScreen = useMediaQuery({ minWidth: 769, maxWidth: 1024 });
  const isLargeScreen = useMediaQuery({ minWidth: 1025 });

  return (
    <div className={`${styles.container} ${isSmallScreen ? styles.smallScreen : ''} ${isMediumScreen ? styles.mediumScreen : ''} ${isLargeScreen ? styles.largeScreen : ''}`}>
      <p>Content goes here</p>
    </div>
  );
};

export default MyComponent;

4、Harmony中的媒体查询

鸿蒙中主要通过 @ohos.mediaquery 实现媒体查询,进行断点  

// 参考:https://developer.harmonyos.com/cn/docs/documentation/doc-references-V3/js-apis-mediaquery-0000001478181613-V3#ZH-CN_TOPIC_0000001573928789__mediaquerymatchmediasync

import mediaquery from '@ohos.mediaquery'

4.1 封装媒体查询方法(.ts)

import mediaQuery from '@ohos.mediaquery'

class BreakpointSystem {
  private currentBreakpoint: string = 'md'
  private smListener: mediaQuery.MediaQueryListener
  private mdListener: mediaQuery.MediaQueryListener
  private lgListener: mediaQuery.MediaQueryListener

  private updateCurrentBreakpoint(breakpoint: string) {
    if (this.currentBreakpoint !== breakpoint) {
      this.currentBreakpoint = breakpoint
      AppStorage.Set<string>('currentBreakpoint', this.currentBreakpoint)
    }
    console.log('======currentBreakpoint======', this.currentBreakpoint)
  }

  private isBreakpointSM = (mediaQueryResult) => {
    if (mediaQueryResult.matches) {
      this.updateCurrentBreakpoint('sm')
    }
  }

  private isBreakpointMD = (mediaQueryResult) => {
    if (mediaQueryResult.matches) {
      this.updateCurrentBreakpoint('md')
    }
  }

  private isBreakpointLG = (mediaQueryResult) => {
    if (mediaQueryResult.matches) {
      this.updateCurrentBreakpoint('lg')
    }
  }

  public register() {
    this.smListener = mediaQuery.matchMediaSync('(320vp<=width<600vp)')
    this.smListener.on('change', this.isBreakpointSM)
    this.mdListener = mediaQuery.matchMediaSync('(600vp<=width<840vp)')
    this.mdListener.on('change', this.isBreakpointMD)
    this.lgListener = mediaQuery.matchMediaSync('(840vp<=width)')
    this.lgListener.on('change', this.isBreakpointLG)
  }

  public unregister() {
    this.smListener.off('change', this.isBreakpointSM)
    this.mdListener.off('change', this.isBreakpointMD)
    this.lgListener.off('change', this.isBreakpointLG)
  }
}

export default new BreakpointSystem()

4.2 使用封装的函数

4.2.1 轮播图中使用

import breakpointSystem from '../common/BreakpointSystem'

@Component
export default struct IndexSwiper {
  @StorageProp('currentBreakpoint') currentBreakpoint: string = 'md'

  @Builder swiperItem(imageSrc) {
    Image(imageSrc)
      .width('100%')
      .aspectRatio(2.5)
      .objectFit(ImageFit.Fill)
  }

  aboutToAppear() {
    breakpointSystem.register()
  }

  aboutToDisappear() {
    breakpointSystem.unregister()
  }

  build() {
    Swiper() {
      this.swiperItem($r('app.media.ic_public_swiper1'))
      this.swiperItem($r('app.media.ic_public_swiper2'))
      this.swiperItem($r('app.media.ic_public_swiper3'))
      this.swiperItem($r('app.media.ic_public_swiper1'))
      this.swiperItem($r('app.media.ic_public_swiper2'))
      this.swiperItem($r('app.media.ic_public_swiper3'))
    }
    .autoPlay(true)
    .indicator(false)
    .itemSpace(10)
    .displayCount(this.currentBreakpoint === 'sm' ? 1 : (this.currentBreakpoint === 'md' ? 2 : 3))
    .width('100%')
    .padding({ left: 12, right: 12, bottom: 16, top: 16 })
  }
}

4.2.2 TarBar中使用

import breakpointSystem from '../common/BreakpointSystem'

@Entry
@Component
struct Index {
  @State currentIndex: number = 0
  @StorageProp('currentBreakpoint') currentBreakpoint: string = 'md'
  private onTabChange = (index: number) => {
    this.currentIndex = index
  }

  aboutToAppear() {
    breakpointSystem.register()
  }

  aboutToDisappear() {
    breakpointSystem.unregister()
  }

  @Builder
  tabItem(index: number, title: Resource, icon: Resource, iconSelected: Resource) {
    TabBarItem({
      index: index,
      currentIndex: this.currentIndex,
      title: title,
      icon: icon,
      iconSelected: iconSelected
    })
  }

  build() {
    Tabs({ barPosition: this.currentBreakpoint === 'lg' ? BarPosition.Start : BarPosition.End }) {
      TabContent() {
        Home()
      }
      .tabBar(this.tabItem(0, $r('app.string.tabBar1'), $r('app.media.ic_home_normal'), $r('app.media.ic_home_actived')))

      TabContent() {
      }
      .tabBar(this.tabItem(1, $r('app.string.tabBar2'), $r('app.media.ic_app_normal'), $r('app.media.ic_app_actived')))

      TabContent() {
      }
      .tabBar(this.tabItem(2, $r('app.string.tabBar3'), $r('app.media.ic_game_normal'), $r('app.media.ic_mine_actived')))

      TabContent() {
      }
      .tabBar(this.tabItem(3, $r('app.string.tabBar4'), $r('app.media.ic_search_normal'), $r('app.media.ic_search_actived')))
    }
    .barWidth(this.currentBreakpoint === 'lg' ? 96 : '100%')
    .barHeight(this.currentBreakpoint === 'lg' ? '60%' : 56)
    .vertical(this.currentBreakpoint === 'lg')
    .onChange(this.onTabChange)
    .backgroundColor('#F1F3F5')
  }
}

4.3 效果图

5、额外加一个Hilog的封装扩展(.ts)

import hilog from '@ohos.hilog';

export class Logger {
  // 日志对应的领域标识
  private domain: number = 0xF811;
  // tag日志标识
  private prefix: string = '[Logger_Utils]';
  // 格式字符串,用于日志的格式化输出
  private format: string = '%{public}s, %{public}s';

  constructor(prefix: string) {
    this.prefix = prefix;
  }

  debug(...args: string[]): void {
    hilog.debug(this.domain, this.prefix, this.format, args);
  }

  info(...args: string[]): void {
    hilog.info(this.domain, this.prefix, this.format, args);
  }

  warn(...args: string[]): void {
    hilog.warn(this.domain, this.prefix, this.format, args);
  }

  error(...args: string[]): void {
    hilog.error(this.domain, this.prefix, this.format, args);
  }
}

export default new Logger('[Logger_Utils]');

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/287824.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

three.js: gltf模型设置发光描边

效果&#xff1a; 代码 &#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div><div style"padding: 10px…

C++Qt6 哈夫曼编码求解 数据结构课程设计 | JorbanS

一、 问题描述 在进行程序设计时&#xff0c;通常给每一个字符标记一个单独的代码来表示一组字符&#xff0c;即编码。在进行二进制编码时&#xff0c;假设所有的代码都等长&#xff0c;那么表示 n 个不同的字符需要 位&#xff0c;称为等长编码。如果每个字符的使用频率相等&…

【算法系列 | 11】深入解析查找算法之—插值查找

序言 心若有阳光&#xff0c;你便会看见这个世界有那么多美好值得期待和向往。 决定开一个算法专栏&#xff0c;希望能帮助大家很好的了解算法。主要深入解析每个算法&#xff0c;从概念到示例。 我们一起努力&#xff0c;成为更好的自己&#xff01; 今天第11讲&#xff0c;讲…

阿里云服务器端口PPTP 1723放行教程

阿里云服务器安装PPTP VPN需要先开通1723端口&#xff0c;阿里云服务器端口是在安全组中操作的&#xff0c;阿里云服务器网aliyunfuwuqi.com来详细说明阿里云服务器安全组开放PPTP VPN专用1723端口教程&#xff1a; 阿里云服务器放行1723端口教程 PPTP是点对点隧道协议&#…

八大算法排序@选择排序(C语言版本)

目录 选择排序概念算法思想示例步骤1步骤2步骤...n最后一步 代码实现时间复杂度空间复杂度特性总结 选择排序 概念 选择排序&#xff08;Selection Sort&#xff09;是一种简单直观的排序算法。基本思想是在未排序的序列中找到最小&#xff08;或最大&#xff09;元素&#xf…

数据库之索引

1. 索引的定义 索引是一个排序的列表&#xff0c;包含索引字段的值和其对应的行记录的数据所在的物理地址。 索引的作用&#xff1a; 加快表的查询速度&#xff0c;还可以对字段排序。 2. 索引的工作方式 有了索引后&#xff0c;要根据条件查询某行数据时&#xff0c;需要先…

IPA打包过程中的Invalid Bundle Structure错误如果解决

在iOS应用程序开发中&#xff0c;打包和发布应用程序是一个必要的步骤。有的时候在打包的过程中可能会遇到一些错误&#xff0c;其中一个比较常见的错误是"Invalid Bundle Structure"。这个错误通常意味着应用程序的文件结构不正确&#xff0c;而导致的无法成功打包应…

自动循环采集全站文章

如果文章页面中&#xff0c;有上一篇、下一篇文章&#xff0c;推荐文章等链接&#xff0c;我们可以利用这个特点&#xff0c;仅配置采集一个文章页面&#xff0c;即可采集整个网站或某个分类下的所有文章&#xff0c;实现自动循环采集全站数据&#xff0c;非常方便简单。 使用…

天然药物,到2028年市场规模将达到 3082亿美元

天然药物&#xff0c;也称为草药或传统药物&#xff0c;是指将植物、矿物和动物产品等天然物质用于药用目的。近年来&#xff0c;人们对天然药物作为传统药物的替代品越来越感兴趣&#xff0c;这导致了天然药物市场的增长。全球天然药物市场&#xff1a; 全球天然药物市场预计从…

2024腾讯云服务器租用价格表_优惠活动大全_最新报价

腾讯云服务器租用价格表&#xff1a;轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c;2核4G5M带宽756元三年、轻量4核8G12M服务器446元一年、646元15个月&#xff0c;云服务器CVM S5实例2核2G配置280.8元一年…

安科瑞余压监控系统在住宅小区的应用方案——安科瑞 顾烊宇

【摘要】&#xff1a;本文分析了火灾发生时人员伤亡的主要原因——烟雾&#xff0c;并针对该原因提供切实可靠的系统应用解决方案&#xff0c;并通过具体案例&#xff0c;从设计依据、产品选型、系统组网、现场安装等方式介绍余压监控系统&#xff0c;希望可以在火灾发生时较大…

BMS均衡技术

一、电池的不一致性&#xff1f; 每个电池都有自己的“个性”&#xff0c;要说均衡&#xff0c;得先从电池谈起。即使是同一厂家同一批次生产的电池&#xff0c;也都有自己的生命周期、自己的“个性”——每个电池的容量不可能完全一致。例如以下的两个原因都会造成电池不一致…

树与二叉树笔记整理

摘自小红书 ## 树与二叉树 ## 排序总结

【数据库】MySQL数据库存储引擎、数据库管理和数据库账号管理

【数据库】MySQL数据库存储引擎、数据库管理和数据库账号管理 一 常用的数据引擎1.1 InnoDB存储引擎1.2 MyISAM存储引擎1.3 Memory存储引擎1.4 ARCHIVE存储引擎 二 数据库管理2.1 元数据库概念与分类2.2 相关操作命令 三 数据表的管理四 数据库账户管理 一 常用的数据引擎 数据…

清风数学建模笔记-多分类-fisher线性判别分析

内容&#xff1a;Fisher线性判别分析 一.介绍&#xff1a; 1.给定的训练姐&#xff0c;设法投影到一维的直线上&#xff0c;使得同类样例的投影点尽可能接近和密集&#xff0c;异类投影点尽可能远离。 2.如何同类尽可能接近&#xff1a;方差越小 3.如何异类尽可能远离&#…

阿里云2核2G3M服务器能放几个网站?有限制吗?

阿里云2核2g3m服务器可以放几个网站&#xff1f;12个网站&#xff0c;阿里云服务器网的2核2G服务器上安装了12个网站&#xff0c;甚至还可以更多&#xff0c;具体放几个网站取决于网站的访客数量&#xff0c;像阿里云服务器网aliyunfuwuqi.com小编的网站日访问量都很少&#xf…

获取网页信息

每次copy & paste总是很麻烦&#xff0c;现在有点问题&#xff0c;先记录下来。 需求&#xff1a;获取url 里Feature list&#xff0c;并输出表格形式 可以用Convert curl commands to code&#xff1a;得到get请求的header&#xff0c;cookie等 import requests import…

Jmeter二次开发实操问题汇总(JDK问题,jar包问题)

前提 之前写过一篇文章&#xff1a;https://qa-lsq.blog.csdn.net/article/details/119782694 只是简单尝试了一下生成一个随机手机号码。 但是如果在工作中一个实际场景要用的二次开发&#xff0c;可能会遇到一些问题。 比如这样一个场景&#xff1a; Mobile或者前端调用部分…

【动态规划】LeetCode-10. 正则表达式匹配

10. 正则表达式匹配。 给你一个字符串 s 和一个字符规律 p&#xff0c;请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。 ‘.’ 匹配任意单个字符‘*’ 匹配零个或多个前面的那一个元素 所谓匹配&#xff0c;是要涵盖 整个 字符串 s的&#xff0c;而不是部分字符串。 …

conda: error: argument COMMAND: invalid choice: ‘activate‘

1.问题 2.解决方法 1.寻找基本路径 conda info | grep -i base environment2.更新资源 source /Users/suhang/miniconda3/etc/profile.d/conda.sh3.重新运行命令 conda activate chatglm参考图&#xff1a;
最新文章