vue-构建app项目

以下记录vue-cli 3构建app项目的步骤。

一、初始化配置,并运行启动app

1、安装nodeJS,git ,配置环境,Vue CLI 3.x 需要 Node.js 8.9 或更高版本 (推荐 8.11.0+)。

2、安装vue-cli ,命令:npm install -g @vue/cli

3、创建项目:vue create mapp-demo

推荐vue ui 使用图形化界面创建和管理项目

vue-构建app项目

 

 

 

4、选择安装插件和依赖,一般babel,eslint,css预处理器,fastclick ,选择vant作为前端组件库

注意:哪些是运行依赖,哪些是开发依赖

如下图:

vue-构建app项目

 

 

 

 

5、运行项目: 任务 -> serve -> 运行、启动app 

vue-构建app项目

 

 

 

vue-构建app项目

6、

(1)可安装vue devtools调试工具。

(2)vue-cli 3.x 构建的项目文件目录说明

vue-构建app项目

 

 

 

 

二、移动端初始化设置

(1)禁止移动端通过手指放大缩小页面

<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,er-scalable=no">

  页面位置: public/index.html  

 

(2)css reset

参考 https://meyerweb.com/eric/tools/css/reset/

/* http://meyerweb.com/eric/tools/css/reset/ 
   v2.0 | 20110126
   License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, 
figure, figcaption, footer, header, hgroup, 
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure, 
footer, header, hgroup, menu, nav, section {
    display: block;
}
body {
    line-height: 1;
}
ol, ul {
    list-style: none;
}
blockquote, q {
    quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
    content: ‘‘;
    content: none;
}
table {
    border-collapse: collapse;
    border-spacing: 0;
}

页面位置:新建文件放在  src/assets/reset.css

 

(3)解决部分手机屏幕1像素带来的页面样式兼容性问题

@charset "utf-8";
.border,
.border-top,
.border-right,
.border-bottom,
.border-left,
.border-topbottom,
.border-rightleft,
.border-topleft,
.border-rightbottom,
.border-topright,
.border-bottomleft {
    position: relative;
}
.border::before,
.border-top::before,
.border-right::before,
.border-bottom::before,
.border-left::before,
.border-topbottom::before,
.border-topbottom::after,
.border-rightleft::before,
.border-rightleft::after,
.border-topleft::before,
.border-topleft::after,
.border-rightbottom::before,
.border-rightbottom::after,
.border-topright::before,
.border-topright::after,
.border-bottomleft::before,
.border-bottomleft::after {
    content: "\0020";
    overflow: hidden;
    position: absolute;
}
/* border
 * 因,边框是由伪元素区域遮盖在父级
 * 故,子级若有交互,需要对子级设置
 * 定位 及 z轴
 */
.border::before {
    box-sizing: border-box;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    border: 1px solid #eaeaea;
    transform-origin: 0 0;
}
.border-top::before,
.border-bottom::before,
.border-topbottom::before,
.border-topbottom::after,
.border-topleft::before,
.border-rightbottom::after,
.border-topright::before,
.border-bottomleft::before {
    left: 0;
    width: 100%;
    height: 1px;
}
.border-right::before,
.border-left::before,
.border-rightleft::before,
.border-rightleft::after,
.border-topleft::after,
.border-rightbottom::before,
.border-topright::after,
.border-bottomleft::after {
    top: 0;
    width: 1px;
    height: 100%;
}
.border-top::before,
.border-topbottom::before,
.border-topleft::before,
.border-topright::before {
    border-top: 1px solid #eaeaea;
    transform-origin: 0 0;
}
.border-right::before,
.border-rightbottom::before,
.border-rightleft::before,
.border-topright::after {
    border-right: 1px solid #eaeaea;
    transform-origin: 100% 0;
}
.border-bottom::before,
.border-topbottom::after,
.border-rightbottom::after,
.border-bottomleft::before {
    border-bottom: 1px solid #eaeaea;
    transform-origin: 0 100%;
}
.border-left::before,
.border-topleft::after,
.border-rightleft::after,
.border-bottomleft::after {
    border-left: 1px solid #eaeaea;
    transform-origin: 0 0;
}
.border-top::before,
.border-topbottom::before,
.border-topleft::before,
.border-topright::before {
    top: 0;
}
.border-right::before,
.border-rightleft::after,
.border-rightbottom::before,
.border-topright::after {
    right: 0;
}
.border-bottom::before,
.border-topbottom::after,
.border-rightbottom::after,
.border-bottomleft::after {
    bottom: 0;
}
.border-left::before,
.border-rightleft::before,
.border-topleft::after,
.border-bottomleft::before {
    left: 0;
}
@media (max--moz-device-pixel-ratio: 1.49), (-webkit-max-device-pixel-ratio: 1.49), (max-device-pixel-ratio: 1.49), (max-resolution: 143dpi), (max-resolution: 1.49dppx) {
    /* 默认值,无需重置 */
}
@media (min--moz-device-pixel-ratio: 1.5) and (max--moz-device-pixel-ratio: 2.49), (-webkit-min-device-pixel-ratio: 1.5) and (-webkit-max-device-pixel-ratio: 2.49), (min-device-pixel-ratio: 1.5) and (max-device-pixel-ratio: 2.49), (min-resolution: 144dpi) and (max-resolution: 239dpi), (min-resolution: 1.5dppx) and (max-resolution: 2.49dppx) {
    .border::before {
        width: 200%;
        height: 200%;
        transform: scale(.5);
    }
    .border-top::before,
    .border-bottom::before,
    .border-topbottom::before,
    .border-topbottom::after,
    .border-topleft::before,
    .border-rightbottom::after,
    .border-topright::before,
    .border-bottomleft::before {
        transform: scaleY(.5);
    }
    .border-right::before,
    .border-left::before,
    .border-rightleft::before,
    .border-rightleft::after,
    .border-topleft::after,
    .border-rightbottom::before,
    .border-topright::after,
    .border-bottomleft::after {
        transform: scaleX(.5);
    }
}
@media (min--moz-device-pixel-ratio: 2.5), (-webkit-min-device-pixel-ratio: 2.5), (min-device-pixel-ratio: 2.5), (min-resolution: 240dpi), (min-resolution: 2.5dppx) {
    .border::before {
        width: 300%;
        height: 300%;
        transform: scale(.33333);
    }
    .border-top::before,
    .border-bottom::before,
    .border-topbottom::before,
    .border-topbottom::after,
    .border-topleft::before,
    .border-rightbottom::after,
    .border-topright::before,
    .border-bottomleft::before {
        transform: scaleY(.33333);
    }
    .border-right::before,
    .border-left::before,
    .border-rightleft::before,
    .border-rightleft::after,
    .border-topleft::after,
    .border-rightbottom::before,
    .border-topright::after,
    .border-bottomleft::after {
        transform: scaleX(.33333);
    }
}

页面位置:新建文件放在  src/assets/border1px.css

 

(4)为避免浏览器兼容问题引起的点击问题(部分浏览器对点击事件有300毫秒的延迟响应机制)

解决办法:

1)先安装依赖 Fastclick (界面操作方式->搜索依赖Fastclick并安装  ; 或者 命令方式安装  )

注意:是Fastclick运行依赖

2)页面位置:src/main.js文件中,加入以下代码

import Fastclick from ‘fastclick‘
 
//问题:当使用FastClick 时,input框在ios上点击输入调取手机自带输入键盘不灵敏,有时候甚至点不出来。而安卓上完全没问题。这个原因是因为FastClick的点击穿透。
//FastClick的ios点击穿透解决方案
Fastclick.prototype.focus = function (targetElement) {
  let length;
  if (targetElement.setSelectionRange && targetElement.type.indexOf(‘date‘) !== 0 && targetElement.type !== ‘time‘ && targetElement.type !== ‘month‘) {
      length = targetElement.value.length;
      targetElement.focus();
      targetElement.setSelectionRange(length, length);
  } else {
      targetElement.focus();
  }
};

Fastclick.attach(document.body);

//way2
/*if ("addEventListener" in document && "ontouchstart" in window) {
  FastClick.prototype.focus = function(targetElement) {
    targetElement.focus();
  };
  document.addEventListener(
    "DOMContentLoaded",
    function() {
      FastClick.attach(document.body);
    },
    false
  );
}*/

 

(5)vant相关引入

1)自动按需引入组件 (或者界面搜索依赖 babel-plugin-import并安装)

babel-plugin-import 是一款 babel 插件,它会在编译过程中将 import 的写法自动转换为按需引入的方式

# 安装插件
npm i babel-plugin-import -D
// 在.babelrc 中添加配置
// 注意:webpack 1 无需设置 libraryDirectory
{
  "plugins": [
    ["import", {
      "libraryName": "vant",
      "libraryDirectory": "es",
      "style": true
    }]
  ]
}

// 对于使用 babel7 的用户,可以在 babel.config.js 中配置
module.exports = {
  plugins: [
    [‘import‘, {
      libraryName: ‘vant‘,
      libraryDirectory: ‘es‘,
      style: true
    }, ‘vant‘]
  ]
};
// 接着你可以在代码中直接引入 Vant 组件
// 插件会自动将代码转化为方式二中的按需引入形式
import { Button } from ‘vant‘;

2)iPhone X 等机型底部存在底部指示条,指示条的操作区域与页面底部存在重合,容易导致用户误操作,因此我们需要针对这些机型进行底部安全区适配。Vant 中部分组件提供了safe-area-inset-bottom属性,设置该属性后,即可在对应的机型上开启适配,如下示例:

页面位置:public/index.html

 <!-- 在 head 标签中添加 meta 标签,并设置 viewport-fit=cover 值 -->
    <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,er-scalable=no, viewport-fit=cover">
    <!-- 开启 safe-area-inset-bottom 属性 -->
    <van-number-keyboard safe-area-inset-bottom />
 

3)rem适配  (注意:如果只是用px,不需配置此步骤)

Vant 中的样式默认使用px作为单位,如果需要使用rem单位,推荐使用以下两个工具:

然后,需要进行PostCSS配置

下面提供了一份基本的 postcss 配置,可以在此配置的基础上根据项目需求进行修改

module.exports = {
  plugins: {
    ‘autoprefixer‘: {
      browsers: [‘Android >= 4.0‘, ‘iOS >= 7‘]
    },
    ‘postcss-pxtorem‘: {
      rootValue: 37.5,
      propList: [‘*‘]
    }
  }
}

注意:在配置 postcss-loader 时,应避免 ignore node_modules 目录,这会导致 Vant 的样式无法被编译

4)同一台机器运行多个vue项目,修改vue.config.js中端口号的设置

module.exports = {

......其他设置项
lintOnSave: true, // 在保存时校验格式
productionSourceMap: false, // 生产环境是否生成 SourceMap
devServer: {
open: true, // 启动服务后是否打开浏览器
host: ‘0.0.0.0‘,
port: 3000, // 服务端口
https: false,
hotOnly: false,
proxy: null, // 设置代理
before: app => {}
}
};

 

 

 

 

============写在最后====================================================================================================

【注意事项】

在界面模式下安装依赖的时候,要选择运行依赖还是开发依赖。

问题:原先vant和fastclick都是运行依赖安装好了,后来安装babel-plugin-import需选择开发依赖,但是会改变了vant和fastclick为开发依赖。后来卸载重装了好几次,,觉得界面选择的时候,存在bug吧。

如果还是界面模式下,建议先安装好开发依赖babel-plugin-import,然后选择运行依赖切换按钮下的vant和fastclick,点击安装前也再点击 运行依赖的切换按钮,以保证安装的是运行依赖。

vue-构建app项目

 

vue-构建app项目

上一篇:阿里架构师分享的Android面试,这些是拿到大厂offer的重点,你必须要看!


下一篇:Java异常层次结构示意图