「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」。
SPA 单页面应用程序
我们熟知的 JavaScript 框架如
react、vue、angular都可用于构建SPA
单页面应用程序(Single Page Application)简称 SPA,顾名思义,指的是只有一个 Web 页面的应用(只加载单个 HTML 页面),在用户与应用程序交互时动态更新该页面。
相较于传统多页面应用程序【每次请求服务器返回的都是一个完整的 HTML 页面】,SPA 只有第一次会加载页面。
🌤显著优势
- 减轻服务器的压力
- 服务器只提供数据,不负责页面的合成与逻辑的处理,吞吐能力会提高几倍
- 良好的前后端工作分离模式
- 后端专注于提供 API 接口
- 前端专注于页面渲染
- 良好的交互体验
- SPA 的内容改变不需要重新加载整个页面
- 获取数据也是通过 Ajax 异步获取
- 没有页面间的跳转,不会出现 “白屏现象”
💦但也其局限性
- 不利于 SEO 搜索引擎优化
- SSR 服务器端渲染
- 首次渲染速度较慢
- 路由懒加载
- 代码压缩
- CDN 加速
- 网络传输压缩
🥂推荐博客:SPA 首屏加载速度慢怎么解决?
Vue-Cli(脚手架)
vue-cli 是 Vue.js 开发的标准工具,它极大地简化了程序员基于 webpack 创建工程化的 Vue 项目的过程。
🧬引用自 vue-cli 官网上的一句话:程序员可以专注在编写应用上,而不必花好几天纠结 webpack 配置的问题。
安装
> npm install -g @vue/cli
使用
> vue create 项目名称
# OR
> vue ui
vue create xxx 创建过程:
创建成功✔
或者也可以使用 UI 界面创建脚手架:
运行
> npm run serve
访问 localhost:8080:
目录结构
在工程化的项目中,vue 要做的事情很单纯:通过 main.js 把 App.vue 渲染到 index.html 指定区域中。
其中:
App.vue用来编写带渲染的模板结构index.html中需要预留一个el 区域main.js把App.vue渲染到index.html所预留的区域中
下面来看看工程化项目的目录结构:
组件化开发
定义
组件化开发指的是:根据封装的思想,把页面上可重用的部分封装为组件,从而方便项目的开发和维护。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树。
👑如下图所展示的效果,契合了组件化开发的思想,用户可以通过拖拽组件的方式,快速生成一个页面的布局结构。
感兴趣的可以去体验下拖拽组件的快感:www.ibootstrap.cn/
好处
前端组件化开发的好处主要体现在以下两方面:
- 提高了前端代码的复用性和灵活性
- 提高了开发效率和后期的可维护性
Vue 中的组件化
vue 是一个完全支持组件化开发的框架,规定组件的后缀名是 .vue。之前接触到的 App.vue 本质就是一个 vue 组件。
.vue 组件构成
每个 .vue 都由 3 部分构成:
<template>:模板结构,是 vue 提供的容器标签,其内 DOM 结构仅支持单个根节点(Vue 3.x 支持多个根节点)<script>:封装组件的 JavaScript 业务逻辑<style>:组件的 UI 样式
其中,每个组件必须包含 template 模板结构,script 行为 和 style 样式 是可选部分。
基本的 .
vue组件案例
<template>
<div id="app">
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
}
}
}
</script>
<style lang="less" scoped>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
text-align: center;
}
</style>
注册组件
🌅VScode 配置 @
路径提示符 与 @ 配置(@ 导向 /src 目录),可以提示文件/文件夹路径防止写错。
🎯先安装 Path Autocomplete 插件:
🎯修改 setting.json 配置文件,添加如下代码:
// 导入文件时是否携带文件的拓展名
"path-autocomplete.extensionOnImport": true,
// 配置 @ 的路径提示符
"path-autocomplete.pathMappings": {
"@": "${folder}/src"
},
🌈@ 路径提示效果演示:
前提:VScode 打开的文件夹是单个项目的根目录,而不能是多个项目的根目录,否则
@失效。
全局组件
🛫以下使用 2 种方式注册并使用全局组件
方式一: Vue.component()
main.js:
import Vue from 'vue'
import App from './App.vue'
import Header from './components/Header.vue'
Vue.config.productionTip = false
// 注册全局组件
Vue.component('Header', Header)
// 如果 Header 的 name 属性存在,可作为注册后的组件名称
// Vue.component(Header.name, Header)
new Vue({
render: h => h(App),
}).$mount('#app')
App.vue:
<template>
<div id="app">
<!-- 使用全局组件 -->
<Header></Header>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
<style lang="less" scoped>
</style>
渲染效果:
方式二: Vue.use()
方式二参考并引用:在 Vue 项目中注册全局组件
Vue 官方提供的插件有 Vue Router、Vuex 和 Vue 服务端渲染三个 Vue.use 可以接受一个对象,Vue.use(obj) 对象 obj 中需要一个 install 函数在 Vue.use(obj) 时,会自动调用该 install 函数,并传入到 Vue 构造器。
👑首先在 @/components 文件夹下新建一个 index.js:
// 引入待全局注册的组件
import EChart from "@/components/Echart.vue";
import Header from '@/components/Header.vue'
// npm install echarts --save
import * as echarts from 'echarts'
export default {
install: function(Vue) {
console.log('自定义插件');
// 注册全局组件!
Vue.component('EChart', EChart)
Vue.component('Header', Header)
// 可以往Vue的原型对象上添加自定义属性或者方法, 在其他.vue文件中,可以通过this访问自定义的属性和方法
Vue.prototype.$echarts = echarts
}
}
🛫main.js:
import Vue from 'vue'
import App from './App.vue'
import Plugin from '@/components'
Vue.config.productionTip = false
// Vue.prototype.$echarts = echarts
// Vue.component('Header', Header)
// Vue.component('EChart', EChart)
// 使用自定义插件
Vue.use(Plugin)
new Vue({
render: h => h(App),
}).$mount('#app')
⛸App.vue:
<template>
<div id="app">
<!-- 务必设置宽高! -->
<div id="echart" ref="echart"></div>
<!-- 使用全局注册组件 -->
<EChart></EChart>
<Header></Header>
</div>
</template>
<script>
export default {
name: 'App',
methods: {
initEchart() {
var myChart = this.$echarts.init(this.$refs.echart)
// 绘制图表
myChart.setOption({
title: {
text: 'ECharts 入门示例'
},
tooltip: {},
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
},
yAxis: {},
series: [
{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}
]
});
}
},
mounted() {
this.initEchart()
},
}
</script>
<style lang="less" scoped>
#echart {
width: 450px;
height: 300px;
}
</style>
效果演示:
局部组件
局部组件是在某一个具体的 vue 实例中定义的,只能在该 vue 实例中使用。
引入 => 注册 => 使用
<template>
<div id="app">
<!-- 3.使用组件 -->
<Header></Header>
</div>
</template>
<script>
// 1.引入组件
import Header from '@/components/Header.vue'
export default {
name: 'App',
// 2.注册局部组件
components: {
Header,
},
}
</script>
访问组件数据
父组件访问子组件数据
🏍使用 ref 给子组件定义一个别名,然后使用 vm.$refs.子组件名.xxx 获取子组件中的数据 data 或方法 methods。
<template>
<div>
<div style="background-color: pink;">
<h2>父组件</h2>
<Child ref="children"></Child>
<button @click="getMsg()">获取</button>
获取到的子组件数据: {{ message }}
</div>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
name: 'parent',
components: {
Child,
},
data() {
return {
message: '',
}
},
methods: {
getMsg() {
// 访问子组件的数据
this.message = this.$refs.children.msg
},
},
}
</script>
演示效果:
子组件访问父组件数据
🚎使用 vm.$parent 访问父组件。
// 场景类似父组件访问子组件数据, 只不过此处无需 ref 引用
console.log(this.$parent.message)
组件间的数据共享
不同于组件之间访问数据,数据共享指的是在组件间传递值。
组件树
组件之间的关系分为以下 3 种:
- 父子关系
- 兄弟关系
- 后代关系
父子组件
父子组件之间的数据共享又分为父->子、子->父。
🚀父子组件间的数据流动图
父组件向子组件共享数据
父组件通过 v-bind 属性绑定向子组件共享数据,同时,子组件需要使用 props 接收数据。
props是组件的自定义属性,可以通过props把数据传递到子组件内部,供子组件内部进行使用。
父组件 Parent.vue:
<template>
<div style="width: 350px; background-color: lightblue;">
<h2>Parent 组件</h2>
<Child :msg="message"></Child>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
name: 'Parent',
components: {
Child,
},
data() {
return {
message: 'Hello Vue.js!'
}
},
}
</script>
子组件 Child.vue:
<template>
<div>
<div style="width: 300px; height: 100px; background-color: tomato;">
<h3>Child 组件 --- {{ msg }}</h3>
</div>
</div>
</template>
<script>
export default {
name: 'Child',
props: {
msg: String
},
}
</script>
执行结果:
💝注:除了指定
props对象外,还可以指定数组类型的props,如props: ['value', 'name', 'age']。
props 验证
对象类型的 props 节点提供了多种数据验证方案,例如:
- 🌈基础的类型检查
- 🪁多个可能的类型
- 🎯必填项校验
- 🔍属性默认值
- 🚀自定义验证函数
基础的类型检查
可以直接为组件的 props 属性指定校验类型,防止绑定错误类型的数据。
export default {
props: {
prop1: String, // 字符串类型
prop2: Number, // 数字类型
prop3: Boolean, // 布尔值类型
prop4: Array, // 数组类型
prop5: Object, // 对象类型
prop6: Date, // 日期类型
prop7: Function,// 函数类型
prop8: Symbol, // 符号类型
},
}
多个可能的类型
若 props 种的某个属性类型不唯一,可将其定义为数组。
export default {
props: {
username: [String, Object]
},
}
必填项 & 默认值
export default {
props: {
age: {
type: Number,
// 必填项
required: true,
// 默认值
default: 19
}
},
}
自定义验证函数
可为 props 属性指定自定义验证函数,实现更加精确的校验。
export default {
name: 'Child',
props: {
msg: {
validator(value) {
// validator 函数的返回值为 true 表示验证通过, false 表示验证失败!
// 例如传入的msg必须匹配某些字符串才可通过校验:
return ['success', 'warning', 'danger'].indexOf(value) !== -1
},
},
},
}
不通过校验的错误信息:
子组件向父组件共享数据
子组件通过自定义事件的方式向父组件共享数据。
父组件 Parent.vue:
<template>
<div>
<h2>Parent 组件 --- {{ message }}</h2>
<Child :msg="message" @changeMessage="getMsg"></Child>
</div>
</template>
<script>
import Child from './Child.vue'
export default {
name: 'Parent',
components: {
Child,
},
data() {
return {
message: 'Hello Vue.js!',
}
},
methods: {
// 通过形参接收子数组传递来的数据
getMsg(msg) {
this.message = msg
},
},
}
</script>
子组件 Child.vue:
<template>
<div>
<div>
<h3>Child 组件 --- {{ msg }}</h3>
<button @click="changeMsg">点我:触发子传父</button>
</div>
</div>
</template>
<script>
export default {
name: 'Child',
props: ['msg'],
methods: {
changeMsg() {
// 点击按钮时, 改变数据
this.msg = 'Hello React!'
// 同时触发自定义事件 changeMessage
this.$emit('changeMessage', this.msg)
},
},
}
</script>
演示一下:
兄弟组件
兄弟组件之间实现数据共享的方案是 EventBus。可以借助于第三方的包 mitt 来创建 eventBus 对象。
兄弟组件间的数据共享
安装 mitt 依赖包:
> npm install mitt
在项目中创建公共的 eventBus 模块:
// eventBus.js
// 导入 mitt 包
import mitt from 'mitt'
// 创建 EventBus 的实例对象
const bus = mitt()
// 将 EventBus 的示例对象共享出去
export default bus
数据发送方:
<template>
<div>
<span>Right(数据发送方)---{{ count }}</span>
<button @click="changeCount">Click</button>
</div>
</template>
<script>
// 导入 eventBus.js 模块,得到共享的 bus 对象
import bus from '@/eventBus.js'
export default {
name: 'Right',
data() {
return {
count: 0,
}
},
methods: {
changeCount() {
this.count++
// 调用 bus.emit() 方法触发自定义事件并发送数据
bus.emit('countChange', this.count)
},
},
}
</script>
数据接收方:
<template>
<div>
<span>Left(数据接收方): {{ lCount }}</span>
</div>
</template>
<script>
// 导入 eventBus.js 模块,得到共享的 bus 对象
import bus from '@/eventBus.js'
export default {
name: 'Left',
data() {
return {
lCount: '',
}
},
created() {
// 调用 bus.on() 方法注册一个自定义事件,通过事件处理函数的形参接收数据
bus.on('countChange', (count) => {
this.lCount = count
})
},
}
</script>
演示一下:
全局数据共享 vuex
🚀Vuex 是终极的组件之间的数据共享方案。在企业级的 vue 项目开发中 vuex 可以让组件之间的数据共享变得高效、清晰、且易于维护。
🔎持续关注本专栏,后续文章会单独聊聊 vuex 的内容。
动态组件
动态组件指的是动态切换组件的显示与隐藏。vue 提供了一个内置的 <component> 组件,专门用于实现组件的动态渲染。
基本语法:
① <component> 是组件的占位符
② 通过 is 属性 动态指定要渲染的组件名称
③ <component is="要渲染的组件名称"></component>
示例代码:
<template>
<div>
<button @click="changeLeft">Left</button>
<button @click="changeRight">Right</button>
<div>
<!-- 动态渲染组件:动态组件的使用<components> -->
<component :is="which"></component>
</div>
</div>
</template>
<script>
import Left from '@/components/Left.vue'
import Right from '@/components/Right.vue'
export default {
name: 'App',
data() {
return {
which: 'Left'
}
},
components: {
Left,
Right
},
methods: {
changeLeft() {
this.which = 'Left'
},
changeRight() {
this.which = 'Right'
}
}
}
</script>
稍微演示下:
是不是发现上图不对劲的地方了!没错,默认情况下,切换动态组件时无法保持组件的状态。此时可以使用 vue 内置的 <keep-alive> 组件保持(缓存)动态组件的状态。
注:
include/exclude中包含的名字是组件的name属性!
<!-- keep-alive 保持状态: 将内部组件缓存,而不是销毁,Vue 还提供了对应的生命周期函数! -->
<!-- include 属性可指定需缓存的组件、相反,exclude 指定不被缓存的组件名(二选一、不能同时使用) -->
<keep-alive include="Left,Right">
<component :is="which"></component>
</keep-alive>
实现效果:
组件插槽
插槽(Slot)是 vue 为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望用户指定的部分定义为插槽。
可以把插槽理解为是组件封装期间,为用户预留的内容占位符。
匿名插槽
🔎子组件(带匿名插槽):
<template>
<div>
<!-- 插槽: 默认值为Default Message -->
<slot>Default Message</slot>
</div>
</template>
🚀父组件:
<template>
<div>
<MyComponent>
<!-- 替换slot插槽 -->
<template>
<h3>用户自定义的内容1</h3>
<h3>用户自定义的内容2</h3>
<h3>用户自定义的内容3</h3>
</template>
</MyComponent>
</div>
</template>
效果演示:
具名插槽
如果在封装组件时需要预留多个插槽节点,则需要为每个 <slot> 插槽指定具体的 name 名称。这种带有具体名称的插槽叫做 “具名插槽”。
🌈在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称。
🏹Tip:
slot-scope是旧 api (不推荐使用),v-slot是最新的。- 没有指定
name名称的插槽,默认名称叫做default。
🔎子组件:
<template>
<div>
<!-- 具名插槽 -->
<slot name="header">Header Message</slot>
<slot name="default">Main Message</slot>
<footer>
<slot name="footer">Footer Message</slot>
</footer>
</div>
</template>
🚀父组件:
<template>
<div>
<MyComponent>
<!-- 具名(header)插槽 -->
<template v-slot:header>
<h2>滕王阁序</h2>
</template>
<!-- 具名(default)插槽 -->
<template v-slot:default>
<div>豫章故郡, 洪都新府.</div>
<div>星分翼轸, 地接衡庐.</div>
</template>
<!-- v-slot:footer简写形式: #footer -->
<template #footer>
<p>Author: 王勃</p>
</template>
</MyComponent>
</div>
</template>
演示结果:
🚀注:插槽节点不仅仅可以传入标签元素,还可以传入组件 (无需 <template> 占位符,直接写入组件内即可),例如:
<MyComponent>
<HelloWorld :msg="'组件插槽'"></HelloWorld>
</MyComponent>
🏆 v-slot 简写形式
🎨即把 v-slot: 替换为字符 #。例如 v-slot:header 可以被重写为 #header.
作用域插槽
子组件中的作用域插槽可以为父组件中的插槽的显示提供数据。好比复古唱片机,根据提供的不同唱片向外输出不同的音乐。
基本用法
父组件:
<template>
<div>
<!-- 定义作用域插槽 -->
<slot name="func" :infomation="info"></slot>
</div>
</template>
<script>
export default {
data() {
return {
info: {
username: 'w',
age: 21,
sex: 'M',
},
}
},
}
</script>
子组件:
<MyComponent>
<!-- 使用作用域插槽 -->
<template #func="scope">
<div>
{{ scope.infomation }}
</div>
</template>
</MyComponent>
解构赋值
起步推荐文章:[译] 我最终是怎么玩转了 Vue 的作用域插槽
<MyComponent>
<!-- 解构赋值 -->
<!-- <template #func="{ infomation }"> -->
<!-- 解构赋值之命别名 -->
<template #func="{ infomation:msg }">
<div>
<h5>{{ msg.username }}</h5>
<h5>{{ msg.age }}</h5>
<h5>{{ msg.sex }}</h5>
</div>
</template>
</MyComponent>
简单常见的应用场景
🌅数据在子组件自身,但根据数据生成的结构需要组件的使用者来决定。
父组件:
<template>
<div>
<tr v-for="item in userList" :key="item.id">
<slot :user="item"></slot>
</tr>
</div>
</template>
子组件:
<MyComponent>
<template #default="scope">
<td>{{ scope.user.id }}</td>
<td>{{ scope.user.username }}</td>
<td>{{ scope.user.age }}</td>
<td>{{ scope.user.sex }}</td>
</template>
</MyComponent>
渲染后的效果等价于:
<tr v-for="item in userList" :key="item.id">
<td>{{ scope.user.id }}</td>
<td>{{ scope.user.username }}</td>
<td>{{ scope.user.age }}</td>
<td>{{ scope.user.sex }}</td>
</tr>
🔎关于作用域插槽的实际应用场景:vue 作用域插槽,你真的懂了吗?
作用域插槽适合的场景是至少包含三级以上的组件层级(文中例子),是一种优秀的组件化方案!
axios
Axios 是一个基于 promise 网络请求库。
安装
npm install axios --save
使用
GET
原始请求:
// 发起一个get请求
axios({
method: 'get',
url: 'http://localhost:8090/user/get',
params: {
name: 'w'
}
})
.then(function (response) {
console.log(response)
});
axios GET API:
// 公共路径抽取到 main.js 文件中, 见下文 '全局配置' 部分
// GET请求
axios.get('/user?params=12345' )
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// params
axios.get( '/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.then(function () {
// 总是会执行
});
// 支持 async/await 用法
async function getUser() {
try {
const response = await axios.get('/user?ID=12345');
console.log(response);
} catch (error) {
console.error(error);
}
}
// 解构赋值
async function getUser() {
try {
// 解构 data 数据部分
const { data } = await axios.get('/user?ID=12345');
console.log(data);
} catch (error) {
console.error(error);
}
}
POST
原始请求:
// 发起一个post请求
axios({
method: 'post',
url: '/user/login',
data: {
name: 'author',
password: '123456'
}
});
axios POST API:
// POST请求
axios.post('/user/login', {
name: 'author',
password: '123456'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// await/async + 解构赋值
async function login() {
try {
// 解构赋值后重命名
const { data: msg } = await axios.post('/user/login', this.user);
console.log(msg);
} catch (error) {
console.error(error);
}
}
全局配置
// 设置全局公共请求路径
axios.defaults.baseURL = 'https://www.escook.cn'
// 配置后使用 this.$axios.get()/post() 发请求
Vue.prototype.$axios = axios
如果遇到以下问题均为跨域问题,后端跨域有问题建议看这篇。
如果后端接口不归自己提供,那么就需要在前端配置跨域。简单提一下:
vue 项目运行地址:http://localhost:8080
API 接口运行地址:www.escook.cn
在 main.js 入口文件中配置:
// 向当前 vue 项目运行端口发送请求, 这样就不存在跨域问题, 然后发现请求的接口不存在, 直接将请求交由 proxy 代理!
axios.defaults.baseURL = 'http://localhost:8080'
Vue.prototype.$axios = axios
然后在项目根目录创建 vue.config.js 配置文件,并添加以下代码:
必须重启项目才能让
vue.config.js改动的配置生效。
module.exports = {
devServer: {
port: 8080,
// 代理转发地址
proxy: 'https://www.escook.cn'
}
}
发送请求:
export default {
methods: {
async getData() {
const data = await this.$axios.get('/api/cart')
console.log(data);
},
},
created() {
this.getData()
},
}
响应结果:
由此可见,一个请求的响应包含以下信息。
{
// config 是 axios 请求的配置信息
config: {},
// data 由服务器提供的响应
data: {},
// headers 是服务器响应头
// 所有的 header 名称都是小写,而且可以使用方括号语法访问
// 例如: response.headers['content-type']
headers: {},
// request 是生成此响应的请求
// 在 node.js 中它是最后一个 ClientRequest 实例 (in redirects),
// 在浏览器中则是 XMLHttpRequest 实例
request: {},
// status 来自服务器响应的 HTTP 状态码
status: 200,
// statusText 来自服务器响应的 HTTP 状态信息
statusText: 'OK'
}
当使用 then 时,可以接收如下响应:
axios.get('/api/cart')
.then(function (response) {
console.log(response.config);
console.log(response.data);
console.log(response.headers);
console.log(response.status);
console.log(response.statusText);
});
拦截器
基本用法
在发送请求前/接收请求数据后若要进行一些处理,则可以使用 axios 提供的拦截器实现,分别对应请求拦截器 (发送请求前执行) 与响应拦截器 (响应数据前执行)。
// 添加请求拦截器(发送请求前执行)
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器(响应数据前执行)
axios.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
return response;
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error);
});
如果你稍后需要移除拦截器,可以这样:
const myInterceptor = axios.interceptors.request.use(function () {/*...*/});
axios.interceptors.request.eject(myInterceptor);
axios 拦截器 + Element UI 实现 Loading 加载效果
// 通过axios拦截器增添Loading加载效果!
let loadingInstance = null
axios.interceptors.request.use((config) => {
// 发送请求后且返回数据前, 页面会一直处于加载状态
loadingInstance = Loading.service({ fullscreen: true, text: '加载数据中, 请稍等..' })
return config
}, (error) => {
return Promise.reject(error)
})
axios.interceptors.response.use((response) => {
// 关闭加载页面的效果
loadingInstance.close()
return response
}, (error) => {
return Promise.reject(error)
})
演示效果:
关于 axios 的内容,这里仅推荐一份文档:
- Axios 中文文档
- 前者文档的 GitHub 阅读地址:github.com/axios/axios
Element UI
Element UI:一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的 PC 端组件库。
安装
> npm i element-ui -S
引入
在 main.js 中写入以下内容:
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';
Vue.use(ElementUI);
new Vue({
el: '#app',
render: h => h(App)
});
使用
<el-tag>标签一</el-tag>
<el-tag type="success">标签二</el-tag>
<el-tag type="info">标签三</el-tag>
<el-tag type="warning">标签四</el-tag>
<el-tag type="danger">标签五</el-tag>
🚀类似的组件库还有:
Echarts
Apache ECharts:一个基于 JavaScript 的开源可视化图表库。
安装
> npm install echarts --save
引入
import Vue from 'vue'
import App from './App.vue'
import * as echarts from 'echarts'
Vue.prototype.$echarts = echarts
new Vue({
render: h => h(App),
}).$mount('#app')
使用
🪁根据文档修改
setOption以修改图形
<template>
<div>
<!-- 一定要设置宽高才能显示图形 -->
<div id="echart" ref="echart"></div>
</div>
</template>
<script>
export default {
methods: {
initEchart() {
// 实例化echarts对象
var myChart = this.$echarts.init(this.$refs.echart)
// 绘制图表
myChart.setOption({
title: {
text: 'ECharts 入门示例'
},
tooltip: {},
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
},
yAxis: {},
series: [
{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}
]
});
}
},
mounted() {
this.initEchart()
},
}
</script>
<style lang="less" scoped>
#echart {
width: 450px;
height: 300px;
}
</style>
❤️/ END / 如果本文对你有帮助,点个「赞」支持下吧。