vue项目总结(一)

之前一直在做pc端的页面,对移动端的开发并没有过多的接触。借着这次的项目,也算正式入坑移动端了:)


移动端坑的地方在哪里呢?


一是要适配各种机型,ios还好一点,但是安卓就坑了,各式各样的尺寸,加上高清屏,适配一直是一件很头疼的问题。但是,问题总能找出一些解决方案,媒体查询,rem布局,vw/vh布局等等。单纯的媒体查询太麻烦,而vw/vh布局呢,兼容性不是很好,低版本的手机不支持。所以,这次的项目,适配的重担就交给了rem布局。而rem布局,又大致分为了两个版本,一个是网易版本的,一个是淘宝版本的。详情可以参考大神的这篇文章 —— 传送门

二是则是浏览器的问题了,这个也是避免不了的。因为每个产商搞出来的东西肯定是不可能一样的,这样的话,特性的支持上肯定有所差异。所以,只能尽量去满足不同浏览器的差异了。


开发前的一些准备


因为这次是使用vue开发,所以要先使用官方给的命令行工具vue-cli构建好开发的脚手架,这里就不赘述了。然后就将适配的js文件放入项目中(当然也可以使用npm去引入),在这里,我使用的是淘宝的适配方案,虽然说网易的更容易去计算,但我在这个项目中使用Sass/SCSS,所以不存在计算难的问题了。


使用淘宝的lib-flexible.js

1) 引入

// 在main.js中配置
// 需要根据flexible.js在实际项目的路径去配置(下面的是我项目的配置)

import './assets/scripts/flexible.js'

2) 代码如下

// 这个是flexible.js

(function (win, lib) {
  var doc = win.document;
  var docEl = doc.documentElement;
  var metaEl = doc.querySelector('meta[name="viewport"]');
  var flexibleEl = doc.querySelector('meta[name="flexible"]');
  var dpr = 0;
  var scale = 0;
  var tid;
  var flexible = lib.flexible || (lib.flexible = {});

  if (metaEl) {
    var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
    if (match) {
      scale = parseFloat(match[1]);
      dpr = parseInt(1 / scale);
    }
  } else if (flexibleEl) {
    var content = flexibleEl.getAttribute('content');
    if (content) {
      var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
      var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
      if (initialDpr) {
        dpr = parseFloat(initialDpr[1]);
        scale = parseFloat((1 / dpr).toFixed(2));
      }
      if (maximumDpr) {
        dpr = parseFloat(maximumDpr[1]);
        scale = parseFloat((1 / dpr).toFixed(2));
      }
    }
  }

  if (!dpr && !scale) {
    var isAndroid = win.navigator.appVersion.match(/android/gi);
    var isIPhone = win.navigator.appVersion.match(/iphone/gi);
    var devicePixelRatio = win.devicePixelRatio;
    if (isIPhone) {
      // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
      if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
        dpr = 3;
      } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)) {
        dpr = 2;
      } else {
        dpr = 1;
      }
    } else {
      // 其他设备下,仍旧使用1倍的方案
      dpr = 1;
    }
    scale = 1 / dpr;
  }

  docEl.setAttribute('data-dpr', dpr);
  if (!metaEl) {
    metaEl = doc.createElement('meta');
    metaEl.setAttribute('name', 'viewport');
    metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
    if (docEl.firstElementChild) {
      docEl.firstElementChild.appendChild(metaEl);
    } else {
      var wrap = doc.createElement('div');
      wrap.appendChild(metaEl);
      doc.write(wrap.innerHTML);
    }
  }

  function refreshRem() {
    var width = docEl.getBoundingClientRect().width;
    // 适配平板
    if (width / dpr > 540) {
      width = 540 * dpr;
    }
    var rem = width / 10;
    docEl.style.fontSize = rem + 'px';
    flexible.rem = win.rem = rem;
  }

  win.addEventListener('resize', function () {
    clearTimeout(tid);
    tid = setTimeout(refreshRem, 300);
  }, false);
  win.addEventListener('pageshow', function (e) {
    if (e.persisted) {
      clearTimeout(tid);
      tid = setTimeout(refreshRem, 300);
    }
  }, false);

  if (doc.readyState === 'complete') {
    doc.body.style.fontSize = 12 * dpr + 'px';
  } else {
    doc.addEventListener('DOMContentLoaded', function (e) {
      doc.body.style.fontSize = 12 * dpr + 'px';
    }, false);
  }


  refreshRem();

  flexible.dpr = win.dpr = dpr;
  flexible.refreshRem = refreshRem;
  flexible.rem2px = function (d) {
    var val = parseFloat(d) * this.rem;
    if (typeof d === 'string' && d.match(/rem$/)) {
      val += 'px';
    }
    return val;
  }
  flexible.px2rem = function (d) {
    var val = parseFloat(d) / this.rem;
    if (typeof d === 'string' && d.match(/px$/)) {
      val += 'rem';
    }
    return val;
  }

})(window, window['lib'] || (window['lib'] = {}));

lib-flexible虽然是淘宝开源的较为成熟的适配方案,但还是存在一定的问题。比如高清屏,1px边框等。这个方案只适配了iphone设备,安卓设备压根没适配。有兴趣的可以看看大神的这两篇文章(对这个方案有更深的了解) —— 淘宝弹性布局方案lib-flexible实践基于淘宝弹性布局方案lib-flexible的问题研究


移动端还有一个问题,那就是click事件300毫秒延迟。解决方案也很简单

1) 安装

 npm install fastclick --save

2) 引入项目

在main.js中配置

 import fastClick from 'fastclick'

 fastClick.attach(document.body)


vue中使用SCSS

在项目中,我们经常会使用到SCSS中的变量(可用于颜色,便于维护修改界面的整体颜色等等),Mixin, 还有就是函数,这些是比较常用的。这些东西一般在项目每个vue文件会使用到,比如说rem布局中使用的自定义函数 —— px2rem。然而每次使用前都要引用一次文件,那感觉很麻烦,所以就将全局中常用的SCSS代码放入到一个SCSS文件中,并注入到全局中。这样一来,就不用每次都引用这么麻烦了。

1) 首先你得安装Sass/SCSS的loader才可以在项目中使用SCSS

npm install sass-loader node-sass --save-dev

2) 然后得添加一个依赖

npm install sass-resources-loader --save-dev

3) 最后修改build/utils.js

scss: generateLoaders('sass').concat({
  loader: 'sass-resources-loader',
  options: {
    // 这里的'../src/assets/your.scss'
    // 换成实际项目中需要注入全局的文件路径
    resources: path.resolve(__dirname, '../src/assets/your.scss')
  }
})

这样三步完成后,就可以愉快的使用SCSS了。


vue使用stylus

stylus也是一种CSS预处理器,它极大地提高了编程的效率。无论是变量定义,嵌套选择器,mixins,函数,都很方便我们去编写css。

1) 首先你也得去安装stylus才可以在项目中使用

npm install stylus stylus-loader --save-dev

2) webpack中的配置是可以省略的,因为vue-cli生成的项目中,vue会自动检测 lang 去识别使用哪一种语法,会自动调用相对应的 loader 去解析处理。

// build/webpack.base.conf.js —— module —— rules
{
  test: '/\.styl$/',
  loader: 'style-loader!css-loader!stylus-loader'
}

3) 然后在单独的stylus文件或者vue组件中使用stylus语法即可


有时候有一些变量,mixins,函数等需要在全局中使用,这个时候就需要一些额外的配置了。

1) 首先在公共的stylus文件夹中创建一个全局的stylus文件 —— index.styl。然后在该文件中引入各个需要在全局中使用的 .styl 文件。
2) 在build/utils.jsgenerateLoaders方法下做如下修改

var stylusOptions = {
  import: [
    path.join(__dirname, "../src/common/stylus/index.styl"), // index.styl 为全局变量文件
  ],
  paths: [
    path.join(__dirname, "../src/common/"),
    path.join(__dirname, "../"),
  ],
}

return {
  css: generateLoaders(),
  postcss: generateLoaders(),
  less: generateLoaders('less'),
  sass: generateLoaders('sass', { indentedSyntax: true }),
  scss: generateLoaders('sass'),
  stylus: generateLoaders('stylus', stylusOptions),
  styl: generateLoaders('stylus', stylusOptions)
}

这样子就可以使用了


图标字体

一般来说,使用图标字体资源的时候(例如svg),不会说直接去引入,那样子太麻烦。而使用 iconfont ,不需要导入太多图片,节省了空间,使用起来也比较方便。

这是两个可以将 svg 图标转化为字体文件的网站 —— icomoon阿里巴巴矢量图标库


步骤

  • 首先将需要使用的 svg 上传,或者选择网站上提供的免费图标
  • 然后配置一些信息,不同网站有不同的配置方法,大同小异,然后将它们下载下来
  • 一般来说,在一个文件夹中会有4个以 .eot .svg .ttf .woff 结尾的文件;还有就是样式的 .css 文件。这就是我们项目中所要使用到的文件
  • 然后放入项目目录中,在main.js 中引入 之前那个.css 文件
// 一般来说,以vue项目为例,会将.eot .svg .ttf .woff文件放在 src/common/fonts 中,该 css 文件放在 src/common/styles 中
// common一般是代表着用来存放公共的一些文件
// 然后需要在这个 css 文件中修改一下引入字体文件的 url

// 参照下面这个,根据项目真实路径修改就可以就可以
src:  url('../fonts/vue-sell.eot?8o9vnq');
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值