vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > vue pc和移动端布局

vue如何实现pc和移动端布局详细代码

作者:我是沐辰

这篇文章主要给大家介绍了关于vue如何实现pc和移动端布局的相关资料, Vue响应式布局适配是一种根据设备特性自动调整布局的方法,文中通过代码以及图文介绍的非常详细,需要的朋友可以参考下

1.核心点

2.开撸

2.1 获取当前设备类型,共享给全局使用

export default new Vuex.Store({
  state: {
    device: 'pc'
  },
  mutations: {
    setDevice (state, data) {
      state.device = data
    }
  }
})
<template>
  <div id="app">
    <router-view />
  </div>
</template>
<script>
import { mapMutations } from 'vuex'
import { throttle } from 'lodash-es'
export default {
  created () {
    // resize节流
    this.resizeChange = throttle(this.resizeChange, 200)
    this.resizeChange()
    window.addEventListener('resize', this.resizeChange, false)
  },
  methods: {
    ...mapMutations(['setDevice']),
    resizeChange () {
      // 判断是否是 pc 或者 移动端,也可以用机型之类的条件来判断,个人觉得用像素更简单快捷
      // 默认设置当屏幕宽度 > 1000 时,为PC端
      if (document.documentElement.clientWidth > 1000) {
        this.setDevice('pc')
      } else {
        // 默认设置当屏幕宽度 <= 1000 时,为移动端
        this.setDevice('m')
      }
    }
  },
  destroyed () {
    window.removeEventListener('resize', this.resizeChange, false)
  }
}
</script>

到目前为止,我们可以通过 vuex 中的 device 拿到当前的设备类型,pc 对应的是 pc 端,m 对应的是移动端

2.2 页面文件结构及关键代码

// 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 没有本质差异,仅修改 类名 或 组件名称后缀为 -pc </p>
  </div>
</template>
<script>
export default {
  name: 'index-m'
}
</script>
<style lang="scss" scoped>
.index-m {
	// 如果是 m.vue,这里正常使用 px 作为基本单位
}
</style>

在首页 index.vue 中,将其所对应的 pc 端代码定义为 pc.vue,对应的 移动端 代码定义为 m.vue,并导入到 index.vue 中,分别命名为 pc 和 m,而后使用动态组件,并使用$store.state.device来控制当前所展示的页面为 pc端 还是 移动端。

2.3 使用 postcss-px-to-viewport 将项目中的 px 单位转换为 vw

截止到目前,我们已经实现了不同设备下(pc端 或 移动端)代码的按需展示,但是有一个问题亟待解决。

众所周知,移动端设备的屏幕大小不一、“千奇百怪”,如果继续使用 px 作为基本单位,最后呈现的效果必然不理想,经过对比,决定使用 vw 来作为移动端的基本单位。

但是我们都知道,一般情况下设计稿的尺寸是固定的 px 单位,在开发时需要将 px 单位转为 vw 来进行开发,但是这一过程略显繁琐,哪怕安装了 vs code 的单位转换插件依旧差强人意,这时,我们便可以请出 postcss-px-to-viewport 来帮我们解决这一问题。

npm install postcss-px-to-viewport --save-dev
yarn add -D postcss-px-to-viewport
// .postcssrc.js
module.exports = {
  plugins: {
      // 用来给不同的浏览器自动添加相应前缀,如-webkit-,-moz-等等
      autoprefixer: {}, 
      "postcss-px-to-viewport": {
        // 需要转换的单位,默认为"px"
        unitToConvert: 'px',
        viewportWidth: 375,
        // 单位转换后保留的精度
        unitPrecision: 3,
        // 能转化为vw的属性列表
        propList: [
          '*'
        ],
        // 希望使用的视口单位
        viewportUnit: 'vw',
        // 字体使用的视口单位
        fontViewportUnit: 'vw',
        // 设置最小的转换数值,如果为1的话,只有大于1的值会被转换
        minPixelValue: 1,
        // 仅转换的文件,这里不要使用 \/ 去匹配文件,不生效??
        // 这里还有一个坑,就是如果使用了 include 规则的话,正常的版本不生效,可以安装这个
        // "postcss-px-to-viewport": "github:evrone/postcss-px-to-viewport"
        include: [/device\\m.vue/]
      }
  }
};

配置include: [/device\\m.vue/]使我们移动端代码中的 px 单位自动转换为 vw,而 pc 端的代码不受影响。

2.4 使用 node 自动创建符合需求的页面

2.4.1 创建脚本文件

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>
`
  },
// 移动端 页面基本结构
  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端 页面基本结构
  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
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)
      }
    })
  })
}
// 创建页面目录
const dotExistDirectoryCreate = (directory) => {
  return new Promise((resolve) => {
    mkdirs(directory, function () {
      resolve(true)
    })
  })
}
// 递归创建目录
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()
})
  "new:view": "node ./scripts/generateView"

2.4.2 使用脚本生成符合需求的页面

3.持续优化

经过实践发现,pc端 和 移动端 的差别更多体现在页面元素的大小、位置、显隐上,而实际的业务逻辑变化并不大,上述方案中并未抽离页面的 js 代码,导致代码存在冗余,这里我们可以使用 mixins 来优化。

举例来讲,我们可以在首页 index 页面目录下添加一个 mixin.js 文件,将 device/pc.vue 和 device/m.vue 的公共业务逻辑抽离到该文件中,从而实现复用。

因项目较小,我也是后知后觉的才想到可以进一步优化,现如今项目已部署,因此就没有再调整,可以按照上述方案自行优化调整。

到此这篇关于vue如何实现pc和移动端布局的文章就介绍到这了,更多相关vue pc和移动端布局内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文