欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue如何實現(xiàn)pc和移動端布局詳細代碼

 更新時間:2023年10月11日 10:01:02   作者:我是沐辰  
這篇文章主要給大家介紹了關(guān)于vue如何實現(xiàn)pc和移動端布局的相關(guān)資料, Vue響應(yīng)式布局適配是一種根據(jù)設(shè)備特性自動調(diào)整布局的方法,文中通過代碼以及圖文介紹的非常詳細,需要的朋友可以參考下

1.核心點

  • 本方案未采用同一套代碼去響應(yīng)各端的方式去開發(fā),個人覺得兼容太麻煩、樣式難以精確控制,遂采用 pc 和 移動端 兩套代碼、一套路由規(guī)則的方式去開發(fā)
  • 本方案適用于官網(wǎng)類、展示類的項目
  • 本方案在移動端中使用 vw 作為基本單位,使用 postcss-px-to-viewport 實現(xiàn)移動端 px 單位自動轉(zhuǎn)為 vw

2.開擼

2.1 獲取當前設(shè)備類型,共享給全局使用

  • vuex 中定義名為 device 的 state,用于全局共享當前設(shè)備(pc || 移動)
export default new Vuex.Store({
  state: {
    device: 'pc'
  },
  mutations: {
    setDevice (state, data) {
      state.device = data
    }
  }
})
  • App.vue 中使用像素來檢測當前所處設(shè)備
<template>
  <div id="app">
    <router-view />
  </div>
</template>
<script>
import { mapMutations } from 'vuex'
import { throttle } from 'lodash-es'
export default {
  created () {
    // resize節(jié)流
    this.resizeChange = throttle(this.resizeChange, 200)
    this.resizeChange()
    window.addEventListener('resize', this.resizeChange, false)
  },
  methods: {
    ...mapMutations(['setDevice']),
    resizeChange () {
      // 判斷是否是 pc 或者 移動端,也可以用機型之類的條件來判斷,個人覺得用像素更簡單快捷
      // 默認設(shè)置當屏幕寬度 > 1000 時,為PC端
      if (document.documentElement.clientWidth > 1000) {
        this.setDevice('pc')
      } else {
        // 默認設(shè)置當屏幕寬度 <= 1000 時,為移動端
        this.setDevice('m')
      }
    }
  },
  destroyed () {
    window.removeEventListener('resize', this.resizeChange, false)
  }
}
</script>

到目前為止,我們可以通過 vuex 中的 device 拿到當前的設(shè)備類型,pc 對應(yīng)的是 pc 端,m 對應(yīng)的是移動端

2.2 頁面文件結(jié)構(gòu)及關(guān)鍵代碼

  • 頁面文件結(jié)構(gòu)

  • 代碼
// index.vue
<template>
  <div class="index">
    <component :is="$store.state.device"></component>
  </div>
</template>
<script>
import m from './device/m.vue'
import pc from './device/pc.vue'
export default {
  name: 'index',
  components: {
    pc,
    m
  }
}
</script>
// device 目錄下的 m.vue 或 pc.vue
// m.vue
<template>
  <div class="index-m">
  	<p> 這里沒有其他特殊之處,正常寫 移動端 和 pc 端代碼即可 </p>
  	<p> m.vue 和 pc.vue 沒有本質(zhì)差異,僅修改 類名 或 組件名稱后綴為 -pc </p>
  </div>
</template>
<script>
export default {
  name: 'index-m'
}
</script>
<style lang="scss" scoped>
.index-m {
	// 如果是 m.vue,這里正常使用 px 作為基本單位
}
</style>

在首頁 index.vue 中,將其所對應(yīng)的 pc 端代碼定義為 pc.vue,對應(yīng)的 移動端 代碼定義為 m.vue,并導(dǎo)入到 index.vue 中,分別命名為 pc 和 m,而后使用動態(tài)組件,并使用$store.state.device來控制當前所展示的頁面為 pc端 還是 移動端。

2.3 使用 postcss-px-to-viewport 將項目中的 px 單位轉(zhuǎn)換為 vw

截止到目前,我們已經(jīng)實現(xiàn)了不同設(shè)備下(pc端 或 移動端)代碼的按需展示,但是有一個問題亟待解決。

眾所周知,移動端設(shè)備的屏幕大小不一、“千奇百怪”,如果繼續(xù)使用 px 作為基本單位,最后呈現(xiàn)的效果必然不理想,經(jīng)過對比,決定使用 vw 來作為移動端的基本單位。

但是我們都知道,一般情況下設(shè)計稿的尺寸是固定的 px 單位,在開發(fā)時需要將 px 單位轉(zhuǎn)為 vw 來進行開發(fā),但是這一過程略顯繁瑣,哪怕安裝了 vs code 的單位轉(zhuǎn)換插件依舊差強人意,這時,我們便可以請出 postcss-px-to-viewport 來幫我們解決這一問題。

  • 作用
    該插件可以讓我們在寫 css 代碼的時候正常的使用 px,其會將 px 單位自動轉(zhuǎn)換為視口單位 (vw, vh, vmin, vmax)

  • 文檔

  • 安裝

npm install postcss-px-to-viewport --save-dev
yarn add -D postcss-px-to-viewport
  • 配置
// .postcssrc.js
module.exports = {
  plugins: {
      // 用來給不同的瀏覽器自動添加相應(yīng)前綴,如-webkit-,-moz-等等
      autoprefixer: {}, 
      "postcss-px-to-viewport": {
        // 需要轉(zhuǎn)換的單位,默認為"px"
        unitToConvert: 'px',
        viewportWidth: 375,
        // 單位轉(zhuǎn)換后保留的精度
        unitPrecision: 3,
        // 能轉(zhuǎn)化為vw的屬性列表
        propList: [
          '*'
        ],
        // 希望使用的視口單位
        viewportUnit: 'vw',
        // 字體使用的視口單位
        fontViewportUnit: 'vw',
        // 設(shè)置最小的轉(zhuǎn)換數(shù)值,如果為1的話,只有大于1的值會被轉(zhuǎn)換
        minPixelValue: 1,
        // 僅轉(zhuǎn)換的文件,這里不要使用 \/ 去匹配文件,不生效??
        // 這里還有一個坑,就是如果使用了 include 規(guī)則的話,正常的版本不生效,可以安裝這個
        // "postcss-px-to-viewport": "github:evrone/postcss-px-to-viewport"
        include: [/device\\m.vue/]
      }
  }
};

配置include: [/device\\m.vue/]使我們移動端代碼中的 px 單位自動轉(zhuǎn)換為 vw,而 pc 端的代碼不受影響。

2.4 使用 node 自動創(chuàng)建符合需求的頁面

2.4.1 創(chuàng)建腳本文件

  • 根目錄下創(chuàng)建 scripts 及其子文件

  • template.js
module.exports = {
  viewTemplate: viewName => {
    return `
<template>
  <div class="${viewName}">
    <component :is="$store.state.device"></component>
  </div>
</template>
<script>
import m from './device/m.vue'
import pc from './device/pc.vue'
export default {
  name: '${viewName}',
  components: {
    pc,
    m
  }
}
</script>
`
  },
// 移動端 頁面基本結(jié)構(gòu)
  mTemplate: viewName => {
    return `
<template>
  <div class="${viewName}-m">
  </div>
</template>
<script>
export default {
  name: '${viewName}-m'
}
</script>
<style lang="scss" scoped>
.${viewName}-m {
}
</style>
`
  },
// pc端 頁面基本結(jié)構(gòu)
  pcTemplate: viewName => {
    return `
<template>
  <div class="${viewName}-pc">
  </div>
</template>
<script>
export default {
  name: '${viewName}-pc'
}
</script>
<style lang="scss" scoped>
.${viewName}-pc {
}
</style>
`
  }
}
  • generateView.js
// generateView.js
const chalk = require('chalk')
const path = require('path')
const fs = require('fs')
const log = message => console.log(chalk.green(`${message}`))
const successLog = message => console.log(chalk.blue(`${message}`))
const errorLog = error => console.log(chalk.red(`${error}`))
const { viewTemplate, mTemplate, pcTemplate } = require('./template')
const generateFile = (path, data) => {
  if (fs.existsSync(path)) {
    errorLog(`${path}文件已存在`)
    return
  }
  return new Promise((resolve, reject) => {
    fs.writeFile(path, data, 'utf8', err => {
      if (err) {
        errorLog(err.message)
        reject(err)
      } else {
        resolve(true)
      }
    })
  })
}
// 創(chuàng)建頁面目錄
const dotExistDirectoryCreate = (directory) => {
  return new Promise((resolve) => {
    mkdirs(directory, function () {
      resolve(true)
    })
  })
}
// 遞歸創(chuàng)建目錄
const mkdirs = (directory, callback) => {
  var exists = fs.existsSync(directory)
  if (exists) {
    callback()
  } else {
    mkdirs(path.dirname(directory), function () {
      fs.mkdirSync(directory)
      callback()
    })
  }
}
// 獲取頁面名稱
const getViewName = (viewPath) => {
  const arr = viewPath.split('\\')
  return arr[arr.length - 1]
}
log('請輸入要生成的頁面組件名稱(無需添加.vue后綴)、支持深層目錄解析(dirName/viewName)、頁面將生成在 views/目錄下')
let viewName = ''
process.stdin.on('data', async chunk => {
  const inputName = String(chunk).trim().toString()
  // Vue頁面組件路徑
  let viewPath = path.resolve(__dirname, '../src/views', inputName)
  viewName = getViewName(inputName)
  viewPath = path.resolve(viewPath, viewName + '.vue')
  const viewDirectory = path.dirname(viewPath)
  // 檢查界面是否存在
  const hasViewExists = fs.existsSync(viewPath)
  if (hasViewExists) {
    errorLog(`${inputName}頁面已存在,請重新輸入`)
    return
  }
  try {
    // 1.生成頁面目錄
    log(`正在生成頁面目錄 ${viewDirectory}`)
    await dotExistDirectoryCreate(viewDirectory)
    // 2.生成頁面子目錄
    const sonViewDirectory = path.resolve(viewDirectory, './device')
    log(`正在生成頁面子目錄 ${sonViewDirectory}`)
    await dotExistDirectoryCreate(sonViewDirectory)
    // 3.生成 m.vue 頁面
    const mViewPath = path.resolve(sonViewDirectory, './m.vue')
    log(`正在生成子目錄子頁面文件 ${mViewPath}`)
    await generateFile(mViewPath, mTemplate(viewName))
    // 4.生成 pc.vue 頁面
    const pcViewPath = path.resolve(sonViewDirectory, './pc.vue')
    log(`正在生成子目錄子頁面文件 ${pcViewPath}`)
    await generateFile(pcViewPath, pcTemplate(viewName))
    // 5.生成頁面
    log(`正在生成頁面文件 ${viewPath}`)
    await generateFile(viewPath, viewTemplate(viewName))
    successLog('生成成功')
  } catch (e) {
    errorLog(e.message)
  }
  process.stdin.emit('end')
})
process.stdin.on('end', () => {
  log('exit')
  process.exit()
})
  • package.json 中 scripts 節(jié)點下添加如下代碼
  "new:view": "node ./scripts/generateView"

2.4.2 使用腳本生成符合需求的頁面

  • 打開終端,輸入 npm run new:view
  • 根據(jù)提示,輸入要生成的文件名稱(支持深層目錄解析)
  • 下圖中我們創(chuàng)建了一個名為 about 的頁面,可以看到,只需要一個指令及文件名,我們便得到了想要的頁面結(jié)構(gòu),極大的提高了開發(fā)效率

3.持續(xù)優(yōu)化

經(jīng)過實踐發(fā)現(xiàn),pc端 和 移動端 的差別更多體現(xiàn)在頁面元素的大小、位置、顯隱上,而實際的業(yè)務(wù)邏輯變化并不大,上述方案中并未抽離頁面的 js 代碼,導(dǎo)致代碼存在冗余,這里我們可以使用 mixins 來優(yōu)化。

舉例來講,我們可以在首頁 index 頁面目錄下添加一個 mixin.js 文件,將 device/pc.vue 和 device/m.vue 的公共業(yè)務(wù)邏輯抽離到該文件中,從而實現(xiàn)復(fù)用。

因項目較小,我也是后知后覺的才想到可以進一步優(yōu)化,現(xiàn)如今項目已部署,因此就沒有再調(diào)整,可以按照上述方案自行優(yōu)化調(diào)整。

到此這篇關(guān)于vue如何實現(xiàn)pc和移動端布局的文章就介紹到這了,更多相關(guān)vue pc和移動端布局內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue列表數(shù)據(jù)刪除后主動刷新頁面及刷新方法詳解

    vue列表數(shù)據(jù)刪除后主動刷新頁面及刷新方法詳解

    這篇文章主要給大家介紹了關(guān)于vue列表數(shù)據(jù)刪除后主動刷新頁面及刷新方法的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • vant中的toast層級改變操作

    vant中的toast層級改變操作

    這篇文章主要介紹了vant中的toast層級改變操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • vue之el-menu-item如何更改導(dǎo)航菜單欄選中的背景顏色

    vue之el-menu-item如何更改導(dǎo)航菜單欄選中的背景顏色

    這篇文章主要介紹了vue之el-menu-item如何更改導(dǎo)航菜單欄選中的背景顏色問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • vue中路由跳轉(zhuǎn)不計入history的操作

    vue中路由跳轉(zhuǎn)不計入history的操作

    這篇文章主要介紹了vue中路由跳轉(zhuǎn)不計入history的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 詳解vue+css3做交互特效的方法

    詳解vue+css3做交互特效的方法

    本篇文章主要介紹了詳解vue+css3做交互特效的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • vue.js提交按鈕時進行簡單的if判斷表達式詳解

    vue.js提交按鈕時進行簡單的if判斷表達式詳解

    這篇文章主要給大家介紹了關(guān)于vue.js提交按鈕時如何進行簡單的if判斷表達式的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-08-08
  • Vue3中Reactive的使用詳解

    Vue3中Reactive的使用詳解

    Vue 3 的 Composition API 帶來了強大的 reactive 函數(shù),它允許你在 Vue 應(yīng)用程序中創(chuàng)建響應(yīng)式數(shù)據(jù),本文我們將深入探討 Vue 3 的 reactive,并提供一些注意事項和解決方案,希望可以幫助打更好地使用它
    2023-11-11
  • Vue3中reactive丟失響應(yīng)式問題詳解

    Vue3中reactive丟失響應(yīng)式問題詳解

    在vue3中,如果你用reactive聲明了一個對象,用另一個對象直接給它賦值,那么它就會失去響應(yīng)式,下面這篇文章主要給大家介紹了關(guān)于Vue3中reactive丟失響應(yīng)式問題的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • vue中rem的配置的方法示例

    vue中rem的配置的方法示例

    這篇文章主要介紹了vue中rem的配置的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • vue3實戰(zhàn)-axios請求封裝問題(get、post、put、delete)

    vue3實戰(zhàn)-axios請求封裝問題(get、post、put、delete)

    這篇文章主要介紹了vue3實戰(zhàn)-axios請求封裝問題(get、post、put、delete),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03

最新評論