幻之纪元·网游先锋

前端【VUE】13

一、基本使用

1、介绍

Vant 是一个轻量、可靠的移动端组件库,于 2017 年开源。

目前 Vant 官方提供了 Vue 2 版本、Vue 3 版本和微信小程序版本,并由社区团队维护 React 版本和支付宝小程序版本。

2、安装

1 # Vue 3 项目,安装最新版 Vant:

2 npm i vant -S

3

4 # Vue 2 项目,安装 Vant 2:

5 npm i vant@latest-v2 -S

3、项目引入

创建vue项目,然后在main.js中引入vant组件

方式一. 自动按需引入组件 (推荐)

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

1 # 安装插件

2 npm i babel-plugin-import -D

配置

1 // 在.babelrc 中添加配置

2 // 注意:webpack 1 无需设置 libraryDirectory

3 {

4 "plugins": [

5 ["import", {

6 "libraryName": "vant",

7 "libraryDirectory": "es",

8 "style": true

9 }]

10 ]

11 }

12

13 // 对于使用 babel7 的用户,可以在 babel.config.js 中配置

14 module.exports = {

15 plugins: [

16 ['import', {

17 libraryName: 'vant',

18 libraryDirectory: 'es',

19 style: true

20 }, 'vant']

21 ]

22 };

方式二. 手动按需引入组件

1 import Button from 'vant/lib/button';

2 import 'vant/lib/button/style';

方式三. 导入所有组件

Vant 支持一次性导入所有组件,引入所有组件会增加代码包体积,因此不推荐这种做法

1 import Vue from 'vue';

2 import Vant from 'vant';

3 import 'vant/lib/index.css';

4

5 Vue.use(Vant);

4、组件注册

全局注册

全局注册后,你可以在 app 下的任意子组件中使用注册的 Vant 组件。

1 import Vue from 'vue';

2 import { Button } from 'vant';

3

4 // 方式一. 通过 Vue.use 注册

5 // 注册完成后,在模板中通过 标签来使用按钮组件

6 Vue.use(Button);

7

8 // 方式二. 通过 Vue.component 注册

9 // 注册完成后,在模板中通过 标签来使用按钮组件

10 Vue.component(Button.name, Button);

局部注册

局部注册后,你可以在当前组件中使用注册的 Vant 组件。

1 import { Button } from 'vant';

2

3 export default {

4 components: {

5 [Button.name]: Button,

6 },

7 };

4、使用

main.js内容

1 import Vue from 'vue'

2 import App from './App.vue'

3

4 // 导入组件

5 import Vant from 'vant'

6 // 导入组件样式库

7 import 'vant/lib/index.css'

8 // 全局注册vant

9 Vue.use(Vant)

10

11 Vue.config.productionTip = false

12

13 new Vue({

14 render: h => h(App)

15 }).$mount('#app')

在App.vue中使用相关组件

1

10

14

启动服务,查看样式加载情况,npm run serve

二、适配的配置

vw适配

官方说明:https://vant-contrib.gitee.io/vant/v2/#/zh-CN/advanced-usage

1、下载依赖

1 npm i postcss-px-to-viewport@1.1.1 -D

2 安装报错,则:

3 npm i postcss-px-to-viewport@1.1.1 -D --legacy-peer-deps

2、新增配置

项目根目录, 新建postcss的配置文件postcss.config.js

1 // postcss.config.js

2 module.exports = {

3 plugins: {

4 'postcss-px-to-viewport': {

5 // 设计稿如果是2倍图,宽是750,则 750/2 = 375,下面就写375

6 // 设计稿如果是3倍图,宽是 1080,则 1080/3 = 360,下面就写360

7 viewportWidth: 375

8 }

9 }

10 }

3、修改了配置需要重启服务

REM适配

1、下载依赖包

1 npm i postcss-pxtorem -D

2 npm i lib-flexible

3 报错解决,安装时,加 --legacy-peer-deps 选项

2、main.js中导入所需的js

1 import 'lib-flexible'

3、新增配置

项目根目录,创建 postcss.config.js,把下面的代码加入进去即可

1 module.exports = {

2 plugins: {

3 'postcss-pxtorem': {

4 rootValue: 37.5,

5 propList: ['*'],

6 },

7 },

8 };

4、修改配置重启服务

定制主题

第一步:

方式1:按需引入样式(推荐)

在 babel.config.js 中配置按需引入样式源文件,注意 babel6 不支持按需引入样式,请手动引入样式。

1 module.exports = {

2 plugins: [

3 [

4 'import',

5 {

6 libraryName: 'vant',

7 libraryDirectory: 'es',

8 // 指定样式路径

9 style: (name) => `${name}/style/less`,

10 },

11 'vant',

12 ],

13 ],

14 };

方式2:手动引入

1 // 引入全部样式

2 import 'vant/lib/index.less';

3

4 // 引入单个组件样式

5 import 'vant/lib/button/style/less';

第二步:

使用 Less 提供的 modifyVars 即可对变量进行修改,下面是参考的 webpack 配置。

1 // webpack.config.js

2 module.exports = {

3 rules: [

4 {

5 test: /\.less$/,

6 use: [

7 // ...其他 loader 配置

8 {

9 loader: 'less-loader',

10 options: {

11 // 若 less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。

12 lessOptions: {

13 modifyVars: {

14 // 直接覆盖变量

15 'text-color': '#111',

16 'border-color': '#eee',

17 // 或者可以通过 less 文件覆盖(文件路径为绝对路径)

18 // hack: `true; @import "your-less-file-path.less";`,

19 },

20 },

21 },

22 },

23 ],

24 },

25 ],

26 };

如果 vue-cli 搭建的项目,可以在 vue.config.js 中进行配置。

1 // vue.config.js

2 module.exports = {

3 css: {

4 loaderOptions: {

5 less: {

6 // 若 less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。

7 lessOptions: {

8 modifyVars: {

9 // 直接覆盖变量

10 'text-color': '#111',

11 'border-color': '#eee',

12 // 或者 如果要修改的样式比较多,可以通过 less 文件覆盖(文件路径为绝对路径)

13 // hack: `true; @import "your-less-file-path.less";`, aaaa: 'red' // 项目中组件的颜色color : @aaa, 此时就会根据这里的变量进行颜色的覆盖

14 },

15 },

16 },

17 },

18 },

19 };

三、面经项目

基础依赖下载

1 // 1、脚手架

2 npm i @vue/cli -g

3

4

5 // 2、下载vant

6 npm i vant@latest-v2 -S

1、目录结构

2、src/api下的调用接口的js

article.js

1 import request from '@/utils/request'

2

3 // 获取文章列表接口封装完成

4 export const getArticles = (obj) => {

5 return request.get('/interview/query', {

6 // get请求参数

7 params: {

8 current: obj.current || 1, // 当前页 → 做分页

9 pageSize: obj.pageSize || 10, // 每页条数 → 做分页

10 sorter: obj.sorter // 排序字段 → 推荐(weight_desc) & 最新(不传参数)

11 }

12 // // headers请求头,配置token

13 // headers: {

14 // Authorization: `Bearer ${token}`

15 // }

16 })

17 }

18

19 // 获取文章详情数据

20 export const getArticleDetail = (id) => {

21 return request.get('interview/show', {

22 params: {

23 id

24 }

25 })

26 }

27

28 // 点赞接口

29 export const updateLike = (id) => {

30 return request.post('interview/opt', {

31 id,

32 optType: 1 // 喜欢

33 })

34 }

35

36 // 收藏接口

37 export const updateCollect = (id) => {

38 return request.post('interview/opt', {

39 id,

40 optType: 2 // 收藏

41 })

42 }

43

44 // 获取我的收藏

45 export const getArticlesCollect = (obj) => {

46 return request.get('/interview/opt/list', {

47 params: {

48 page: obj.page, // 当前页

49 pageSize: 5, // 可选

50 optType: 2 // 表示收藏

51 }

52 })

53 }

54

55 // 获取我的喜欢

56 export const getArticlesLike = (obj) => {

57 return request.get('/interview/opt/list', {

58 params: {

59 page: obj.page, // 当前页

60 pageSize: 5, // 可选

61 optType: 1 // 表示喜欢

62 }

63 })

64 }

user.js

1 // 本文件用于存放所有和用户相关的请求函数

2 import request from '@/utils/request'

3

4 // 1. 注册用户

5 export const register = (data) => {

6 // 进行注册请求

7 // 注意:这里必须 return,将请求的promise对象返回,将来才能await拿结果

8 return request.post('/user/register', data)

9 }

10

11 // 2. 账户登录

12 export const login = (data) => {

13 // 进行登录请求

14 return request.post('/user/login', data)

15 }

16

17 // 3. 获取用户信息

18 export const getUserInfo = () => {

19 return request('/user/currentUser')

20 }

3、公共组件components目录下

1

21

22

40

41

4、路由router目录下

index.js

1 import Vue from 'vue'

2 import VueRouter from 'vue-router'

3 import { getToken } from '@/utils/storage'

4

5 // 一级路由页面的导入

6 const Login = () => import('@/views/Login')

7 const Register = () => import('@/views/Register')

8 const Layout = () => import('@/views/Layout')

9 const Detail = () => import('@/views/Detail')

10

11 // 二级路由页面的导入

12 const Article = () => import('@/views/Article')

13 const Collect = () => import('@/views/Collect')

14 const Like = () => import('@/views/Like')

15 const User = () => import('@/views/User')

16

17 Vue.use(VueRouter)

18

19 const router = new VueRouter({

20 routes: [

21 { path: '/login', component: Login },

22 { path: '/register', component: Register },

23 { path: '/article/:id', component: Detail },

24 {

25 path: '/',

26 component: Layout,

27 redirect: '/article',

28 children: [

29 { path: '/article', component: Article },

30 { path: '/like', component: Like },

31 { path: '/collect', component: Collect },

32 { path: '/user', component: User }

33 ]

34 }

35 ]

36 })

37

38 // 白名单(就是一个数组,数组收录所有无需登录即可访问的页面)

39 const whiteList = ['/login', '/register']

40

41 // 路由前置守卫

42 // 1. to 往哪去

43 // 2. from 从哪来

44 // 3. next 是否放行 next() 放行 next(路径) 拦截到某个页面

45 router.beforeEach((to, from, next) => {

46 const token = getToken()

47 if (token) {

48 // 如果有token,直接放行

49 next()

50 } else {

51 // 没有token的人,看看要去哪

52 // 判断访问的路径 to.path, 是否在白名单中

53 if (whiteList.includes(to.path)) {

54 next()

55 } else {

56 next('/login')

57 }

58 }

59 })

60

61 export default router

5、工具utils目录下

request.js

1 import axios from 'axios'

2 import { Toast } from 'vant'

3 import { getToken, delToken } from './storage'

4 import router from '@/router/index'

5

6 // 创建自定义的实例

7 const instance = axios.create({

8 baseURL: 'http://interview-api-t.itheima.net/h5/',

9 timeout: 5000

10 })

11

12 // 自定义配置 (请求和响应拦截器)

13 // 添加请求拦截器

14 instance.interceptors.request.use(function (config) {

15 // 在发送请求之前做些什么

16 const token = getToken()

17 // 统一携带token

18 if (token) {

19 config.headers.Authorization = `Bearer ${token}`

20 }

21 return config

22 }, function (error) {

23 // 对请求错误做些什么

24 return Promise.reject(error)

25 })

26

27 // 添加响应拦截器

28 instance.interceptors.response.use(function (response) {

29 // 对响应数据做点什么

30 return response.data

31 }, function (error) {

32 // console.log(error)

33 // 有错误响应,后台正常返回了错误信息

34 if (error.response) {

35 if (error.response.status === 401) {

36 // 清除掉无效的token

37 delToken()

38 // 拦截到登录

39 router.push('/login')

40 } else {

41 // 有错误响应,提示错误消息

42 // this.$toast(error.response.data.message)

43 Toast(error.response.data.message)

44 }

45 }

46 // 对响应错误做点什么

47 return Promise.reject(error)

48 })

49

50 // 导出实例

51 export default instance

storage.js 公共存储

1 const KEY = 'vant-mobile-exp-token'

2

3 // 1. 获取token (需要返回token)

4 export const getToken = () => {

5 return localStorage.getItem(KEY)

6 }

7 // 2. 设置token

8 export const setToken = (newToken) => {

9 localStorage.setItem(KEY, newToken)

10 }

11 // 3. 删除token

12 export const delToken = () => {

13 localStorage.removeItem(KEY)

14 }

vant按需导入的vant-ui.js

1 // 按需导入:将需要的vant组件,逐一导入

2 import {

3 Grid,

4 GridItem,

5 CellGroup, Icon, List, Cell, Toast, NavBar, Form, Field, Button, Rate, Tabbar, TabbarItem

6 } from 'vant'

7 import Vue from 'vue'

8 Vue.use(Grid)

9 Vue.use(GridItem)

10 Vue.use(CellGroup)

11 Vue.use(Icon)

12 Vue.use(List)

13 Vue.use(Cell)

14 Vue.use(Toast)

15 Vue.use(NavBar)

16 Vue.use(Form)

17 Vue.use(Field)

18 Vue.use(Tabbar)

19 Vue.use(TabbarItem)

20 Vue.use(Button)

21 Vue.use(Rate)

6、views目录下的视图

Article.vue

1

32

33

93

94

Collect.vue

1

14

15

42

43

Detail.vue

1

27

28

67

68

Layout.vue

1

15

16

21

22

Like.vue

1

14

15

42

43

Login.vue

1

37

38

63

64

Register.vue

1

37

38

76

77

User.vue

1

21

22

46

47

7、根组件App.vue

1

7

8

17

18

8、main.js

1 import Vue from 'vue'

2 import App from './App.vue'

3 import router from './router'

4

5 // 全部导入:将所有的vant组件,一次性导入到项目中

6 // import Vant from 'vant'

7 // import 'vant/lib/index.css'

8 // Vue.use(Vant)

9

10 // 导入按需导入的配置文件

11 import '@/utils/vant-ui'

12

13 // 组件的全局注册

14 import ArticleItem from '@/components/ArticleItem'

15 Vue.component('ArticleItem', ArticleItem)

16

17 Vue.config.productionTip = false

18

19 new Vue({

20 router,

21 render: h => h(App)

22 }).$mount('#app')

9、package.json

1 {

2 "name": "hm-exp-mobile",

3 "version": "0.1.0",

4 "private": true,

5 "scripts": {

6 "serve": "vue-cli-service serve",

7 "build": "vue-cli-service build",

8 "lint": "vue-cli-service lint"

9 },

10 "dependencies": {

11 "axios": "^1.3.5",

12 "core-js": "^3.8.3",

13 "vant": "^2.12.54",

14 "vue": "^2.6.14",

15 "vue-router": "^3.5.1"

16 },

17 "devDependencies": {

18 "@babel/core": "^7.12.16",

19 "@babel/eslint-parser": "^7.12.16",

20 "@vue/cli-plugin-babel": "~5.0.0",

21 "@vue/cli-plugin-eslint": "~5.0.0",

22 "@vue/cli-plugin-router": "~5.0.0",

23 "@vue/cli-service": "~5.0.0",

24 "@vue/eslint-config-standard": "^6.1.0",

25 "babel-plugin-import": "^1.13.6",

26 "eslint": "^7.32.0",

27 "eslint-plugin-import": "^2.25.3",

28 "eslint-plugin-node": "^11.1.0",

29 "eslint-plugin-promise": "^5.1.0",

30 "eslint-plugin-vue": "^8.0.3",

31 "less": "^4.0.0",

32 "less-loader": "^8.0.0",

33 "postcss-px-to-viewport": "1.1.1",

34 "vue-template-compiler": "^2.6.14"

35 }

36 }

10、postcss.config.js

1 // postcss.config.js

2 module.exports = {

3 plugins: {

4 'postcss-px-to-viewport': {

5 // 标准屏的宽度,设计图 750-2倍图,标准屏 375

6 viewportWidth: 375

7 }

8 }

9 }

11、vue.config.js

1 const { defineConfig } = require('@vue/cli-service')

2 module.exports = defineConfig({

3 transpileDependencies: true,

4 // 将资源访问路径从 / 配置成 ./ 相对路径

5 publicPath: './',

6 css: {

7 loaderOptions: {

8 less: {

9 // 若 less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。

10 lessOptions: {

11 modifyVars: {

12 // 直接覆盖变量

13 blue: '#FA6D1D'

14 }

15 }

16 }

17 }

18 }

19 })

打包发布

1 // yarn管理

2 yarn build

3

4 // npm 管理

5 npm run build

配置publicPath

1 module.exports = {

2 // 设置获取.js,.css文件时,是以相对地址为基准的。

3 // https://cli.vuejs.org/zh/config/#publicpath

4 publicPath: './'

5 }

路由懒加载

路由懒加载 & 异步组件, 不会一上来就将所有的组件都加载,而是访问到对应的路由了,才加载解析这个路由对应的所有组件

官网链接:https://router.vuejs.org/zh/guide/advanced/lazy-loading.html#%E4%BD%BF%E7%94%A8-webpack

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。

1 const Detail = () => import('@/views/detail')

2 const Register = () => import('@/views/register')

3 const Login = () => import('@/views/login')

4 const Article = () => import('@/views/article')

5 const Collect = () => import('@/views/collect')

6 const Like = () => import('@/views/like')

7 const User = () => import('@/views/user')