项目初始化 vant组件库 ESLint REM适配 axios封装

871 阅读13分钟

技术介绍

  • vuejs: 核心vue

  • vuex: 状态管理插件

  • vue-router: 路由插件

  • axios: ajax请求

  • json-bigint: 最大安全数值处理

  • socket.io-client: 即时通讯库

  • vant: 移动组件库

  • amfe-flexible: rem适配

  • vue-lazyload: 图片懒加载

  • 打包App:DCLOUD 打包

一. 项目创建

步骤

创建项目

vue create 项目名

选用自定义方式去创建项目

? Please pick a preset: (Use arrow keys)
  wzr ([Vue 2] less, babel, router, eslint)
  wz ([Vue 2] less, babel, router, vuex, eslint)
  Default ([Vue 2] babel, eslint)
  Default (Vue 3) ([Vue 3] babel, eslint)
> Manually select features

手动选择特性

? Check the features needed for your project:
 (*) Choose Vue version
 (*) Babel
 ( ) TypeScript
 ( ) Progressive Web App (PWA) Support
 (*) Router
>(*) Vuex
 (*) CSS Pre-processors
 (*) Linter / Formatter
 ( ) Unit Testing
 ( ) E2E Testing

版本

? Choose a version of Vue.js that you want to start the project with (Use arrow keys)
> 2.x
  3.x

路由是否使用history模式?

? Use history mode for router? (Requires proper server setup forindex 
fallback in production) (Y/n) n

css 预处理器

? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are 
  supported by default): (Use arrow keys)
  Sass/SCSS (with dart-sass)
  Sass/SCSS (with node-sass)
> Less
  Stylus

代码风格

? Pick a linter / formatter config:
  ESLint with error prevention only
  ESLint + Airbnb config
> ESLint + Standard config
  ESLint + Prettier

检查节点

? Pick additional lint features:
 (*) Lint on save
>(*) Lint and fix on commit

存储插件配置位置

? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
> In dedicated config files
  In package.json

是否要保存前面的设置作为预设方案

? Save this as a preset for future projects? (y/N) n

如果以后不需要的预设名字方案了, 可以找到C:\Users\用户名 下的.vuerc 这个文件删除

创建成功

🎉  Successfully created project vuex_day3.
👉  Get started with the following commands:

 $ cd vuex_day3 (进入项目)
 $ npm run serve (启动项目)

二. 创建远程仓库

登陆gitee,建立与本地项目同名空仓库

  • 与本地项目同名。这样方便简化推送命令。

  • 空仓库。就是远程仓库中先不要有任何的文件, 方便直接向上推。

创建之后,会看到如下页面效果

image-20201127101839269.png 第一步仓库建立完成之后,接下来进行连接并首次推送,这一步主要是运行两句git命令:

  • 添加远端仓库地址到本地仓库

    git remote add origin 远程仓库地址

  • 推送到远程仓库

    git push -u origin master

如果后续有代码变化,需要提交到远程仓库,则需要两个步骤:

# 正常本地提交
git add .
git commit -m '说明'

# 推到远程仓库
git push
  • 完成第一次推送(git push -u origin master)后,接下来只需要写git push 即可

常见的错误

  • 问题1 : 无法推送到gitee。(观察错误提示)

    可能原因:密码,用户名不对 (如果git push 失败,你一定要认真查看出错)

    解决方案:删除本地凭证,重新输入用户名,密码。

image-20200521103847742.png

删除之后,再次git push ,就会弹出框,让你重新写用户名密码。

  • 问题2 : gitee git remote add origin 报错

    报错示例图:

git-remote-add-错误.png 解决方案:

1. 先删除
git remote remove origin

2. 再重新添加
git remote add origin XXXXXXX

  • 问题3 : 项目创建完成之后,git log没有提交记录,会导致git push 失败。

    原因可能是:git 没有安装~

    解决办法:安装git

工作目录

├── node_modules      # 安装的包
├── public	          # 静态资源
│   ├── favicon.ico
│   └── index.html
└── src
    ├── api	          # 请求接口封装模块
    ├── assets	      # 资源目录
    ├── components	  # 组件目录
    ├── router	      # 路由模块
    ├── store	        # Vuex容器模块
    ├── styles        # 样式目录
    ├── utils         # 工具模块目录
    ├── views         # 视图组件目录
        └──home        # 首页模块
        |	    ├── home.vue
        ├─video       # 视频模块
        |	    ├── video.vue
        ├─question    # 问答模块
        |	    ├── question.vue
        ├─search      # 搜索模块
        |	    ├── search.vue
        ├─user        # 用户模块
        |     ├── user.vue
        └─Layout.vue  # 公用布局组件
    ├── App.vue	      # 根组件
    └── main.js	      # 入口文件
├── .browserslistrc   # 浏览器的约定
├── .editorconfig     # 对本项目要用到编辑器的约定
├── .eslintrc.js      # eslint 配置
├── .gitignore        # git的忽略设置,哪些文件不需要git托管
├── babel.config.js	  # babel配置文件
├── package-lock.json	# npm相关文件
├── package.json	    # npm相关文件
└── README.md	        # 项目说明文件

三. 自定义改动

默认生成的目录结构不满足我们的开发需求,所以这里需要做一些自定义改动。主要是两个工作:

  • 删除初始化的默认文件
  • 新增调整我们需要的目录结构

删除

  1. 清空src/views/App.vue中的内容。

==注意eslint要求每个文件最后一行都要留下空行==

  1. 删除默认生成的文件:
  • components/HelloWorld.vue
  • views/Home.vue
  • views/About.vue

新增

在 src 目录下中补充创建以下目录:

  • /api:存储请求函数模块
  • /styles: 样式文件模块
  • /utils: 工具函数模块

四. Vant组件库

vue.js移动端组件库介绍

基于 Vue.js移动端组件库有很多,在官方的 awesome 中也推荐了一些:

- mint UI : 饿了么 (element-ui的移动端版)

- vant:有赞公司

- cube-ui : 滴滴公司

- NutUI: JD公司

在我们的项目中使用的是有赞开发的 Vant (码云上的地址)。

1. 安装

npm i vant # 完整安装的格式是: npm install vant --save

注意:是生产依赖(项目发布上线了还是需要vant的),而不是开发依赖(只是在开发项目时使用,而上线了就不需要npm i xxx -D/--save-dev

2. 引入 Vant 组件库

在vue项目中有两种方式使用vant组件库:

完整引入

好处:使用方便(不需要每次使用组件都import )

缺点:打包体积大

按需引入

好处:打包体积小

缺点:相对于全部引入要稍微麻烦一些:每次使用都要import组件

结论: 在开发项目时直接使用完整引入方式,在项目打包时再去做调整

具体代码:

在src/main.js 中,以vue插件的方式完整引入vant组件

import Vue from 'vue'
import Vant from 'vant' // 组件库
import 'vant/lib/index.css' // 样式

Vue.use(Vant) // 引入

3. 使用

在app.vue中(其他任意组件也行), 测试使用

<van-button type="default">默认按钮</van-button>
<van-button type="primary">主要按钮</van-button>
<van-button type="info">信息按钮</van-button>
<van-button type="warning">警告按钮</van-button>
<van-button type="danger">危险按钮</van-button>

van-button就是vant组件库中提供的按钮组件

效果如下

image-20210603235531109.png

五. ESLint-基本介绍

ESLint 是一个代码检查工具,用来检查你的代码是否符合指定的规范(例如: = 的前后必须有一个空格)

  • 规范
    • 行业推荐的规范; 在创建项目时,我们使用的是 JavaScript ==Standard== Style 代码风格的规则
    • 自定义的规范。你和你的团队可以自行约定一套规范
  • 使用ESLint的好处在于:多人协作时代码风格统一

eslint是法官,Standard 是法律

vue-cli工具在创建项目时提供选项,我们前面在创建项目时选中了它,所以它在本项目中是直接生效的

JavaScript Standard Style 规范说明

规范大全: github.com/standard/st…

如果找不到的规则 再看看这里: www.verydoc.net/eslint/0000…

改正错误的四种方式

有四种方法来修正错误:

  • 手动修正: 人肉修改
  • 命令修正:npm run lint
  • 修改规则:让代码符合修改之后的规则,当然也就不报错了
  • 插件修正: 配合vscode 中的eslint插件

1. 手动修正

根据错误提示来一项一项手动修正。

如果你不认识命令行中的语法报错是什么意思,你可以根据错误规则名字(func-call-spacing, space-in-parens,.....)去 ESLint 规则列表网站中查找其具体含义。

2. 命令修正

vuecli创建项目时 提供了自动修复功能(有些复杂的错误还是要手动来改正),具体做法是运行:

npm run lint

3. 修改规则 ( ESLint-自定义规则 )

在项目根目录下面,有一个.eslintrc.js文件,它是对eslint进行配置的,其中有一个属性是专门用来设置自定义代码规则的:rules

module.exports = {
  root: true, // 当前项目使用这个配置文件, 不会往父级目录找.eslintrc.js文件
  env: { // 指定eslint启动环境(vuecli底层是node支持), browser: true也可以在浏览器设置
    node: true
  },
  extends: [ // 扩展配置
    'plugin:vue/essential', // vue里必须的规则
    '@vue/standard' // 使eslint继承@vue/cli脚手架里的 - standard标准
  ],
  parserOptions: { // 对新语法使用eslint
    parser: 'babel-eslint' // 使用babel-eslint 来解析新语法ES6
  },
  // 这里可以进行自定义规则配置
  // key:规则代号
  // value:具体的限定方式
  //   "off" or 0 - 关闭规则
  //   "warn" or 1 - 将规则视为一个警告(不会影响退出码),只警告,不会退出程序
  //   "error" or 2 - 将规则视为一个错误 (退出码为1),报错并退出程序
  // 自定义规则 - 其实上面集成后有很多内置的规则, 这里可以进行规则的一些修改
  rules: {
     // 上线环境用打印就报警告, 开发环境关闭此规则
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
     // debugger可以终止代码执行
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    // 不允许有连续多行空行(关闭规则)
    'no-multiple-empty-lines': 'off' 
  }
}

rules是一个对象,以键值对的格式来约定规则:

  • 键名是规则名(可在报错信息和eslint官网查看)
  • 值是这条规则的具体说明, 最常见的有off,warn,error。

4. 插件修正

用vscode打开项目时,将脚手架工程作为vscode根目录, 因为eslint要使用配置文件.eslintrc

五个步骤:

image-20210602235429627.png

补充内容:

{
  "eslint.enable": true,
  "eslint.run": "onType",
  "eslint.options": {
      "extensions": [
          ".js",
          ".vue",
          ".jsx",
          ".tsx"
      ]
  },
  "editor.codeActionsOnSave": {
      "source.fixAll.eslint": true
  }
}

更多的规则: www.cnblogs.com/jiaoshou/p/…

可能遇到的问题

1. ctrl+s保存不自动格式化

打开一个代码文件, 右下角有个ESLint, 如果是图示这样, 点击一下然后弹出来的对话框选择AnyWhere 在任意处生效(启动vscode中的eslint)

变成v就代表启动着

2. 自动缩进

  • 把Beautify插件卸载 - eslint也能美化代码

image-20210128154636196.png

  • ==可能还有JS/CSS Format插件/其他美化插件==

    不想卸载可以禁用

  • 如果你的vscode中用其它扩展 启用 自动格式化功能,则有可能与eslint的规则冲突!

    关闭vscode中的自动格式化 image-20200704091610961-1622645347578.png

  • 如果上面不行, 就修改vscode的配置

    文件>设置里, 搜索这个, 把下面的勾去掉

image-20210128194808213.png

3. 保存, 单引变双引

vetur插件和eslint冲突, 修改eslint插件配置, 把这里代码覆盖进去

{
    "eslint.run": "onType",
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    },
    "vetur.validation.template": false, // 把 vetur 扩展的 template 格式化去掉
	"editor.formatOnSave": false, // 去掉 vscode 自带的自动保存 ,vscode 默认也是 false的,如果要用 eslint 格式化,默认的格式化就不能开启
    "eslint.enable": true, // eslint 格式化的配置
    "eslint.autoFixOnSave": true, // eslint保存时候自动解决语法错误
    "eslint.options": { // eslint选项-格式化js和vue文件
        "extensions": [
            ".js",
            ".vue"
        ]
    },
    "eslint.validate": [
        "javascript",
        {
            "language": "vue",
            "autoFix": true,
        },
        "html",
        "vue"
    ],
}

六. 用REM解决多屏适配

使用REM适配技术

因为这个项目是移动端项目(用户是通过手机来访问的),所以,它需要去适配不同的手机屏幕

Vant 中的样式默认使用px作为单位,如果需要使用rem单位,推荐使用以下两个工具一起工作,来达到目标。官网地址]()

  1. 把所有px单位改成rem , 用postcss-pxtorem 来实现,它是一款 postcss 插件,用于将px转化为 rem。

  2. 根据不同的手机屏幕的宽度,来动态设置rem的参考值:html标签上的font-size的大小。用lib-flexible 来实现,用于设置 rem 基准值 。

  • 它对应的包名不是这个名字,而是amfe-flexible。
  • 它需要是生产依赖

1. 安装包

区别 :

# 后处理器 开发阶段使用
# -D: 表示开发依赖, 项目上线之后就不需这个包了(只需要在开发阶段把px->rem就行了)
# 作用:把px单位自动转成rem单位
npm i postcss-pxtorem@5.1.1 -D

# 修改rem基准值的js插件   需要在打包后需要使用
# 作用: 根据设置屏幕的宽度去调整rem的值(html标签上font-size的大小)
#      它的默认计算方式是屏幕宽度的1/10,默认值是37.5
npm i amfe-flexible

2. 设置postcss

创建postcss.config.js文件

module.exports = {
  plugins: {
    'postcss-pxtorem': {
      // 能够把所有元素的px单位转成Rem
      // rootValue: 转换px的基准值。
      // 例如一个元素宽是75px,则换成rem之后就是2rem。
      rootValue: 37.5,
      propList: ['*']
    }
  }
}

这一步完成之后,通过npm run serve 重启一下项目,它会把原来样式中的px单位自动转成rem单位

3. 引入flexible

在入口文件src/main.js导入 amfe-flexible

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

// 引入Vant所有的组件
import Vant from 'vant'
// 用它的样式
import 'vant/lib/index.css'

// 它会根据的手机尺寸来调整rem的基准值:html标签上的font-size。
import 'amfe-flexible'

七. axios-封装工具 axios 请求

为了调用ajax方便,这里我们先对 axios进行一次封装,把它封装成一个独立的模块,在需要的时候直接加载使用

1. 安装 axios

把axios安装到项目中

npm i axios

2. 二次封装

创建 src/utils/request.js 文件

// 对axios进行二次封装
//    axios本身是一个独立的库,是对ajax的封装。为了方便在项目中使用,我们对它再次封装
// (1) 接口基地址
// (2) 请求,响应拦截器

import axios from 'axios'

const instance1 = axios.create({
  // 后端服务器1
  baseURL: '' // 本项目线上的接口地址
})

const instance2 = axios.create({
  // 后端服务器2
  baseURL: ''
  // timeout: 1000,
  // headers: {'X-Custom-Header': 'foobar'}
})

export { instance1, instance2 }

// 默认导出intance1
export default instance1

baseURL是关键字,不能写错

理解多个基地址

image-20200107182039345.png

3. 测试

<template>
  <div id="app">
    <van-button type="primary" @click="hTestAxios2">测试axios的效果-async</van-button>
    <router-view/>
  </div>
</template>
<script>
import { instance2 } from '@/utils/request.js'
// import request from '@/utils/request.js'
export default {
  methods: {
    hTestAxios1 () {
      instance2({
        method: 'GET',
        url: 'v1_0/user/channels'
      }).then(res => {
        console.log(res)
      }).catch(err => {
        console.log(err)
      })
    }
  }
}
</script>

可以在控制台中看到类似如下:

image-20200107182640395.png

axios-复习async-await

1. 内容

async hTestAxios2 () {
  try {
    const res = await instance2({
      method: 'GET',
      url: 'v1_0/user/channels'
    })
    console.log(res)
  } catch (err) {
    console.log(err)
  }
}

2. try-catch

如果try中的代码发生了错误,就会到catch中。

这有一个小误区,可能是ajax操作没有错,而是后续的操作出错了,而我们会把错误误导到ajax上。

async hTestAxios2 () {
      try {
        const res = await instance2({
          method: 'GET',
          url: 'v1_0/user/channels'
        })
        console.log(res.data.data.adc.length) // 这句有错误
      } catch (err) {
        console.log(err)
      }
    },

八. axios-封装业务请求模块

1. 分析现有代码的问题

不友好的代码

try {
  await ajax({
  	method: 'GET',
  	url: '/v1_0/user/channels'
	})
}

上面的代码中对于ajax请求的做法比较直观:点击按钮就发出请求,请求写出url地址,方法,参数。但是它这样做是有一些问题的:

  • 不够语义化(只知道是是发请求,而不知道具体是做什么 )
  • 不方便代码复用。如果在另一个模块中也需要获取频道信息功能的话,就需要再写一次了。
  • 不方便统一修改url地址。如果要修改url地址,还需要找到这个组件内部才能定位去修改。

解决思路

提前将某个业务相关的操作都封装为一个模块

2. 对业务代码进一步封装

2.1 建立模块

创建 api/channel.js 并写入

// 用来封装所有与用户操作相关的业务
// 1.登录,退出,修改密码,修改头像.....
import ajax from '../utils/request'
/**
 * 用户登录
 * @param {*} mobile 手机号
 * @param {*} code 密码
 */
export const getChannels = () => {
  return ajax({
    url: '/v1_0/user/channels',
    method: 'GET'
  })
}

2.2 使用模块

在具体的页面中加载调用,两个步骤:

( 1 ) 导入上面封装api

( 2 ) 调用

// 1. 导入上面封装api
import { getChannels } from '@/api/channel.js'


async hTestAxios2 () {
  try {
    // 2. 调用
    const res = await getChannels()
    console.log(res)
  } catch (err) {
    console.log(err)
  }

之后项目中所有的涉及接口的请求就都不要直接在组件中直接写了,而是:

  • 先写成模块中的方法。在src/api/xxxx模块

  • 再从模块中取出方法来在组件中使用。

3. 可能的问题

要记得写return,不写return就无法获取返回结果

export const getChannels = () => {
  // request() 这个函数的返回值是一个promise
  return request({
    url: 'v1_0/user/channels',
    method: 'GET'
  })
}

小结

image-20210604123644925.png