美文网首页前端开发那些事前端&优化
移动端项目开发总结(持续更新中...)

移动端项目开发总结(持续更新中...)

作者: 苏日俪格 | 来源:发表于2019-06-17 19:06 被阅读1次

    ☞☞ 个人主页欢迎访问 ☜☜

    最近在开发一个移动端项目微信公众号,前端框架我用当然是Vue,期间遇到了很多问题,在这里记录一下,希望也可以帮助到入坑vue项目的伙伴们,先说说我用到的技术栈

    vue:前端主体框架vue 2.0
    vue-router:vue全家桶之一 vue的路由
    axios:基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中配合vue-axios完成vue中和后台对接url发送请求
    vuex:vue全家桶之一 vue的状态管理器
    Webpack:webpack 3.0在nodejs下用于对项目的模块化管理方案,或者是自动化打包工具,将我们项目中的所有文件经过loader之后解析为浏览器识别的js模块
    vux:UI框架
    Less:less语言 打包后自动编译为css
    ESNext:es写法 完美支持vue 2.0
    Rem:整个项目采用rem布局来兼容各个尺寸的手机
    Jquery:jquery库
    Flex:flex布局更方便快捷
    vue-quill-editor:基于quill插件开发的一款支持vue的富文本编辑器
    vue-scroller:滚动条 上拉加载
    vue-cropper:截图工具
    mint-ui:IndexList首字母索引列表

    为了赶项目进度这里直接安装的vue-cli脚手架,不会搭建vue项目的可以看我的两外两个文章:
    Vue 2.x + Webpack 4.x的那些事---萌新必备
    Vue-cli+Element+Less开发
    接下来把在项目开发的过程中遇到的几个坑和几个vue开发小技巧分享给大家:

    一、 rem布局

    所谓rem布局就是一种弹性布局--等比缩放,就是开发之前,先考虑好移动端的适配问题,因为移动端会出现各种尺寸,不能尺寸大小都一样

    //假设一个比例,然后根据这个比例和我们的UI设计图计算出我们想要的适配方案
    
    // 首先在css全局里面写入:
    html{
        font-size: 20px;
    }
    // js全局写入:
    var rem = 20;   // 设 全局的html的font-size默认是20px
    ;(function(){
        // 320: 设备大小 原比例1:1 宽度320px
        // 假设1px = (20/320)rem  即1rem = 20px
        // 实际根据UI设计图 如果设计图大小宽度为640  那么640/320=2 所以设计图是2倍图
        // 综上所述 2倍图应该是20*2=40px 即实际1rem = 40px
        // 所以在设计图量的尺寸(像素)/40就是实际要在页面写入的rem  exp: 测量设计图中的某一div宽度为80px 经过计算80/40=2 那么写入样式就应该是width: 2rem;
        rem = 20/320*document.documentElement.clientWidth;  // 20/320 = 实际字体大小/实际设备宽度
        document.documentElement.style.fontSize = rem+'px';
        window.onresize = function(){
            rem = 20/320*document.documentElement.clientWidth;
            document.documentElement.style.fontSize = rem+'px';
        };
    })();
    

    二、 代理

    在和后台做交互数据的过程中,避免不了出现不同端口或者不同域名,这个时候我们就要做代理,首先vue提倡的交互工具是axios这里就不多说了,至于为什么技术栈里会涉及到vue-axios,是为了更好地适配vue而做的

    // 首先在全局引入:
    import axios from 'axios';
    import VueAxios from 'vue-axios';
    Vue.use(VueAxios,axios);
    

    在config文件夹下有一个index.js,该文件就是webpack的配置,里面有一个proxyTable对象,将下面的代码放进去:

          '/api': {    //将映射为/api
                target: 'http://192.168.0.242:8080/',  // 后台的接口域名
                secure: false,  // 如果是https接口,需要配置这个参数
                changeOrigin: true,  //是否跨域
                pathRewrite: {  // 如果接口本身没有/api需要通过pathRewrite来重写地址
                    '^/api': ''
                }              
            }
    

    在vue中这样交互:

            // 在代码里通过axios和后台进行交互:
            var url = '/api/wechatRegister/sendCodeToMoile.htm'  // 原地址为: http://192.168.0.242:8080/wechatRegister/sendCodeToMoile.htm
            var paramsObj = {
                mobile: this.phoneNumber
            }
            this.axios.get(url, {
                params: paramsObj
            }).then((res) => {
                // coding...
            }).catch((response) => {
                console.log(response)
            })
    

    这样就可以完成代理进行交互了,但是在你之后打包项目到生产环境的时候你会发现并无法访问;这里有几个坑需要填一下:

    三、 webpack配置问题(打包之后可能会出现的问题)

    之前项目遇到过的一些问题:
    配置vue+webpack踩过的坑
    Vue中使用锚点定位跳转失效
    vue中使用监听器(watch)需要注意的问题
    vue项目样式中的scoped属性
    vue+webpack 绑定src找不到图片报404

    以下是本次项目中遇到的一些问题:

    (1)路径问题
    • 如果项目中采用了反向代理Nginx的话,那么config/index.js配置中的build下的assetsPublicPath一定要用.//代表域名的根目录,./代表当前路径)
    • 如果打包之后背景图片读取不到,就在build/utils.js下添加一句代码publicPath: '../../',像这样:
    return ExtractTextPlugin.extract({
            use: loaders,
            fallback: 'vue-style-loader',
            publicPath: '../../'
          })
    
    (2) 代理的交互接口请求不到

    发现所有请求都失效报错了,在network下查看地址都错了,这是因为开发环境和生产环境不一样,地址需要根据环境变化的,所以我的解决方案是定义一个全局变量挂载在vue的实例上,该全局变量通过识别生产或是开发模式来给webpack的代理一个值,再将该变量写入每一个接口中:

    • plugins/global.js 自定义的一个全局js文件:
    //项目域名地址
    const url = 'http://192.168.0.22:8083';
    
    let ROOT;
    //由于封装的axios请求中,会将ROOT打包进去,为了方便之后不再更改,判断了当前环境,而生成的不同的ROOT
    if (process.env.NODE_ENV == 'development') {
        //开发环境下的代理地址,解决本地跨域跨域,配置在config目录下的index.js dev.proxyTable中
        ROOT = "/api"
    } else {
        //生产环境下的地址
        ROOT = url;
    }
    
    exports.PROXYROOT = url; //代理指向地址
    exports.ROOT = ROOT;
    
    
    • config/index.js webpack配置文件:
    const config = require('../src/plugins/global');
    
    proxyTable: {
        [config.ROOT]: {
            target: config.PROXYROOT,
            secure: false,
            changeOrigin: true,
            pathRewrite: {
                ['^'+config.ROOT]: ''
            }
        }
    }
    
    • main.js 入口文件:
    const variable = require('@/plugins/global');
    Vue.prototype.api_config = variable.PROXYROOT;
    
    • vue交互代码:
            var url = this.api_config + '/wechatRegister/sendCodeToMoile.htm'
            var paramsObj = {
                mobile: this.phoneNumber
            }
            this.axios.get(url, {
                params: paramsObj
            }).then((res) => {
                // coding...
            }).catch((response) => {
                console.log(response)
            })
    
    (3)项目中的icon处理

    打包之后的一些小icon图标vue都会以base64打包掉,而不会打包在assets下以图片形式展示的

    (4)慎用eslint规范

    如果没有那么了解eslint编码规范的话,就把build下的webpack.base.conf.js中的这块代码注释掉,像这样:

    const createLintingRule = () => ({
      // test: /\.(js|vue)$/,
      // loader: 'eslint-loader',
      // enforce: 'pre',
      // include: [resolve('src'), resolve('test')],
      // options: {
      //   formatter: require('eslint-friendly-formatter'),
      //   emitWarning: !config.dev.showEslintErrorsInOverlay
      // }
    })
    

    用了这个的话,一些编码不规范,vue就会报错

    (5)npm包管理

    在项目中安装一些npm依赖包的时候,会被分成两组对象dependenciesdevDependencies

    • dependencies是生产环境需要的包,通过npm install -S命令进行安装
    • devDependencies是开发环境需要的包,通过npm install -D命令进行安装,生产环境就不需要了

    所以在我们代码里面使用的一些功能性插件和UI组件一定要安装在dependencies中,否则在生产环境功能就会失效

    (6)jquery或$ is not defined

    如果想在vue中引入jquery,那么它的正确使用方式是这样的:

    • 安装jquery:
    npm i jquery -S
    
    • 在webpack里面配置一下 build/webpack.base.conf.js:
    // 在文件最顶端如果没引入webpack的话引入一下
    const webpack = require("webpack")
    
      plugins: [
        new webpack.ProvidePlugin({
          jQuery: "jquery",
          $: "jquery"
        })
      ],
    

    然后无需引入,在vue代码中直接使用即可 exp: $('#app')

    (7)vux的webpack配置(这里特别注意不是vuex是vux UI框架)

    使用了vux这个组件的朋友可以看一下,安装引入之后,官方也说了,还需要在webpack配置一下,前面的步骤官方都写的很明白,只是最后一步配置问题有很多伙伴不会,这里我也遇到了坑,所以记录了一下:
    在build/webpack.base.conf.js下:

    // 引入vux的loader
    const vuxLoader = require('vux-loader')
    
    module.exports = vuxLoader.merge(webpackConfig, {
      plugins: [
        'vux-ui'
      ]
    })
    

    四、 小技巧

    (1)双击事件实现方式

    双击事件可以通过短时间内的两个单击事件来实现,就是给单击事件加一个定时器,写一个计算点击的次数,根据点击的次数来达到双击的效果:

            this.count ++;     // 初始值设为0
            let timer = setTimeout(() => {
                if (this.count == 2) {
                    console.log('双击');
                }
                this.count = 0;
                clearTimeout(timer);
            }, 300);
    
    (2)touchstart和click事件冲突

    这两个事件如果同时使用的时候,可能会引发冲突,即touchstart好使,click失效,这个问题来自于touchstart下阻止了默认事件,导致click失效,需要去掉touchstart身上的取消默认事件方法或属性

    (3)微信公众号更改文章标题

    在配置全局路由的时候,加一个meta对象,在meta对象里面写一个title,该title就是我们微信公众号文章上的title,在配置一个全局路由守卫,将路由中的title赋值给DOM的title:

    import Vue from 'vue';
    import Router from 'vue-router';
    
    // 登录
    const Login = r => require.ensure([], () => r(require('@/components/login/Login.vue')), 'Login');
    // 注册
    const Register = r => require.ensure([], () => r(require('@/components/register/Register.vue')), 'Register');
    
    Vue.use(Router);
    
    const router =  new Router({
        routes: [
            {
                path: '/',
                redirect: '/login'
            }, {
                path: '/login',
                name: 'Login',
                component: Login,
                meta: {
                    title: '用户登录'
                }
            }, {
                path: '/register',
                name: 'Register',
                component: Register,
                meta: {
                    title: '用户注册'
                }
            }
        ]
    });
    
    // 全局路由守卫
    router.beforeEach((to, from, next) => {
        document.title = to.meta.title;
        next();
    });
    
    export default router;
    
    (4)微信自定义分享
    • 安装依赖包
    npm install weixin-js-sdk
    
    • 引入微信插件
    import wx from 'weixin-js-sdk';
    
    • 全局微信分享配置
      我在全局引入了该方法,并且封装在了vue下:
    Vue.prototype.$wxConfig = function(appId, timestamp, nonceStr, signature) {
        // 微信分享功能的配置项  全局引入
        wx.config({
            debug: false,
            appId: appId, // 和获取Ticke的必须一样------必填,公众号的唯一标识
            timestamp: timestamp, // 必填,生成签名的时间戳
            nonceStr: nonceStr, // 必填,生成签名的随机串
            signature: signature, // 必填,签名
            
            // 需要分享的列表项:分享给朋友/QQ好友, 分享到朋友圈/QQ空间
            jsApiList: [
                'onMenuShareAppMessage',
                'onMenuShareTimeline',
                'onMenuShareQQ',
                'onMenuShareQZone',
                'updateAppMessageShareData',
                'updateTimelineShareData'
            ]
        });
    }
    

    在app.vue中使用:
    通过axios请求拿到了这四个属性值,然后调用传参:

    this.$wxConfig(this.appId, this.timestamp, this.nonceStr, this.signature);
    

    再封装一个可定义的分享插件:

    Vue.prototype.$wechat = function(title, link, imgUrl, desc) {
        // 微信分享功能分享之后的信息
    
        // 处理验证失败的信息
        wx.error(function (res) {
            console.log('验证失败返回的信息:', res)
        });
            
        // 处理验证成功的信息
        wx.ready(function () {
            var shareData = {
                title: title,   // 分享标题
                desc: desc, // 分享描述 这里请特别注意是要去除html
                link: link, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致window.location.href.split('#')[0]
                imgUrl: imgUrl,  // 分享图标
                success: function (res) {
                    // 用户确认分享后执行的回调函数
                    console.log('用户确认分享后执行的回调函数:', res)
                },
                cancel: function (res) {
                    // 用户取消分享后执行的回调函数
                    console.log('取消分享到朋友圈返回的信息为:', res)
                }
            };
            if(wx.onMenuShareAppMessage){ //微信文档中提到这两个接口即将弃用,故判断
                wx.onMenuShareAppMessage(shareData);    //1.0 分享到朋友
                wx.onMenuShareTimeline(shareData);  //1.0 分享到朋友圈
                wx.onMenuShareQQ(shareData);  //1.0 分享到QQ
                wx.onMenuShareQZone(shareData);  //1.0 分享到QQ空间
            }else{
                wx.updateAppMessageShareData(shareData);    //1.4 分享给朋友/QQ好友
                wx.updateTimelineShareData(shareData);  //1.4 分享到朋友圈/QQ空间
            }
        })
    }
    

    然后再每个页面初始化的时候调用上面的这个方法:

    created () {
        this.$wechat('公众号文章标题', 'http://www.baidu.com/', '图片', '公众号文章信息')
    }
    

    五、 兼容性问题

    由于Android和IOS的系统以及浏览器内核不同等,许多东西无法适配兼容,这里提供一个方案,可以判断两者将其分开来写:

    • 封装好一个判断设备的插件
    Vue.prototype.$is_android = function() {
        // 判断当前访问的设备是安卓还是IOS
        var userAgent = navigator.userAgent;
        var isAndroid = userAgent.indexOf('Android') > -1 || userAgent.indexOf('Linux') > -1;   // Android设备
        var isIOS = !!userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); // IOS设备
        if (isAndroid) {
          return true;
        }
        if (isIOS) {
           return false;
        }
    }
    
    • To use
    let isAndroid = this.$is_android;
    if (isAndroid) {
        // Android设备访问
        // coding...
    } else {
        // IOS设备访问
        // coding...
    }
    

    虽然chrome浏览器自带模拟机模拟移动端,但是毕竟是模拟机,内核什么的都是不同的,所以真实效果还是要在真机测试的,其中好多新的css3或h5的写法在IOS下不兼容,测试出以下bug:

    (1)css3背景

    Android写法(IOS下失效):

    background: url('../images/icon/icon-right.png') center  no-repeat / 100%;
    

    IOS下需改成:

    background: url('../images/icon/icon-right.png') center  no-repeat;
    
    background-size: 100%;
    
    (2)flex布局

    使用flex布局的时候需要注意一下
    justify-content: space-evenly;在IOS下失效,要么使用space-around替代,要么换其他方式

    (3)fixed属性在IOS软键盘弹出后失效

    fixed属性在IOS软键盘弹出后失效

    六、 项目前后的准备

    在开发项目前需要了解一下需求以及需要哪些插件,提前找好,当然UI组件之类的可以提前找个差不多,但是插件的话找到了可能最后也会因为一些原因被淘汰掉,这里我先说一下如何选择一款适合自己项目的UI;

    vue的UI库非常多,但是要找准适合自己项目的:

    • Cube UI:滴滴的基于 Vue.js 实现的精致移动端组件库。 stars:6k
    • Muse-UI:基于 Vue2.0 开发的组件库。 stars:7k
    • Element:饿了么前端开发的基于 Vue 2.0 的桌面端组件库。 stars:38k
    • Mint UI:饿了么前端开发的基于 Vue 2.0 的移动端组件库。 stars:14k
    • vue-element-admin:是一个后台前端解决方案,它基于 vueelement-ui实现。 stars:35k
    • uni-app:是一个使用 Vue.js 开发跨平台应用的前端框架。 stars:8k
    • SUI Mobile:由阿里巴巴国际UED前端出品的移动端UI库,是一套基于 Framework7 开发的UI库,并且能兼容到 iOS 6.0+ 和 Android 4.0+,非常适合开发跨平台Web App。 stars:6k
    • WeUI:是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信内网页和微信小程序量身设计,令用户的使用感知更加统一。 stars:22k
    • MUI:最接近原生APP体验的高性能前端框架。 stars:11k

    以上就是我所知道的所有vue的UI库,以及他们是干什么的详细介绍也展现给了大家,希望有帮助。

    如果您想自己写更多特效或者好看的字体库,那么这里有两个推荐:

    • Animate.css:一个CSS动画的跨浏览器库。 stars:60k
    • Awesome-vue:一套绝佳的图标字体库和CSS框架。 stars:46k

    项目中有富文本编辑器和截图的需求,因此找了几种插件:

    富文本编辑器:

    • Vue-Quill-Editor:基于 Quill、适用于 Vue 的富文本编辑器,这款可以用在移动端,是比较好用的一个。 stars:4k
    • wangEditor:基于javascript和css开发的 Web富文本编辑器,只适用在PC端,移动端会出现很多问题。 stars:7.7k
    • Vue2Editor:用于使用Vue.js和Quill.js构建的富文本编辑,这款没用过,个人感觉既然适配了vue,就应该没啥大问题。 stars:1.5k

    期间还用过两款,不过让我pass了,bug漏洞百出,问题很多;在使用前两个编辑器的时候不会的可以问我,会的一定帮助大家

    截图工具:

    • vue-cropper:该插件特别灵活使用特别简单,还支持vue。

    在开发过程中有很多问题需要总结,会逐渐完善代码,如果有什么问题的小伙伴们可以在这里给我留言哈,对大家有帮助的内容可以提供下,一起学习共同进步

    如果喜欢本文的话单击爱心加关注谢谢O(∩_∩)O~

    欢迎访问我的GitHub,喜欢的可以star,项目随意fork,支持转载但要下标注

    相关文章

      网友评论

        本文标题:移动端项目开发总结(持续更新中...)

        本文链接:https://www.haomeiwen.com/subject/qzwofctx.html