同一套代码逻辑,渲染不同的样式到
Web端
和H5端
举个🌰
如图所示,当我们的屏幕尺寸小于等于768px时,我们希望内容是响应式变化的,也就是使用vw为基本单位进行页面渲染;当屏幕尺寸大于768px时,我们则认为网页在Web端进行渲染,希望使用px为基本单位进行渲染。
效果展示
如何处理
以下例子为基于Vue Cli生成的Vue项目。
对于H5,我们可以使用postcss及其插件postcss-px-to-viewport,来进行移动端布局。
1. 安装postcss-px-to-viewport
npm install postcss-px-to-viewport -D
2. 根目录创建postcss.config.js
文件
module.exports = {
plugins: {
'postcss-px-to-viewport': {
unitToConvert: 'px', // 需要转换的单位
viewportWidth: 750, // 设计稿的视口宽度
unitPrecision: 9, // 单位转换后保留的精度
propList: ['*'], // 能转换的vw属性列表
viewportUnit: 'vw', // 希望使用的视口单位
fontViewportUnit: 'vw', // 字体使用的视口单位
selectorBlackList: [], // 需要忽略的css选择器
minPixelValue: 1, // 设置最小的转换数值,如果为1,只有大于1的值才会被转换
mediaQuery: true, // 媒体查询中是否需要转换单位
replace: true, // 是否直接更换属性值
exclude: [/node_modules/, /web.vue/], // web不进行样式转换
landscape: false
}
}
}
这里的关键一步为exclude: [/node_modules/, /web.vue/]
,我们把web的样式给排除了,从而做到样式的条件配置。同时因为我们是使用媒体查询来进行样式的条件加载的,因此需要把mediaQuery
设为true
。
3. 配置vue.config.js
const postcssPxToViewport = require('postcss-px-to-viewport')
const postcssConfig = require('./postcss.config.js')
module.exports = {
css: {
loaderOptions: {
postcss: {
plugins: [
postcssPxToViewport(postcssConfig.plugins['postcss-px-to-viewport'])
]
}
}
}
}
4. 在组件同级目录创建一个文件夹,放置CSS文件
component
├── index.vue // 组件的template、script
└── styles
├── h5.vue // h5对应的样式
└── web.vue // web对应的样式
h5.vue:
<style lang="scss">
@media screen and (max-width:768px) {
.page {
display: flex;
min-height: 100vh;
text-align: center;
flex-direction: column;
.header {
color: #fff;
height: 244px;
background-color: #376ece;
.title {
margin-top: 36px;
font-size: 36px;
line-height: 36px;
font-weight: 500;
}
.sub-title {
margin-top: 20px;
font-size: 28px;
line-height: 28px;
font-weight: 400;
}
}
}
}
</style>
web.vue:
<style lang="scss">
@media screen and (min-width:769px) {
.page {
display: flex;
min-height: 100vh;
text-align: center;
flex-direction: column;
.header {
color: #fff;
height: 244px;
background-color: green;
.title {
margin-top: 36px;
font-size: 36px;
line-height: 36px;
font-weight: 500;
}
.sub-title {
margin-top: 20px;
font-size: 28px;
line-height: 28px;
font-weight: 400;
}
}
}
}
</style>
5. 在组件中引入这两个文件
<template>
<main class="page">
<header class="header">
<h1 class="title">{{ title }}</h1>
<h2 class="sub-title">{{ subTitle }}</h2>
</header>
</main>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
import './styles/h5.vue'
import './styles/web.vue'
export default defineComponent({
setup() {
const title = ref(window.innerWidth > 768 ? 'web' : 'h5')
const subTitle = ref('根据屏幕尺寸条件加载CSS样式')
window.onresize = () => {
title.value = window.innerWidth > 768 ? 'web' : 'h5'
}
return {
title,
subTitle
}
}
})
</script>
这样书写之后,实际上会在header中创建两个style
标签:
其中第一个为H5对应的样式,经过了postcss处理,第二个则为web样式,未经过任何处理。
其他方式
除此之外,如果我们的文件就是简单的css,不需要经过loader处理(sass、stylus、postcss等
),那么我们也可以使用以下方式来进行样式的条件加载:
在HTML中
<style href="styles_mobile.css" media="screen and (max-width:768px)" />
<style href="styles_pc.css" media="screen and (min-width:769px)" />
在CSS中
@import url("styles_mobile.css") screen and (max-width:768px);
@import url("styles_pc.css") screen and (min-width:769px);
在Vue文件中
<style>
@import url("styles_mobile.css") screen and (max-width:768px);
@import url("styles_pc.css") screen and (min-width:769px);
<style>
这样书写之后,经过loader处理,实际上会在header中创建两个style
标签(等同于在HTML中):