阅读 1707

nuxt.js开发移动端项目的实际项目经验

首先使用nuxt.js搭建脚手架以及api相关使用这里就不再做重复的描述,因为官网上的更详细。

一、构建页面自适应

实现原理是根据屏幕的宽度除以ui设计稿的宽度算出其比例再乘以你觉得算起来比较容易的倍数(例如:screenWidth / 750 * 10 ,那么再写style的时候实际宽度是750px就应该写成75rem),我习惯乘以10,具体代码如下,复制即可用。

(function (doc, win) {
    var docEl = doc.documentElement,
        resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
        recalc = function () {
            var clientWidth = docEl.clientWidth;
            if (!clientWidth) return;
            docEl.style.fontSize = 10 * (clientWidth / 750) + 'px';
        };
    if (!doc.addEventListener) return;
    win.addEventListener(resizeEvt, recalc, false);
    doc.addEventListener('DOMContentLoaded', function() {
        recalc();
        FastClick.attach(doc.body);//解决手机浏览器点击事件300ms延迟的bug
    }, false);
})(document, window);
复制代码

(// 这里在640的设备上1rem = 10px,在其他屏幕宽的时候会自动根据这个比例来动态调整)

二、手机端自带click 300ms延迟

300 毫秒延迟的主要原因是解决双击缩放(double tap to zoom)。双击缩放,顾名思义,即用手指在屏幕上快速点击两次,iOS 自带的 Safari 浏览器会将网页缩放至原始比例。 那么这和 300 毫秒延迟有什么联系呢? 假定这么一个场景。用户在 iOS Safari 里边点击了一个链接。由于用户可以进行双击缩放或者双击滚动的操作,当用户一次点击屏幕之后,浏览器并不能立刻判断用户是确实要打开这个链接,还是想要进行双击操作。因此,iOS Safari 就等待 300 毫秒,以判断用户是否再次点击了屏幕。 鉴于iPhone的成功,其他移动浏览器都复制了 iPhone Safari 浏览器的多数约定,包括双击缩放,几乎现在所有的移动端浏览器都有这个功能。

解决这个问题也有很多方法,但是我选择了使用faskclick.js( github.com/ftlabs/fast…)来解决 在项目nuxt.config.js文件中引入js文件

head: {
    title: '灵龙AI智能车贷',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'user-scalable=no'},
      // { name: 'viewport', content: 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0'},
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: './favicon.ico' },
      { rel: 'stylesheet', href: '/reset.css' }
    ],
    script: [
      { src: '/zoomSize.js' },
      { src: '/fastclick.js' },//fastclick在这里
    ],
  },
复制代码

文件引入完了肯定是需要实例化的,实例化 fastclick.js的地方我放在了上面构建页面自适应的JavaScript文件中,因为fastclick必须要在项目实例化之前引入

三、接口请求

这里我使用的是nuxt-axios(npm i @nuxtjs/axios),具体的封装如下

import Vue from 'vue'
export default function ({ $axios, redirect }) {
  // request interceptor
  // $axios.defaults.baseURL = '' // 测试api地址
  $axios.defaults.baseURL = 'https://carloans.appdld.com' // 正式api地址
  // $axios.interceptors.request.use(config => {
  //     let keys = config.method && config.method == 'post' ? 'data' : 'params'
  //     let addHeaderData = config[keys].addHeaderParam //addHeaderParam是额外需要传到header头里面的参数,在请求参数里面定义
  //     if(addHeaderData) {//header中的额外参数
  //       Object.assign(config.headers,addHeaderData)
  //     }
  //     if(config[keys].dataType && config[keys].dataType == 'formData') {//如果后端需要formData数据,就需要在请求参数里面添加dataType:'formData'
  //       config[keys] = config[keys].requestFormData
  //     }else {
  //       delete config[keys].addHeaderParam //去掉额外的header参数,避免传到请求参数里面
  //     }
  //     return config
  //   },
  //   error => {
  //     console.log('err' + error) // for debug
  //     return Promise.reject(error)
  //   }
  // )
  $axios.interceptors.request.use(config => {
    // 在发送请求之前做些什么
    // console.log(config)
    return config
  }, error => {
    // 对请求错误做些什么
    return Promise.reject(error)
  })
 

  // response interceptor
  $axios.interceptors.response.use(response => {
      return response.data 
    },
    error => {
      console.log('err' + error) // for debug
      Vue.prototype.$notice('服务器错误')
      return Promise.reject(error)
    }
  )
}
复制代码

这个文件需要放到plugins文件夹中,nuxt.config.js文件中配置如下

plugins: [
    '@/plugins/axios',
 ],
复制代码

具体调用方法:

this.$axios.post('url', params).then(res => {

})
复制代码

四、notice提示ui插件的封装

由于我的项目中只是需要使用noitce message,如果引入vant等ui框架,就感觉太不应该了,所以就自己手写了一个 具体实现是参照nuxt框架的插件封装方法,在plugins文件中新建notice.js,代码如下: //消息提示框

import Vue from 'vue'
Vue.prototype.$notice = (message) => {
    let bodyDom = document.getElementsByTagName("body")[0]
    let docHeight = window.screen.availHeight / 10
    let screenHeight = docHeight > 133.4 ? docHeight : 133.4
    let domParent = document.createElement('div')
    domParent.setAttribute('style', `width: 75rem;
        position: fixed;
        top: 0;
        left: 0;
        z-index: 9999;
        display: flex;
        justify-content: center;
        align-items: center;`
    );
    domParent.style.height = screenHeight + 'rem';
    let domChildren = document.createElement('span')
    domChildren.setAttribute('style', `display: block;
        width: auto;
        height: 8rem;
        padding: 0rem 3rem;
        background:rgba(0,0,0,0.5);
        line-height: 8rem;
        text-align: center;
        font-size: 2.8rem;
        color: #FFFFFF;
        border-radius:1.2rem;`
    );
    let nodetext = document.createTextNode(message)
    domChildren.appendChild(nodetext)
    domParent.appendChild(domChildren)
    bodyDom.appendChild(domParent)
    setTimeout(() => {
        bodyDom.removeChild(domParent)
    },2000)
}
复制代码

使用方法:

Vue.prototype.$notice('服务器错误')
复制代码

或者

this.$notice('服务器错误')
复制代码

当然插件的封装方法不止这一种,例如还有Vue.use,具体实现方式这里不做描述

五、动态渲染框架

其原理nuxt官网说的非常的详细

如果你觉得对你有用,不妨给我个小星星。 如果你有更好的建议请给我留言 此处不做口水战的战场

文章分类
前端
文章标签