mpvue样式绑定
在使用mpvue的时候,很多同学应该会感到很不方便,比如没法用vue-router,没法在js中控制节点的style属性样式,只能通过样官方推荐的样式绑定的办法控制样式,最难受的是不能用slot,不过总的来说,感觉总比小程序原生开发要方便一点,下面扒一扒mpvue中样式绑定需要注意的几个点。
先上图:
瞄一眼代码:
<template>
<div class="style">
<button @click="changeTag">change</button>
<div :class="cls1">class绑定(按照vue原来的方式绑定对象是不行的)</div>
<div :class="{red:tag,blue:!tag}">class绑定(mpvue官方推荐绑定方式,在template中绑定)</div>
<div :class="cls2">class绑定(通过全局函数转换,也就是官方推荐的转换为字符串)</div>
<div :style="styles1">style绑定(按照vue原来的方式绑定对象是不行的)</div>
<div :style="{backgroundColor:tag?'brown':'dodgerblue'}">style绑定(mpvue官方推荐绑定方式,在template中绑定)</div>
<div :style="styles2">class绑定(通过全局函数转换,也就是官方推荐的转换为字符串)</div>
</div>
</template>
<script>
import {classes, styles} from "../../common/css";
export default {
name: "style",
data() {
return {
tag: true,
}
},
methods: {
changeTag() {
this.tag = !this.tag
},
},
computed: {
cls1() {
return {
red: this.tag,
blue: !this.tag
}
},
cls2() {
return classes({
red: this.tag,
blue: !this.tag
})
},
styles1() {
return {
backgroundColor: this.tag ? 'brown' : 'dodgerblue'
}
},
styles2() {
return styles({
backgroundColor: this.tag ? 'brown' : 'dodgerblue'
})
},
}
}
</script>
<style scoped lang="scss">
.style {
& > div {
margin-bottom: 12px;
padding: 12px;
color: white;
letter-spacing: 2px;
background-color: gray;
transition: all 0.4s;
}
.red {
background-color: brown;
}
.blue {
background-color: dodgerblue;
}
}
</style>
看到代码的话,可以观察出来,通过自定义的函数将classObject或者styleObject转换为字符串,在一定程度上来说可以降低之前用vue开发的时候样式绑定的差异。
下面是这两个方法的代码:
/*
* power by weishengjian
* datetime 2018/7/14 10:26
*/
/*
* 将对象转变为class字符串
*/
export function classes(obj) {
let classesStr = '';
for (let className in obj) {
if (obj.hasOwnProperty(className) && !!obj[className]) classesStr += className;
}
return classesStr;
}
/*
* 将对象转变为style字符串,对象属性的camel命名会转换为中划线命名
*/
export function styles(obj) {
let stylesStr = '';
for (let styleName in obj) {
if (obj.hasOwnProperty(styleName)) stylesStr += `${styleName.replace(/([A-Z])/g, "-$1").toLowerCase()}:${px2rpx(obj[styleName])};`;
}
return stylesStr;
}
(async () => {
let systemInfo = await getSystemInfo()
windowWidth = systemInfo.windowWidth
}).call(this)
export function px2rpx(str) {
if (/rpx/.test(str)) return str
else if (/px/.test(str)) {
let val = str.substring(0, str.indexOf('px'))
/*在代码中硬编码时,所有px单位都是以375px为整个屏幕宽度作为参照,所以这里需要转换一下*/
val = val * windowWidth / 375
return `${(val - 0) * 750 / windowWidth}rpx`
} else return str
}
下面说一下在开发的时候,编写样式时需要注意的一些点:
- mpvue的template工程自带有px2rpx-loader编译器,px2rpx-loader会自动将得到的css中的px数值转换为 rpx数组(px=2rpx),所以为了统一规范,在scss文件以及在vue的style节点中,编写的样式统一使用px作为单位, 需要注意的是,750rpx为屏幕宽度,所以375px为屏幕宽度;
- 如果是针对横向的,大多数情况下请使用px单位,因为px会自动转为rpx,是根据屏幕变化的,在各种尺寸的设备上效果不会差太多,px的精度要比vw高一点,所以最好使用px,如果是针对纵向的,请使用vh单位, 100vh为屏幕高度,比如有的页面,顶部为tabbar,内容为scroll-view,而scroll-view必须指定一个高度,这时就可以设置顶部tabbar 高度为7vh,scroll-view为93vh,或者说是其他数值;
- 如果宽高是计算属性,请使用styles函数,styles函数会自动将px数值转换为rpx(px=2rpx)
```
<div :style="computedStyles"></div>
computed:{
computedStyles(){
return styles({
width:'100px'
})
},
}
```
- 还有一种情况,如果是在节点上使用style样式的,最好使用rpx单位,否者如果使用px单位,这种情况不会做任何处理 在不同分辨率设备上的显示的效果是不一样的:
<div style="margin-bottom: 24rpx"></div>