Loading

项目总结

0.Vue项目的一些经验总结

做了很多个Vue技术栈项目了,总结一些经常会用到的技术点,方便以后快速回顾,也当作是一种输出方式了。

talk is cheap, show me the code!


1.在Vue中给axios添加请求拦截器

import axios from 'axios'
// 创建一个名字叫request的axios实例,和axios本身的功能一样
// 推荐使用axios.create方式创建实例,因为如果一个系统里面有多个api地址的时候可以给不同的实例设置不同地址
// 如果直接使用axios.default.baseurl的方式就只能设置一个api地址,很局限
const request = axios.create({
  baseURL: 'http://api-toutiao-web.itheima.net'
})

// 请求拦截器
request.interceptors.request.use(
  // 任何所有请求会经过这里
  // config 是当前请求相关的配置信息对象
  // config 是可以修改的
  function (config) {
    const userToken = JSON.parse(window.localStorage.getItem('user_token'))
    if (userToken) {
      // 用户已经登录了,在headers请求头带上token
      config.headers.Authorization = `Bearer ${userToken.token}`
    }
    // 然后我们就可以在允许请求出去之前定制统一业务功能处理
    // 例如:统一的设置 token

    // 当这里 return config 之后请求在会真正的发出去
    return config
  },
  // 请求失败,会经过这里
  function (error) {
    return Promise.reject(error)
  }
)
export default request

2.在Vue中给router添加导航守卫

vue-router的导航守卫也叫路由拦截器

router.beforeEach((to, from, next) => {
  // 在路由拦截器中判断是否有token,如果有token就next放行,否则next重定向到登录页面
  const userToken = window.localStorage.getItem('user_token')
  if (!userToken && to.path !== '/login') {
    return next('/login')
  }
  next()
})

3.在Vue中配置Filters过滤器

  filters: {
    // 文章审核状态过滤器
    auditStatus: value => {
      switch (value) {
        case 0:
          return '草稿'
        case 1:
          return '待审核'
        case 2:
          return '审核通过'
        case 3:
          return '审核失败'
        case 4:
          return '已删除'
        default:
          return '未知'
      }
    }
  },

在模版中使用拦截器,| 符号前面的参数是给拦截器使用的,后面的auditStatus是拦截器。

<el-table-column
   align="center"
   width="120px"
   label="状态">
    <template slot-scope="scope">
    	<el-tag type="success">{{ scope.row.status | auditStatus}}</el-tag>
    </template>
</el-table-column>

4.element-ui中的image组件

图片容器,在保留原生img的特性下,支持懒加载,自定义占位内容、加载失败、大图预览等。

代码胜千言。

<el-image
	style="width: 150px; height: 100px"
	:src="scope.row.cover.images[0]"
	lazy
	:preview-src-list="scope.row.cover.images"
	fit="cover"
>
	<!-- 占位内容 -->
	<div slot="placeholder" class="image-slot">
		加载中<span class="dot">...</span>
	</div>
	<!-- 加载失败内容 -->
	<div slot="error" class="image-slot">
		<img
			class="article-error-cover"
			src="./error.3f7b1f94.gif"
			alt="error"
		/>
	</div>
</el-image>

5.通过数组的方式处理文章状态

比较low的方式

v-if、过滤器写switch...case

逼格高的方式

<el-table-column align="center" width="120px" label="状态">
    <template slot-scope="scope">
        <el-tag :type="articleStatusList[scope.row.status].type">{{
            articleStatusList[scope.row.status].name}}
        </el-tag>
    </template>
</el-table-column>
data() {
    return {
    	articleStatusList: [
            // 文章状态列表
            { status: 0, name: '草稿', type: 'info' },
            { status: 1, name: '待审核', type: 'primary' },
            { status: 2, name: '审核通过', type: 'success' },
            { status: 3, name: '审核失败', type: 'warning' },
            { status: 4, name: '已删除', type: 'danger' }
        ]
    }
}

1611275625411

这样就可以通过不同的status状态来切换对应的文本以及el-tag标签的type类型。

6.element-ui中的分页组件

引入分页组件el-pagination

<el-pagination
	class="article-pagination"
	background
	@size-change="handleSizeChange"
	@current-change="handleCurrentChange"
	:current-page="currentPage4"
	:page-sizes="[100, 200, 300, 400]"
	:page-size="100"
	layout="total, sizes, prev, pager, next, jumper"
	:total="400"
>
</el-pagination>

参数介绍:

属性

background: 设置背景颜色

current-page: 设置当前页码

page-sizes: 设置每页显示多少条记录数,接收一个数组

page-size: 设置当前每页显示多少条记录数,一般为page-sizes属性的第一项

layout: 分页组件显示的内容

total: 总共有多少条记录数

方法

@size-change:每页分页数量变化时触发的事件函数,

@current-page:当前页变化时触发的事件函数

看下图:

1611276870824

然后自己根据业务进行灵活使用。

7.element-ui中的日期选择器

自定义日期格式

<el-form-item label="日期">
	<el-date-picker
		v-model="form.dateList"
		type="daterange"
		range-separator="至"
		start-placeholder="开始日期"
		end-placeholder="结束日期"
		value-format="yyyy-MM-dd"
	>
	</el-date-picker>
</el-form-item>

v-model双向绑定的数据是一个数组,数组下标0的数据是开始日期,数组下标1的数据是结束日期

默认返回的时间格式是一个Date实例,通常转换成 2021-1-22 这种格式数据比较好,那么如何转换呢?可以给组件传入value-format='yyyy-MM-dd'属性实现格式化。

1611281779778

8.element-ui中的loading效果

Element 提供了两种调用 Loading 的方法:指令和服务。对于自定义指令v-loading,只需要绑定Boolean即可。默认状况下,Loading 遮罩会插入到绑定元素的子节点,通过添加body修饰符,可以使遮罩插入至 DOM 中的 body 上。

解决请求没回来之前,用户界面可交互问题;防止请求过慢,用户在分页按钮上面狂点。

请求期间,最好禁用会发送请求的按钮。

1611368600789

发请求的时候将isLoading变量改为true,请求成功或失败后改为false即可。

9.Vue中router的几种传参方式

10.element-ui中的表单验证

11.element-ui中的图片上传

12.补充对象解构的骚操作

默认获取的数据

1611656484391

1611656375776

解构后获取的数据

1611656538719

13.Vue中富文本编辑器使用

常见的富文本编辑器有:

  • 百度富文本编辑器(UEditor)

  • CKEditor

  • Vue-quill-Editor

  • tiptap(需要深度定制的话就用它)

  • element-tiptap(基于tiptap封装的富文本编辑器,与element-ui样式类似,适合不需要深度定制,开箱即用的情况)

Vue官方推荐周边插件资源:https://github.com/vuejs/awesome-vue,可以在这里面找到业务需要的开源插件,例如日历、轮播图、富文本编辑器等。

下面讲解element-tiptap在vue中的使用

1.安装element-tiptap

官方仓库地址:https://github.com/Leecason/element-tiptap/blob/master/README_ZH.md

npm install element-tiptap

2.初始配置

这里使用局部引入方式

import {
  ElementTiptap,
  Doc,
  Text,
  Paragraph,
  Heading,
  Bold,
  Underline,
  Italic,
  Image,
  Strike,
  ListItem,
  BulletList,
  OrderedList,
  TodoItem,
  TodoList,
  HorizontalRule,
  Fullscreen,
  Preview,
  CodeBlock
} from 'element-tiptap'

import 'element-tiptap/lib/index.css'
export default {
  name: 'PublishIndex',
  components: {
    'el-tiptap': ElementTiptap
  },
  props: {},
  data () {
    return {
      extensions: [
        new Doc(),
        new Text(),
        new Paragraph(),
        new Heading({ level: 3 }),
        new Bold({ bubble: true }), // 在气泡菜单中渲染菜单按钮
        new Image(),
        new Underline(), // 下划线
        new Italic(), // 斜体
        new Strike(), // 删除线
        new HorizontalRule(), // 华丽的分割线
        new ListItem(),
        new BulletList(), // 无序列表
        new OrderedList(), // 有序列表
        new TodoItem(),
        new TodoList(),
        new Fullscreen(),
        new Preview(),
        new CodeBlock()
      ]
    }
  },
  computed: {},
  watch: {},
  created () {},
  mounted () {},
  methods: {}
}
</script>
<el-tiptap v-model="form.content" lang="zh" :extensions="extensions"></el-tiptap>

页面效果:

1611814871868

3.定制图片上传

由于element-tiptap默认本地上传图片使用的是base64,因此需要进行定制化,前端上传图片给服务器,服务器返回一个外链的url,将url返回给element-tiptap渲染。

1611815958381

base64补充:它仅适用于非常小的图像。 Base64编码文件比原始文件大。其优势在于不必打开另一个连接并向服务器发送图像的HTTP请求。这种好处很快就会消失,所以只有大量非常小的个人图像才有优势。

富文本中的图片base64和外链方式对比。

base64的图片:

如果图片较大且很多,虽然可以减少http请求,但是也会造成页面很卡,因为要等到全部的图片全部都加载完了之后才开始渲染。

外链的图片:

可以在页面渲染完成之后再进行加载,不会阻塞页面的渲染,体验好,但是会发送http请求。

根据自己的业务需求选择吧。

注意:一般文件上传的接口都要求把请求头中的 Content-Type 设置为 multipart/form-data,但是我们使用 axios 上传文件的话就不要需要手动设置了,你只需要给 data 一个 FormData 对象即可,axios 内部做了对应的封装。

extensions: [
    new Doc(),
    new Text(),
    new Paragraph(),
    new Heading({ level: 3 }),
    new Bold({ bubble: true }), // 在气泡菜单中渲染菜单按钮
    new Image({
        // 自定义图片上传函数 返回Promise
        uploadRequest (file) {
            const fd = new FormData()
            fd.append('image', file)
            // 这里 return 是返回 Promise 对象
            return uploadImage(fd).then(({ data: res }) => {
                // 这个 return 是返回最后的结果
                return res.data.url
            })
        }
    }),
    new Underline(), // 下划线
    new Italic(), // 斜体
    new Strike(), // 删除线
    new HorizontalRule(), // 华丽的分割线
    new ListItem(),
    new BulletList(), // 无序列表
    new OrderedList(), // 有序列表
    new TodoItem(),
    new TodoList(),
    new Fullscreen(),
    new Preview(),
    new CodeBlock()
],

14.element-ui中的响应式布局

el-row表示一行,一行分24列,通过:span属性来标识列的宽度。

设置分栏间隔

响应式布局

xs、sm、md、lg、xl

15.Vue中compute计算属性应用

16.element-ui中的upload组件

<el-upload
	class="upload-demo"
	drag
	action="http://123456abc.xyz/user/images"
	:on-success="handleUploadSuccess"
	name="image"
	:headers="{Authorization: `Bearer ${userToken.token}`}"
	multiple>
	<i class="el-icon-upload"></i>
	<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
</el-upload>

// 文件上传成功
handleUploadSuccess (res) {
    this.$message.success('上传成功!')
    this.uploadDialogVisible = false	// 关闭dialog对话框
    this.loadUserImages()	// 加载页面数据
},

使用el-upload的时候需要注意headers的配置,使用action的方式上传图片默认不会走你自己封装的axios请求拦截器,因此这里需要手动配置headers加上token。

更多的配置参考element文档:https://element.eleme.cn/#/zh-CN/component/upload#methods

17.Vue中监听路由变化

有一个小需求,我们的后台管理项目的左侧菜单栏要支持下面3个功能:

  1. 用户点击菜单,切换激活效果(element已经支持)
  2. 用户刷新页面的时候要保留激活效果
  3. 用户手动切换url时激活效果要同步

实现代码:

    <el-menu
      :default-active="defaultSelectPath"
      class="el-menu-vertical-demo"
      background-color="#002033"
      text-color="#fff"
      active-text-color="#ffd04b"
      :collapse-transition="false"
      router
    >
      <el-menu-item index="/">
        <i class="el-icon-s-home"></i>
        <span>首页</span>
      </el-menu-item>
      <el-menu-item index="article">
        <i class="el-icon-document"></i>
        <span slot="title">内容管理</span>
      </el-menu-item>
    </el-menu>
<script>
    export default {
      name: 'AppAside',
      components: {},
      props: {},
      data () {
        return {
          defaultSelectPath: '/'
        }
      },
      computed: {},
      watch: {
        $route (to, from) {
          if (to.path !== '/') {
            this.defaultSelectPath = this.$route.path.substring(1)
          } else {
            this.defaultSelectPath = this.$route.path
          }
        }
      },
      created () {
      },
      mounted () {
        if (this.$route.path !== '/') {
          this.defaultSelectPath = this.$route.path.substring(1)
        } else {
          this.defaultSelectPath = this.$route.path
        }
      },
      methods: {
      }
    }
</script>

18.Vue中图片裁剪插件

cropper.js

19.Vue中的数据可视化

20.如何寻找一手资料

1.直接去github搜索,用英文搜,例如 搜索 vue crop.

2.使用vue-awesome资源列表搜索.

21.html label标签的应用场景

22.window.URL.createObjectURL API的应用

思考下面一个场景:

用户点击自己的头像,选择新的头像图片进行修改,修改完成之后需要弹出一个dialog对话框,在对话框中显示用户的头像图片,此时头像还没有上传到服务器哦,这个时候怎么办呢?可以使用window.URL.createObjectURL API来实现。

API返回的是一个blob地址,这个API是HTML5的新特性。

代码如下:

1612376447299

23.Vue中修改配置文件不生效的解决方法

1612377467524

直接删除node_modules/.cache文件夹就可以了。

需要额外学习的知识


1.img标签的object-fit属性

2.css3 border属性 渐变、背景图

3.搞懂Vue中的.sync修饰符

4.安装markdown vue主题

posted @ 2021-02-05 23:12  WandyLiang  阅读(314)  评论(0)    收藏  举报