Touch Vision是一套开箱即用的移动端开发模版。本模版除了解决了最核心的适配问题以外,还提供了其他的移动端常见问题的解决方案、安全通信以及常用的组件等功能。
git clone https://github.com/wuyax/touch-vision.git
cd touch-vision
npm install
npm run serve
npm run build
npm run build:dev
NOTE:在该版本和生产环境版本最重要的不同是,该版本保留调试信息console
。
npm run build:analyze
在vue.config.js
中可以配置 CDN,可以在生产环境使用 --cdn
来启用 CDN,如果不需要使用 CDN 可以注释掉相关配置信息或者忽略即可。
npm run build --cdn
移动端适配是本模版的基础功能,也是核心功能。本模版摒弃了传统的rem
适配方案,采用了vw
适配方案。
目前设计师出的视觉设计稿,一般都是使用750px
宽度的,那么100vw = 750px
,即1vw = 7.5px
。那么我们可以根据设计图上的px
值直接转换成对应的vw
值。手动计算非常繁琐,因此引入了postcss-px-to-viewport
插件。正确配置该插件以后实现px
在编译以后转换为vw
。也就是说,在实际开发过程中,开发者不需要进行任何的计算,直接在代码中写px
,大大节省了开发时的计算时间。
插件的配置文件在.postcssrc.js
中,它的基本配置如下:
'postcss-px-to-viewport': {
viewportWidth: 750, // (Number) The width of the viewport.
viewportHeight: 1334, // (Number) The height of the viewport.
unitPrecision: 3, // (Number) The decimal numbers to allow the REM units to grow to.
viewportUnit: 'vw', // (String) Expected units.
selectorBlackList: ['.ignore', '.hairlines'], // (Array) The selectors to ignore and leave as px.
minPixelValue: 1, // (Number) Set the minimum pixel value to replace.
mediaQuery: false // (Boolean) Allow px to be converted in media queries.
}
开发这可以根据自己的设计稿和需求修改对应的参数。 源代码:
.vw-test {
border: 0.5px solid black;
border-bottom-width: 4px;
font-size: 14px;
line-height: 20px;
position: relative;
}
编译后:
.vw-test {
border: 0.5px solid #000;
border-bottom-width: 0.533vw;
font-size: 1.867vw;
line-height: 2.667vw;
position: relative;
}
在不需要把px
转换为vw
的时候,在对应的元素(html)
中添加配置中指定的类名.ignore
或.hairlines
(.hairlines
一般用于设置border-width:0.5px
的元素中),该类的px
不会被转换为vw
:
html
<div class="box ignore"></div>
源代码:
.box {
width: 180px;
height: 300px;
}
.ignore {
margin: 10px;
background-color: red;
}
.hairlines {
border-bottom: 0.5px solid red;
}
编译后:
.box {
width: 24vw;
height: 40vw;
}
.ignore {
margin: 10px; /*.box元素中带有.ignore类名,在这个类名写的px不会被转换*/
background-color: red;
}
.hairlines {
border-bottom: 0.5px solid red;
}
该模版已经集成了优秀的第三方 UI 框架Vant
,并且做好了适配,开发者不需要再为第三方 UI 框架的适配问题发愁了。
关于 Vant 样式重置的问题:
Vant
的viewport
是基于375px
设计的,因此我们在postcss
的配置中做了特殊的配置。- 基于第一条,因此请不要在项目中新建名字中带有
vant
的文件和文件夹。 - 所有公共的
Vant
重置样式都应该写在css/vui-reset.scss
文件中。 - 重置的样式请按照
viewport = 750px
计算。
开发者可以配置exclude: ['node_modules']
来排除第三方组件从px
转换为vw
。更复杂的规则可以移步.postcssrc.js
。
在移动端开发中不可避免的会遇到一些基本的概念,如:视窗 viewport、物理像素(physical pixel)、设备独立像素(density-independent pixel)、CSS 像素、屏幕密度、设备像素比(device pixel ratio),我就不赘述了,感兴趣的可以访问这个页面(amfe/article#17)了解跟详细的信息。
正是因为有以上这些概念,因此,设计稿上的1px
是无法直接实现的。本模版也集成了一像素问题的解决方案。
postcss-write-svg
插件主要用来处理移动端1px
的解决方案。该插件主要使用的是border-image
和background
来做1px
的相关处理。
源代码:
@svg 1px-border {
height: 2px;
@rect {
fill: var(--color, black);
width: 100%;
height: 50%;
}
}
.example {
border: 1px solid transparent;
// 并不是所有的设备都支持
border-image: svg(1px-border param(--color #00b1ff)) 2 2 stretch;
}
编译后:
.example {
border: 1px solid transparent;
border-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' height='2px'%3E%3Crect fill='%2300b1ff' width='100%25' height='50%25'/%3E%3C/svg%3E")
2 2 stretch;
}
- 设置
height: 1px
,根据媒体查询结合transform
缩放为相应尺寸。
div {
height: 1px;
background: #000;
transform: scaleY(0.5);
transform-origin: 0 0;
overflow: hidden;
}
- 用
::after
和::befor
,设置border-bottom:1px solid #000;
,然后在缩放-webkit-transform: scaleY(0.5);
可以实现两根边线的需求
div:after {
display: inherit;
content: '';
width: 100%;
border-bottom: 1px solid #000;
transform: scaleY(0.5);
}
- 用
::after
设置border:1px solid #000; width:200%; height:200%;
,然后再缩放scaleY(0.5)
优点可以实现圆角,缺点是按钮添加active
比较麻烦。
.div::after {
content: '';
width: 200%;
height: 200%;
position: absolute;
top: 0;
left: 0;
border: 1px solid #bfbfbf;
border-radius: 4px;
transform: scale(0.5, 0.5);
transform-origin: top left;
}
- 媒体查询 +
transfrom
对方案 1 的优化
/* 2倍屏 */
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
.border-bottom::after {
transform: scaleY(0.5);
}
}
/* 3倍屏 */
@media only screen and (-webkit-min-device-pixel-ratio: 3) {
.border-bottom::after {
transform: scaleY(0.33);
}
}
每种方案都有自身的缺陷和优点,开发者根据自身的需求和不同的开发情况合理选用。
开发环不可避免的会遇到跨域问题,关于跨域问题的本质原因网上有很多资料,不再赘述。vue-cli
提供的代理就很好的帮助我们解决了这个问题。在vue.config.js
添加如下的配置:
devServer: {
proxy: {
'/api': {
target: 'http://192.168.1.200:8080/', // 接口地址,按需修改
changeOrigin: true, //是否跨域
pathRewrite: {
'^/api': '/api' //需要rewrite重写,
},
cookiePathRewrite: {
//重写cookie路径 按需修改
'/api': '/'
}
}
}
}
为了规范团队代码,避免在团队写作中出现迷之 BUG,该项目模版提供了一套最佳实践的最小化的模版。开发者可以将该模版添加到 VScode 的代码片段中。开发者可以在src/components/base/vue-template.vue
中看到如下代码片段。
<template>
<div class="class-name">
<!-- your code goes here -->
</div>
</template>
<script>
// https://cn.vuejs.org/v2/style-guide/#组件-实例的选项的顺序-推荐
export default {
name: 'YourComponentName',
components: {},
model: {},
props: {},
data() {
return {}
},
computed: {},
watch: {},
created() {},
mounted() {},
beforeDestroy() {},
methods: {}
}
< /script>
<style lang="scss" scoped>
</style>
Accessibility 支持良好的移动端组件既能减少开发者hack
的时间,也能提升用户体验。该模版持续添加有些有用的小组件。
市面上流通的select
组件中,绑定值没办法实现placeholder
的效果,该组件提供了一种思路和解决方案,开发者掌握核心代码以后可以自行修改,以符合项目需求。
行高根据用户输入内容自动调整,而且解决了需要使用输入法 (如中文、日文、韩文等) 的语言,在输入法组合文字过程中就得到更新的问题。
以上两个组件你都可以在components/base/
目录下找到。
按需引入至少并不是万能的,但是它至少能在一定程度上解决package
太大的问题,优化加载速度、节省带宽。
项目抛弃常见的lodash
而使用符合ES
模块化标准的lodash-es
。
// bad
import _ from 'lodash'
// worse
import * as _ from 'lodash-es'
// good
import { xor } from 'lodash-es'
例如代码中只用到了柱状图,提示框和标题组件,因此在引入的时候也只需要引入这些模块,可以有效的将打包后的体积从400
多 KB 减小到170
多 KB。
// 引入 ECharts 主模块
const echarts = require('echarts/lib/echarts')
// 引入图表
require('echarts/lib/chart/bar')
// 引入组件
require('echarts/lib/component/tooltip')
require('echarts/lib/component/title')
Echarts 的所图表和有组件都可以在这里找到。
在处理好常见的前端问题的基础上,该模版还集成了代码加密和代码混淆的功能。开发者可以根据项目实际需求开启或者关闭给功能,也可以对制定文件进行加密和混淆。
更多配置可以访问vue.config.js
。
注意
在和后台服务交互过程中不可避免的会传输数据,为了解决敏感数据在网络中明文传输的问题,该模版提供了加密传输的解决方案。
该方案采用了AES
加密的方案,对敏感数据加密后再传输给后台服务。
模版提供了两个基本的加密和解密方法,开发者务必根据项目需要和后台服务接口进行二次封装。
import CryptoJS from 'crypto-js'
// 加密
function encrypt(word, key) {
if (!word || !key) {
return null
}
let parsedkey = CryptoJS.enc.Utf8.parse(key)
let srcs = CryptoJS.enc.Utf8.parse(word)
let encrypted = CryptoJS.AES.encrypt(srcs, parsedkey, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
})
let d = encrypted.toString()
return d
}
// 解密
function decrypt(word, key) {
if (!word || !key) {
return null
}
let parsedkey = CryptoJS.enc.Utf8.parse(key)
let decrypt = CryptoJS.AES.decrypt(word, parsedkey, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7
})
let d = CryptoJS.enc.Utf8.stringify(decrypt).toString()
return d
}
模版集成了es-lint
和prettier
方便开发者规范代码格式和团队协作,保障代码质量。
- 解决移动端双击缩放问题
- 解决 iOS 中键盘收起后页面底部有留白的问题
<input type='text' v-rpage />
- 为 iSO 中应用切换到后台后倒计时暂停的问题提供解决方案
- 组件示例编写
- 文档发布部署