当前位置: 首页 > news >正文

Vue3项目匹配PC端和移动端---两套组件

        在 Vue 3 项目中同时适配 PC 和移动端,结合 响应式布局、动态组件加载 和 设备检测 来实现

vite : https://cn.vitejs.dev/guide/#scaffolding-your-first-vite-project

npm create vite@latest my-vue-app --template vue
cd my-vue-app
npm install
npm run dev

device.js

export function isMobile() {
  // 方法 1:通过屏幕宽度判断
  return window.innerWidth <= 768

  // 方法 2:通过用户代理字符串判断
  // const userAgent = navigator.userAgent.toLowerCase()
  // return /iphone|ipod|android|windows phone/.test(userAgent)
}

    DesktopLayout.vue:PC 端布局

    <template>
        <div class="desktop-layout">
          <h1>PC 端布局</h1>
          <p>这是 PC 端的页面内容。</p>
          <!-- <router-view :key="$route.fullPath"/>  -->
        </div>
      </template>
      
      <script setup>
      // 这里不需要额外的逻辑
      </script>
      
      <style scoped>
      .desktop-layout {
        width: 1200px;
        margin: 0 auto;
        background-color: #f0f0f0;
        padding: 20px;
      }
      </style>
    MobileLayout.vue
    <template>
        <div class="mobile-layout">
          <h1>移动端布局</h1>
          <p>这是移动端的页面内容。</p>
        </div>
      </template>
      
      <script setup>
      // 这里不需要额外的逻辑
      </script>
      
      <style scoped>
      .mobile-layout {
        width: 100%;
        padding: 10px;
        background-color: #e0e0e0;
      }
      </style>

    在 App.vue 中根据设备类型动态加载组件 DesktopLayout 或 MobileLayout

    <template>
      <div id="app">
        <component :is="layout" />
       
        <h1>主题切换示例</h1>
        <button @click="toggleTheme">切换主题</button>
        <!-- <router-view :key="$route.fullPath"/> -->
      </div>
    </template>
    
    <script setup>
    import { ref, onMounted, onBeforeUnmount } from 'vue'
    import { useThemeStore} from './store/themeStore'
    import DesktopLayout from './components/DesktopLayout.vue'
    import MobileLayout from './components/MobileLayout.vue'
    import { isMobile } from './utils/device'
    
    
    const themeStore = useThemeStore()
    
    // 初始化时用当前主题
    onMounted(() => {
      themeStore.applyTheme(themeStore.currentTheme)
    })
    
    const toggleTheme = () => {
      // const newTheme = themeStore.currentTheme === 'light' ? 'blue' : 'light'
      // themeStore.setTheme(newTheme)
    
      // 多个主题切换
      let themes = ['light', 'blue', 'dark', 'green']
      let currentIndex = themes.indexOf(themeStore.currentTheme)
      let newTheme = themes[(currentIndex + 1) % themes.length] 
      themeStore.setTheme(newTheme)
    }
    
    // 动态加载布局组件
    const layout = ref('DesktopLayout')
    
    // 检测设备类型
    const checkDevice = () => {
      layout.value = isMobile() ? MobileLayout : DesktopLayout
    }
    
    // 组件挂载时检测设备类型
    onMounted(() => {
      checkDevice()
      window.addEventListener('resize', checkDevice)
    })
    
    // 组件销毁时移除事件监听
    onBeforeUnmount(() => {
      window.removeEventListener('resize', checkDevice)
    })
    </script>
    
    <style>
    #app {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      text-align: center;
      background-color: var(--bg-color);
      /* color: var(--text-color); */
      height: 100vh;
      padding: 20px;
      transition: background-color 0.3s, color 0.3s;
    }
    button {
      background-color: var(--primary-color);
      color: var(--text-color);
      border: none;
    }
    </style>
    global.css
    /* src/assets/global.css */
    
    
    /* 全局样式 */
    body {
      margin: 0;
      font-family: Arial, sans-serif;
    }
    
    /* 响应式布局 */
    @media (max-width: 768px) {
      body {
        font-size: 14px;
        color: #ff6347;
      }
    }
    
    
    
    /* :root { */
    /* 默认主题 */
    /* --bg-color: #ffffff;
      --text-color: #000000;
    } */
    [data-theme="light"] {
      --bg-color: #ffffff;
      --text-color: #000000;
      --primary-color: #42b983;
    }
    
    [data-theme="dark"] {
      /* 暗色主题 */
      --bg-color: #333333;
      --text-color: #ffffff;
      --primary-color: #ff6347;
    }
    
    [data-theme="blue"] {
      /* 蓝色主题 */
      --bg-color: #1e90ff;
      --text-color: #ffffff;
      --primary-color: #ffd700;
    }
    
    [data-theme="green"] {
      /* 绿色主题 */
      --bg-color: #2ecc71;
      --text-color: #ffffff;
      --primary-color: #3498db;
    }
    
    

    main.js这引入global.css

    import './assets/global.css'; // 引入全局样式

    相关文章:

  • 生成式人工智能大模型备案政策深度解读
  • 请大家推荐一款免费的网站模版。
  • 【C++】多参数构造函数使用explict的情形
  • LSM-Tree(Log-Structured Merge-Tree)详解
  • Java 单例模式与线程安全
  • Electron使用WebAssembly实现CRC-16 MAXIM校验
  • jmeter环境搭建及使用
  • 【第9章】亿级电商平台订单系统-整体技术架构设计
  • 【华为OD-E卷 -123 判断一组不等式是否满足约束并输出最大差 100分(python、java、c++、js、c)】
  • AI技术学习笔记系列003:`liger_kernel`、`flashattn2` 和 `unsloth` 介绍
  • 第52届医疗器械博览会盛装启幕,开启AI 赋能驱动医疗装备“新视界”
  • 【k8s004】 Docker 打包 K8s镜像
  • 《灵珠觉醒:从零到算法金仙的C++修炼》卷三·天劫试炼(67)混元无极算素数 - 埃拉托斯特尼筛法
  • 阿里云服务器环境部署 一
  • 【从0到1搞懂大模型】RNN基础(4)
  • 路由的原理
  • pytorch小记(九):pytorch中创建指定形状的张量: torch.empty
  • python中a is None 和 a==None有区别吗
  • 簡易傢俬購物Apps
  • 设计模式(行为型)-观察者模式
  • 德国放弃长期以来的反核立场,寻求修复德法合作关系
  • 竞彩湃|水晶宫夺冠后乘胜追击,四大皆空曼城人间清醒?
  • 印度空军为“阵风”战机换装国产导弹,以增强作战能力推动国防自主
  • 欧洲观察室|“美国优先”使欧盟对华政策面临地缘经济困境
  • 上海中心城区首条“定制化低空观光航线”启航,可提前一天提需求
  • 莱布雷希特专栏:古典乐坛边缘人