移动端H5多页开发拍门砖经验

2024-02-26 12:40

本文主要是介绍移动端H5多页开发拍门砖经验,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

poster

两年前刚接触移动端开发,刚开始比较疑惑,每次遇到问题都是到社区里提问或者吸取前辈的经验分享,感谢热衷于分享的开发者为前端社区带来欣欣向上的生命力。本文结合先前写的文章和开发经验分享给大家,希望也能帮助刚步入移动端开发的新人解惑。以下会以其中一个以公积金页面开发项目作为例子,介绍移动端的一些常见问题和使用Vuejs作为lib进行多页开发的经验。

移动端自适应布局

在项目中移动端最常用的自适应布局方案就是flexbox结合rem。规范的分栏式使用flexbox,其他大部分不规则视图使用rem,对于rem最常用的方案就是淘宝开源的可伸缩布局方案。

根据设备设备像素比设置scale的值(scale = 1 / deviceRatio),这样可以保持视口device-width始终等于设备物理像素,接着根据屏幕大小动态计算根字体大小,具体是将屏幕划分为100等分,每份为a,1rem就等于10a。

标注

通常我们会拿到750宽的设计稿,这是基于iPhone6的物理分辨率。有的设计师也许会偷懒,设计图上面没有任何的标注,如果我们边开发边量尺寸,无疑效率是比较低的。要么让设计师标注上,要么自食其力。

如果设计师实在没有时间,推荐使用markman进行标注,免费版阉割了一些功能(比如无法保存本地)不过基本满足了我们的需求了。

后来我发现比markman更好的标注工具PxCook,该工具可以显示PSD设计图中的图层的样式代码,对于前端来说简直方便极了。

标注完成后开始写我们的样式,使用了淘宝的lib-flexible库之后,我们的根字体基准值就为750/100*10 = 75px。此时我们从图中若某个标注为100px,那么css中就应该设置为100/75 = 1.333333rem。所以为了提高开发效率,可以使用px转化为rem的插件。下面是sublimeText和Vscode的转换插件:

px转rem插件

  • sublimeText插件:rem-unit
    rem-unit

  • Vscode插件: cssrem
    pxtorem

使用rem的几点总结

  • 在所有的单位中,font-size推荐使用px,然后结合媒体查询进行重要节点的控制,这样可以满足突出或者弱化某些字体的需求,而非整体调整。
  • 众向的单位可以全部使用px,横向的使用rem,因为移动设备宽度有限,而高度可以无限向下滑动。但这也有特例,比如对于一些活动注册页面,需要在一屏幕内完全显示,没有下拉,这时候所有众向或者横向都应该使用rem作为单位。如图:

shili

左图的表单高度单位由于下边空距较大,使用px在不同屏幕显示更加;而右边的活动注册页由于不能出现滚动条,所有的众向高度、margin、padding都应该使用rem。

  • border、box-shadow、border-radius等一些效果应该使用px作为单位。

手机状态栏和浏览器导航栏的影响

之前发布的文章中,有个SF的前端小伙伴提出的问题:
文中作者有重点强调布局全部铺满,和下方与很多空隙的处理方案是不同的,在工作中我遇到这种情况,设计师的设计稿宽度为750×1334,但实际的展示高度并没有那么多,因为上方有导航栏还包括手机自己的状态栏展示,所以整体高度就达不到750,但是设计师设计稿是严格按照750进行设计的,这种情况下使用rem,严格按照设计师尺寸进行还原就会出现屏幕出现滚动条情况,请问针对这种情况您是怎么处理的?是从设计稿上规范,还是从开发上有相应的措施

依旧以我的分享界面为例:
展示高度不同通常发生在微信及浏览器端,因为前者没有地址栏和工具栏,这样显示高度通常会和设计师设计的视图吻合。那如果按照纯padding,margin即使全部使用rem,在浏览器端依旧会超出一屏高度,对于分享页面这种不是我们想要看到的。这时候就要做出取舍,我对主体区域采用绝对定位,这样上面间隙虽然小,不过仍能保持在一个屏幕高度显示。若采用margin padding在设置,必然已出现滚动条。当然这样的前提是依赖设计图的,通常设计师会为了空间感有保留一定的间隙,也不会将主要对象高度设的过高,否则太撑满也不好看,开发上如果设计图宽高没有在一定界限之内,超出也无法避免,不过我们这种分享界面通常是通过微信分享好友,通过浏览器打开的视图效果出现滚动条其实也不怎么影响不是么?
下面附上微信端和浏览器端的效果图:

微信端:微信端

浏览器端: 浏览器端

Vuejs作为lib开发移动端页面

为何不使用SPA模式

一般移动端使用vue是为了数据交互频繁而且快速开发的页面,为什么不使用单页SPA开发模式,原因大概几点。

  • 为了快速开发,快速上线
  • 项目其他成员不熟悉SPA,不熟悉webpack
  • 参与项目时项目已使用多页开发,短时间无法重构

抛开使用单页的架构,开发多页应用时,一个页面交互逻辑与一个Vue实例对应。

基于接口返回数据的属性注入

"基于接口返回数据的属性注入"是个人创建的话术,抛开此概念,先说一下表单数据的绑定方式。

表单的数据绑定

一个重要的点是有几份表单就分开几个表单对象进行数据绑定

以上图公积金查询为例,由于不同城市会有不同的查询要素,可能登陆方式只有一种,也可能有几种。比如上图有三种登陆方式,在使用vue布局时,有两种方案。

  • 1、 只建立一个表单用于数据绑定,点击按钮触发判断
  • 2、有几种登陆方式建立几个表单,用一个字段标识当前显示的表单

由于使用第三方的接口,一开始也没有先进行接口返回数据结构的查看,采用了第一种错误的方式,错误一是每种登陆方式下面的登陆要素的数量也不同,错误二是数据绑定在同一个表单data下,当用户在用户名登陆方式输入用户名密码后,切换到客户号登陆方式,就会出现数据错乱的情况。

解决完布局问题后,我们需要根据设计图定义一些状态,比如当前登陆方式的切换、同意授权状态的切换、按钮是否可以点击的状态、是否处于请求中的状态。当然还有一些app穿过来的数据,这里就忽略了。

 data: {tags: {arr: [''],activeIndex: 0},isAgreeProxy: true,isLoading: false}

接着审查一下接口返回的数据,推荐使用chrome插件postman,比如呼和浩特的登陆要素如下:

{"code": 2005,"data": [{"name": "login_type","label": "身份证号","fields": [{"name": "user_name","label": "身份证号","type": "text"},{"name": "user_pass","label": "密码","type": "password"}],"value": "1"},{"name": " login_type","label": "公积金账号","fields": [{"name": "user_name","label": "公积金账号","type": "text"},{"name": "user_pass","label": "密码","type": "password"}],"value": "0"}],"message": "登录要素请求成功"
}

可以看到呼和浩特有两种授权登陆方式,我们在data中定义了一个loginWays,初始为空数组,接着methods中定义一个请求接口的函数,里面就是基于返回数据的基础上为上面fields对象注入一个input字段用于绑定,这就是所谓的基于接口返回数据的属性注入。

methods: {queryloginWays: function(channel_type, channel_code) {var params = new URLSearchParams();params.append('channel_type', channel_type);params.append('channel_code', channel_code);axios.post(this.loginParamsProxy, params).then(function(res) {console.log(res);var code = res.code || res.data.code;var msg = res.message || res.data.message;var loginWays = res.data.data ? res.data.data : res.data;// 查询失败if (code != 2005) {alert(msg);return;}// 添加input字段用于v-model绑定loginWays.forEach(function(loginWay) {loginWay.fields.forEach(function(field) {field.input = '';})})this.loginWays = loginWays;this.tags.arr = loginWays.map(function(loginWay) {return loginWay.label;})}.bind(this))}
}

即使返回的数据有我们不需要的数据也没有关系,这样保证我们不会遗失进行下一步登陆所需要的数据。

这样多个表单绑定数据问题解决了,那么怎么进行页面间数据传递?如果是app传过来,那么通常使用URL拼接的方式,使用window.location.search获得queryString后再进行截取;如果通过页面套入javaWeb中,那么直接使用"${字段名}"就能获取,注意要js中获取java字段需要加双引号。

computed: {// 真实姓名realName: function() {return this.getQueryVariable('name') || ''},// 身份证identity: function() {return parseInt(this.getQueryVariable('identity')) || ''},/*If javaWebrealName: function() {return this.getQueryVariable('name') || ''},identity: function() {return parseInt(this.getQueryVariable('identity')) || ''}*/},methods: {getQueryVariable: function(variable) {var query = window.location.search.substring(1);var vars = query.split('&');for (var i = 0; i < vars.length; i++) {var pair = vars[i].split('=');if (decodeURIComponent(pair[0]) == variable) {return decodeURIComponent(pair[1]);}}console.log('Query variable %s not found', variable);}}

关于前端跨域调试

在进行接口请求时,我们的页面通常是在sublime的本地服务器或者vscode本地服务器预览,所以请求接口会遇到跨域的问题,如果使用Gulp进行打包,可以使用插件http-proxy-middleware,或者使用nginx。

使用Gulp

在项目构建的时候通常我们源代码会放在src文件夹下,然后使用gulp进行代码的压缩、合并、图片的优化(根据需要)等等,我们会使用gulp。

解决跨域的问题可以用gulp-connect结合http-proxy-middleware,此时我们在gulp-connect中的本地服务器进行预览调试。

gulpfile.js如下: 开发过程使用gulp server:dev命令,监听文件改动并使用livereload刷新,并且代理src目录;使用gulp命令进行打包;使用gulp server:dist代理dist生产目录。

var gulp = require('gulp');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var autoprefixer = require('gulp-autoprefixer');
var useref = require('gulp-useref');
var connect = require('gulp-connect');
var proxyMiddleware = require('http-proxy-middleware');// 开发跨域代理  将localhost:8088/api 映射到 https://api.xxxxx.com/
gulp.task('server:dev', ['listen'], function() {var middleware = proxyMiddleware(['/api'], {target: 'https://api.xxxxx.com/',changeOrigin: true,pathRewrite: {'^/api': '/'}});connect.server({root: env == 'dev' ? './src' : './dist',port: 8088,livereload: true,middleware: function(connect, opt) {return [middleware]}});
});// 打包后跨域代理
gulp.task('server:dist', ['listen'], function() {var middleware = proxyMiddleware(['/api'], {target: 'https://api.xxxxx.com/',changeOrigin: true,pathRewrite: {'^/api': '/'}});connect.server({root: './dist',port: 8088,livereload: true,middleware: function(connect, opt) {return [middleware]}});
});gulp.task('html', function() {gulp.src('src/*.html').pipe(useref()).pipe(gulp.dest('dist'));
});
gulp.task('css', function() {gulp.src('src/css/main.css').pipe(concat('main.css')).pipe(autoprefixer({browsers: ['last 2 versions'],cascade: false})).pipe(gulp.dest('dist/css/'));gulp.src('src/css/share.css').pipe(concat('share.css')).pipe(autoprefixer({browsers: ['last 2 versions'],cascade: false})).pipe(gulp.dest('dist/css/'));gulp.src('src/vendors/css/*.css').pipe(concat('vendors.min.css')).pipe(autoprefixer({browsers: ['last 2 versions'],cascade: false})).pipe(gulp.dest('dist/vendors/css'));return gulp
});
gulp.task('js', function() {return gulp.src('src/vendors/js/*.js').pipe(concat('vendors.min.js')).pipe(uglify()).pipe(gulp.dest('dist/vendors/js'));
});
gulp.task('img', function() {gulp.src('src/imgs/*').pipe(gulp.dest('dist/imgs'));
});
gulp.task('listen', function() {gulp.watch('./src/css/*.css', function() {gulp.src(['./src/css/*.css']).pipe(connect.reload());});gulp.watch('./src/js/*.js', function() {gulp.src(['./src/js/*.js']).pipe(connect.reload());});gulp.watch('./src/*.html', function() {gulp.src(['./src/*.html']).pipe(connect.reload());});
});
gulp.task('default', ['html', 'css', 'js', 'img']);

使用nginx

在nginx配置使用proxy_pass,需要注意一点:
如果在proxy_pass后面的url加/,表示绝对根路径;如果没有/,表示相对路径,把匹配的路径部分也给代理走。

server {listen 80;server_name  localhost;root   [Your project root];index  index.html index.htm default.html default.htm;location ^~/api { proxy_pass https://api.xxxxx.com/;} 
}

公众号网页的调试

如果你开发的H5基于微信jsSDK,你一定接触过微信授权域名,微信会将授权数据传给一个回调页面,而回调页面必须在你配置的域名下(含子域名)。比如我们获取用户的openid操作。而微信配置域名回去该域名根目录下检测一个xxx_verify_xxx.txt文件,确保该域名是属于你的。

所以要想在微信开发调试工具中获取openid,我们需要使用一种叫做内网穿透的工具。下面是自己比较常用的两个工具:

  • ngrok
  • 花生壳

ngrok

ngrok执行命令

ngrok -config ngrok.cfg start web

在ngrok.exe目录需要一个配置文件ngrok.cfg
以下是配置示例:

server_addr: "tunnel.cn:4443"
trust_host_root_certs: false
tunnels:web:subdomain: "xxx" proto:http: 8086https: 8086

启动后xxx.tunnel.cn:4443会指向你本地的8086端口,将xxx_verify_xxx.txt文件放到8086端口根目录即可配置授权域名成功。

花生壳

花生壳免费版对于个人开通仅需6元,然后每月会提供给你1G的流量,免费版不支持80端口,最多支持两个域名,需要下载桌面客户端。

添加域名映射很简单,免费版无法配置自定义域名,由花生壳自动生成。
花生壳
配置成功后启动客户端可查看当前的状态

PS:更多前端资讯、技术干货,请关注公众号「前端新视界」,后台回复 “1” 获取100本PDF前端电子书
回复 “2” 获取小编精选的Python编程电子书

前端新视界

这篇关于移动端H5多页开发拍门砖经验的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/748912

相关文章

基于Python开发电脑定时关机工具

《基于Python开发电脑定时关机工具》这篇文章主要为大家详细介绍了如何基于Python开发一个电脑定时关机工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 简介2. 运行效果3. 相关源码1. 简介这个程序就像一个“忠实的管家”,帮你按时关掉电脑,而且全程不需要你多做

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo

C#图表开发之Chart详解

《C#图表开发之Chart详解》C#中的Chart控件用于开发图表功能,具有Series和ChartArea两个重要属性,Series属性是SeriesCollection类型,包含多个Series对... 目录OverviChina编程ewSeries类总结OverviewC#中,开发图表功能的控件是Char

鸿蒙开发搭建flutter适配的开发环境

《鸿蒙开发搭建flutter适配的开发环境》文章详细介绍了在Windows系统上如何创建和运行鸿蒙Flutter项目,包括使用flutterdoctor检测环境、创建项目、编译HAP包以及在真机上运... 目录环境搭建创建运行项目打包项目总结环境搭建1.安装 DevEco Studio NEXT IDE

Python开发围棋游戏的实例代码(实现全部功能)

《Python开发围棋游戏的实例代码(实现全部功能)》围棋是一种古老而复杂的策略棋类游戏,起源于中国,已有超过2500年的历史,本文介绍了如何用Python开发一个简单的围棋游戏,实例代码涵盖了游戏的... 目录1. 围棋游戏概述1.1 游戏规则1.2 游戏设计思路2. 环境准备3. 创建棋盘3.1 棋盘类

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设