小知识,大挑战!本文正在参与“ 程序员必备小知识 ”创作活动
本文同时参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金
前言
佛祖保佑, 永无bug
。Hello 大家好!我是海的对岸!
快速搭建vue项目 文档传送门
我自己也写了一篇文章,新建vue项目
,还包括创建vite vue3项目
,vite react项目
【vite vue react】创建项目
关于快速新建vue项目网上教程很多,我就不多此一举,我这里主要讲vue项目新建之后,往里面引入第三方插件的引入方式及使用方式
快速创建项目(快速带过)
用vscode
打开创建的项目 执行yarn serve
引入element-ui
element-ui传送门
安装
yarn add element-ui
引入,我们使用按需引用
- 借助 babel-plugin-component,我们可以只引入需要的组件,以达到减小项目体积的目的。
yarn add babel-plugin-component -D
使用带有 -D
后缀命令,可以将依赖安装到 package.json
的 devDependencies
下
- 按照element-ui的官方文档,来做
按需引入
,
- lib/element/index.js 文件内容如下
import "element-ui/lib/theme-chalk/index.css";
import {
Pagination,
Dialog,
Autocomplete,
Dropdown,
DropdownMenu,
DropdownItem,
Menu,
Submenu,
MenuItem,
MenuItemGroup,
Input,
InputNumber,
Radio,
RadioGroup,
RadioButton,
Checkbox,
CheckboxButton,
CheckboxGroup,
Switch,
Select,
Option,
OptionGroup,
Button,
ButtonGroup,
Table,
TableColumn,
DatePicker,
TimeSelect,
TimePicker,
Popover,
Tooltip,
Breadcrumb,
BreadcrumbItem,
Form,
FormItem,
Tabs,
TabPane,
Tag,
Tree,
Alert,
Slider,
Icon,
Row,
Col,
Upload,
Progress,
Spinner,
Badge,
Card,
Rate,
Steps,
Step,
Carousel,
CarouselItem,
Collapse,
CollapseItem,
Cascader,
ColorPicker,
Transfer,
Container,
Header,
Aside,
Main,
Footer,
Timeline,
TimelineItem,
Link,
Divider,
Image,
Calendar,
Backtop,
PageHeader,
CascaderPanel,
Loading,
MessageBox,
Message,
Notification,
} from 'element-ui';
export default (Vue) => {
Vue.use(Pagination);
Vue.use(Dialog);
Vue.use(Autocomplete);
Vue.use(Dropdown);
Vue.use(DropdownMenu);
Vue.use(DropdownItem);
Vue.use(Menu);
Vue.use(Submenu);
Vue.use(MenuItem);
Vue.use(MenuItemGroup);
Vue.use(Input);
Vue.use(InputNumber);
Vue.use(Radio);
Vue.use(RadioGroup);
Vue.use(RadioButton);
Vue.use(Checkbox);
Vue.use(CheckboxButton);
Vue.use(CheckboxGroup);
Vue.use(Switch);
Vue.use(Select);
Vue.use(Option);
Vue.use(OptionGroup);
Vue.use(Button);
Vue.use(ButtonGroup);
Vue.use(Table);
Vue.use(TableColumn);
Vue.use(DatePicker);
Vue.use(TimeSelect);
Vue.use(TimePicker);
Vue.use(Popover);
Vue.use(Tooltip);
Vue.use(Breadcrumb);
Vue.use(BreadcrumbItem);
Vue.use(Form);
Vue.use(FormItem);
Vue.use(Tabs);
Vue.use(TabPane);
Vue.use(Tag);
Vue.use(Tree);
Vue.use(Alert);
Vue.use(Slider);
Vue.use(Icon);
Vue.use(Row);
Vue.use(Col);
Vue.use(Upload);
Vue.use(Progress);
Vue.use(Spinner);
Vue.use(Badge);
Vue.use(Card);
Vue.use(Rate);
Vue.use(Steps);
Vue.use(Step);
Vue.use(Carousel);
Vue.use(CarouselItem);
Vue.use(Collapse);
Vue.use(CollapseItem);
Vue.use(Cascader);
Vue.use(ColorPicker);
Vue.use(Transfer);
Vue.use(Container);
Vue.use(Header);
Vue.use(Aside);
Vue.use(Main);
Vue.use(Footer);
Vue.use(Timeline);
Vue.use(TimelineItem);
Vue.use(Link);
Vue.use(Divider);
Vue.use(Image);
Vue.use(Calendar);
Vue.use(Backtop);
Vue.use(PageHeader);
Vue.use(CascaderPanel);
Vue.use(Loading.directive);
Vue.prototype.$loading = Loading.service;
Vue.prototype.$msgbox = MessageBox;
Vue.prototype.$alert = MessageBox.alert;
Vue.prototype.$confirm = MessageBox.confirm;
Vue.prototype.$prompt = MessageBox.prompt;
Vue.prototype.$notify = Notification;
Vue.prototype.$message = Message;
};
- 把这个
element插件
引入到main.js
中
- 将
helloworld.vue
原本的内容删掉,放一个element
的button
看看有没有成功
<template>
<div class="hello">
<el-button>112233</el-button>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: String,
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
</style>
引入axios
安装
npm install axios --save
或
yarn add axios
还要安装一个 qs
yarn add qs
实现 接口统一管理
使用axios,封装axios,实现 接口统一管理 步骤:
- 在
src/lib/
下新建apis
文件夹,文件夹里限价index.js
,封装axios
, - 在
main.js
中 引入, - 在各个子模块中调用
vue.config.js
配置
http.js
import axios from "axios";
// 创建 axios 实例
const requests = axios.create({
// 这里我没有设置basURL,我是在vue.config.js 中的 devServer中的 host:localhost 上访问的
// 如果要打包部署的话,用nginx 代理好一个端口,再进行接口的调整
// baseURL: process.env.VUE_APP_API, // 基础url,如果是多环境配置这样写,也可以像下面一行的写死。
// baseURL: 'http://168.192.0.123’,
// 如果设置了代理,那你本地开发环境的axios的baseUrl要写为'',即空字符串
baseURL: "",
timeout: 6000, // 请求超时时间
});
// request interceptor(请求拦截器)
requests.interceptors.request.use((config) => {
// 实际使用时,设置的token 验证
// const token = localStorage.getItem('token');
// if (token) {
// config.headers['token'] = token; // 让每个请求携带自定义 token 请根据实际情况自行修改
// }
return config;
}, err);
// response interceptor(接收响应拦截器)
requests.interceptors.response.use((response) => {
// debugger
const res = response.data;
if (res.code !== 0 && res.code !== 200) {
this.$notify.error({
title: "错误",
message: res.message || res.msg,
});
// 401:未登录;
if (res.code === 401 || res.code === 403) {
this.$notify.error({
title: "错误",
message: "请登录",
});
}
return Promise.reject("error");
} else {
return res;
}
}, err);
// 错误处理函数
const err = (error) => {
if (error.response) {
const data = error.response.data;
if (error.response.status === 403) {
this.$notify.error({
title: "错误",
message: data.message || data.msg,
});
}
if (error.response.status === 401) {
this.$notify.error({
title: "错误",
message: "你没有权限。",
});
// if (token) {
// store.dispatch('Logout').then(() => {
// setTimeout(() => {
// window.location.reload()
// }, 1500);
// });
// }
}
}
return Promise.reject(error);
};
export default requests;
// 这里的提示消息 实际看你选用哪个UI框架
// 比如你使用 vant框架,可以用 Notify
// 这里面的 Notify 指的是前端vant框架里面的弹框组件,这里你可以按你自己的实际需求来决定选择提示框
// 比如你使用 element-ui框架,可以用 notify
// 本次 http.js 中用到的就是 element-ui框架的notify
index.js
import requests from "./http";
import qs from "qs";
// 接口文件呢,post请求参数名为data,get请求参数名为params
// qs主要有两个方法:
// 方法一:将对象序列化,多个对象之间用&拼接(拼接是由底层处理,无需手动操作)
// qs.stringify(); // 转换成查询字符串 将对象 序列化成URL的形式,以&进行拼接
let comments = { name: "hehe", age: 10 };
console.log("111", comments);
let comValue = qs.stringify(comments); // 'name=hehe&age=10'
console.log("222", comValue);
console.log("333", JSON.stringify(comments)); // '{"name":"hehe","age":10}'
// 方法二:将序列化的内容拆分成一个个单一的对象
// qs.parse(); // 转换成json对象
let comValue2 = qs.parse(comValue);
console.log("444", comValue2);
// 111 {name: 'hehe', age: 10}
// 222 name=hehe&age=10
// 333 {"name":"hehe","age":10}
// 444 {name: 'hehe', age: '10'}
const getTestData = () => {
return requests({
url: "/DemoData/pointList.json",
method: "get",
});
};
const apiMethods = {
// 具体调用的方法名称
getTestData,
// 其他的详细接口,可以接着往下写
// ...
};
// 直接导出整个api对象,需要用哪个detailMethod,就 apiMethods.detailMethod
export default apiMethods;
在src/main.js
中 全局引入 封装的axios
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
...
// 引入封装的axios
import apiMethods from "./lib/apis";
...
// 使用处理好的axios
Vue.prototype.$apiMethods = apiMethods;
new Vue({
router,
store,
render: (h) => h(App),
}).$mount("#app");
在public/DemoData
下,新建一个pointList.json
文件
{
"success": true,
"code": 200,
"msg": "操作成功",
"count": 6,
"data": [
{
"pointCode": "111",
"pointName": "点位1"
},
{
"pointCode": "222",
"pointName": "点位2"
}
]
}
这里需要注意一下
在子组件中引用axios
引入echarts
安装
yarn add echarts vue-echarts
注意,很多帖子说的就直接安装vue-echarts,而事实上仅仅安装vue-echarts新版本并不适用,一定要同时安装echarts
插曲 项目跑起来报错(解决过程)
解决这个问题,这里有个小插曲(回头看,这个问题其实挺狗血的,就是看错了,但是也解决了,解决过程就比较硬核)
插曲解决过程看这里:传送门
解决完之后,就正常了
老规矩,在lib
文件夹内创建一个echarts
文件夹,
index.js
中的内容如下:
import echarts from 'echarts';
import Echart from 'vue-echarts';
export default(Vue) => {
Vue.prototype.$echarts = echarts;
Vue.component('Echart', Echart);
};
在main.js
中引入
...
// 引入 echarts
import echarts from './libs/echarts';
...
Vue.use(echarts);
...
在HelloWorld.vue
中 添加一个echarts
图表看看
<template>
<div class="hello">
<el-button>112233</el-button>
<div style="width: 95%; height: 170px; border: 1px solid">
<Echart :options="echartObj" :autoResize="true" style="width: 100%; height: 100%"/>
</div>
</div>
</template>
<script>
import echart from "vue-echarts";
export default {
name: "HelloWorld",
props: {
msg: String,
},
data() {
return {
echartObj: {},
};
},
methods: {
loadEcharts() {
const XData = [
"2019-07-01 00:00:00",
"2019-07-01 00:01:00",
"2019-07-01 00:02:00",
"2019-07-01 00:03:00",
"2019-07-01 00:04:00",
"2019-07-01 00:05:00",
"2019-07-01 00:06:00",
"2019-07-01 00:07:00",
"2019-07-01 00:08:00",
"2019-07-01 00:09:00",
"2019-07-01 00:10:00",
"2019-07-01 00:11:00",
"2019-07-01 00:12:00",
"2019-07-01 00:13:00",
"2019-07-01 00:14:00",
"2019-07-01 00:15:00",
"2019-07-01 00:16:00",
"2019-07-01 00:17:00",
"2019-07-01 00:18:00",
"2019-07-01 00:19:00",
"2019-07-01 00:20:00",
"2019-07-01 00:21:00",
"2019-07-01 00:22:00",
"2019-07-01 00:23:00",
];
const YData = [
"1.3",
"1.2",
"1.0",
"1.1",
"1.3",
"0.8",
"0.9",
"0.9",
"1.3",
"1.3",
"1.2",
"1.0",
"1.1",
"1.3",
"0.8",
"0.9",
"0.9",
"1.3",
"1.1",
"1.3",
"0.8",
"0.9",
"0.9",
"1.3",
];
this.echartObj = {
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
label: {
backgroundColor: "#6a7985",
},
},
},
grid: {
top: "6%",
left: "6%",
right: "6%",
bottom: "3%",
containLabel: true,
},
xAxis: {
type: "category",
data: XData,
axisLabel: {
// 坐标轴刻度标签的相关设置。
formatter(params) {
let newParamsName = ""; // 最终拼接成的字符串
const paramsNameNumber = params.length; // 实际标签的个数
const provideNumber = 10; // 每行能显示的字的个数
const rowNumber = Math.ceil(paramsNameNumber / provideNumber); // 换行的话,需要显示几行,向上取整
/**
* 判断标签的个数是否大于规定的个数, 如果大于,则进行换行处理 如果不大于,即等于或小于,就返回原标签
*/
// 条件等同于rowNumber>1
if (paramsNameNumber > provideNumber) {
/** 循环每一行,p表示行 */
// eslint-disable-next-line no-plusplus
for (let p = 0; p < rowNumber; p++) {
let tempStr = ""; // 表示每一次截取的字符串
const start = p * provideNumber; // 开始截取的位置
const end = start + provideNumber; // 结束截取的位置
// 此处特殊处理最后一行的索引值
if (p === rowNumber - 1) {
// 最后一次不换行
tempStr = params.substring(start, paramsNameNumber);
} else {
// 每一次拼接字符串并换行
tempStr = `${params.substring(start, end)}\n`;
}
newParamsName += tempStr; // 最终拼成的字符串
}
} else {
// 将旧标签的值赋给新标签
newParamsName = params;
}
// 将最终的字符串返回
return newParamsName;
},
},
},
yAxis: {
type: "value",
},
series: [
{
data: YData,
type: "line",
smooth: true, // true: 折线变成曲线
itemStyle: { normal: { color: "#47a6ff" } },
areaStyle: {
normal: {
color: new echart.graphic.LinearGradient(0, 0, 0, 1, [
// 这里用到了echart
{
offset: 0,
color: "#47a6ff",
},
{
offset: 1,
color: "#fff",
},
]),
},
},
},
],
};
},
},
mounted() {
this.loadEcharts();
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
</style>
结果报错
百度了一下,说:
echarts如果是在5.0版本会报以上错误; 原因是因为graphic对象下没有LinearGradient方法; 可以通过降低版本解决:
yarn add echarts@4.8.0
重新降低版本安装之后
又报错,说要安装个 echarts/core
,我记得以前没让我安装这个玩意啊,纳尼??
那安装下吧
yarn add echarts/core
结果没找到包,奇怪,我去翻了下以前用vue-echarts的项目,我以前用的时候,也没用到echarts/core,但是图表也能出来
以前用的vue-echarts是 5版本的稳定版
yarn add vue-echarts@5.0.0-beta.0
看看页面,唉,页面又报错了
排查了一下,本以为是少了一个组件没有安装
后来发现,是xAxis
属性这里,少写了一个字母,拼错了
大家还是要细心细心再细心
效果如下:
引入vue-lottie
先简单介绍下vue-lootie
什么是Lottie
Lottie是一个可以通过bodymovin插件来解析Adobe After Effects动画,并生成json格式的文件。该json文件可以通过Lottie开源库在iOS,Android,macOS,React Native中进行解析生成动画效果。
为什么使用Lottie
一直以来我们的设计同学都是使用设计软件,设计动画效果,开发同学再通过代码来实现动效。对于复杂的动画,开发同学要用很长的时间来实现,并且还有可能无法达到设计同学的最初的效果。
还有一种实现动画的方式就是gif图。然而Android并不支持gif图,而且gif图对于移动端还有占用过多空间的问题。
那么,Lottie为我们做了什么呢。
首先,设计同学在Adobe After Effects上设计了动画效果,通过bodymovin插件,可以将动画导出成一个json文件。
然后,开发同学就可以通过Lottie将前面生成的json文件渲染成动画效果。
这样就可以高效的实现很多复杂动画效果啦。
安装
yarn add vue-lottie
和之前一样,将这个第三方插件 放在之前创建的 libs
文件夹内
如此便引入了vue-lottie
引入vue-amap
安装
npm install vue-amap --save
或
yarn add vue-amap
在lib
文件夹下新建一个VueAMap
文件夹
(注意
:因为我有时会在两台电脑上写文章,而这2台电脑上的Vue项目
对于lib
文件夹命名没有统一,一台电脑上命名是lib
,另一台电脑上是libs
,所以你们看到截图里出现libs
不要惊讶,语言文字我会统一使用lib
,大家注意一下)
index.js
内容如下:
import VueAMap from 'vue-amap';
VueAMap.initAMapApiLoader({
key: '', // 这里的key 需要去高德地图开发者平台上注册账号,申请开发者,获取key
plugin: [
'AMap.Autocomplete', // 输入提示插件
'AMap.PlaceSearch', // POI搜索插件
'AMap.Scale', // 右下角缩略图插件 比例尺
'AMap.OverView', // 地图鹰眼插件
'AMap.ToolBar', // 地图工具条
'AMap.MapType', // 类别切换控件,实现默认图层与卫星图、实施交通图层之间切换的控制
'AMap.PolyEditor', // 编辑 折线多,边形
'AMap.CircleEditor' // 圆形编辑器插件
],
// 默认高德 sdk 版本为 1.4.4
v: '1.4.15',
uiVersion: '1.0.11' // 引入高德 UI 组件库 版本号
});
export default(Vue) => {
Vue.component('VueAMap', VueAMap);
};
高德地图开发者平台,传送门
main.js
中代码如下
如此,Vue版
的高德地图
便引入进来了
引入nprogress
有时候,我们会看到,网站在跳转的时候,网页内容的正上方会有一个进度条一样的东西,这个进度条走完了,页面也跳转完了
效果就像微信公众上的跳转一样 ( 因为网络不给力,所以跳转完了,还是没内容出来,见笑了哈 )
1. 安装 nprogress
npm install --save nprogress 或者
或
yarn add nprogress
2. 用法
NProgress.start();
NProgress.done();
3.项目中引用
在lib文件夹
内,新建nprogress
文件夹
index.js
代码如下:
/*
* @Author: your name
* @Date: 2021-11-01 09:14:39
* @LastEditTime: 2021-11-01 09:17:11
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \hello-world\src\libs\nprogress\index.js
*/
//导入
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
const start = () => {
NProgress.start()
}
const done = () => {
NProgress.done()
}
export default {
start,
done,
}
4. router.js中调用
router.js
代码如下:
/*
* @Author: your name
* @Date: 2021-07-15 09:44:34
* @LastEditTime: 2021-11-01 09:22:43
* @LastEditors: your name
* @Description: In User Settings Edit
* @FilePath: \hello-world\src\router\index.js
*/
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import NProgress from '../libs/nprogress'
Vue.use(VueRouter)
const routes = [
{
path: '/Home',
name: 'Home',
component: Home
},
{
path: '/About',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
...
]
const router = new VueRouter({
routes
})
router.beforeEach((to, from, next) => {
NProgress.start()
next()
})
router.afterEach(() => {
NProgress.done()
})
export default router
完工
引入jquery
安装
yarn add jquery
lib
文件夹内新建jquery
文件夹
index.js
代码如下:
import $ from 'jquery';
export default(Vue) => {
Vue.prototype.$ = $;
};
在main.js
中引用
...
import jquery from './libs/jquery';
...
Vue.use(jquery);
...
在实际代码组件中使用
<template>
<div>
<div>
<div id="ddd">123</div>
</div>
</div>
</template>
<script>
export default {
name: 'test',
methods: {
test() {
this.$("#ddd").css({ backgroundColor: "red" });
}
},
mounted() {
this.test();
},
}
</script>
<style scoped>
</style>
引入cesium
因为cesium
我写了一个系列,vue安装cesium,我放在了这个系列里面,需要安装的话,看我的这篇文章【vue-cesium】在vue上使用cesium开发三维地图(二)
引入highcharts
highcharts
和highcharts-vue
专门写了一篇文章,请移步:【vue自定义组件】实现3d饼图组件
评论抽奖
欢迎在评论区讨论,掘金官方将在掘力星计划活动结束后,在评论区抽送100份掘金周边
- 抽奖礼物:100份,掘金官方提供,包括掘金徽章、拖鞋、马克杯、帆布袋等,随机发放
- 抽奖时间:「掘力星计划」活动结束后,预计3个工作日内,官方将在所有符合规则的活动文章评论区抽出
- 抽奖方式:掘金官方随机抽奖+人工核实
- 评论内容:与文章内容相关的评论、建议、讨论等,「踩踩」「学习了」等泛泛类的评论无法获奖
都看到这里了,求各位观众大佬们点个赞再走吧,你的赞对我非常重要