项目总结:
1、给数组中添加新属性
this.list.map(item => {
this.$set(item,'属性名',属性值)
})
//同时添加多个,并能监测更新
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
2、vue打包注意事项
vue项目打包时,需要结合后台给的链接地址,设置好图片、css 、 js的路径,避免打包后页面请求不到,在config文件夹中index.js中设置build对象下的属性及属性值。
3、数据渲染页面
最开始渲染页面时,首先判断数据是否存在,存在在继续执行各个逻辑方法,否则会报错。
4、项目打包流程
首先看README.md文档,一般都会写------在查看package.json 文件scripts属性下的build属性值,然后打包
5、验证码倒计时:
A:首先在api中引入某个常量:
export const RESET_TIME = 60 // 验证码延迟时间
B:然后页面中引入该常量 :
import { RESET_TIME } from '@/api/login/index'
C:然后在script标签对中的data(){return{}}中设置变量及变量值
countDown: false, // 倒计时
restTime: RESET_TIME, // 重置时间
timer: null,
D:最后在获取验证码方法中调用:
getCode(){
// 验证手机号
const regPhone = /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/;
if (this.phone == null || this.phone.replace(/(^\s*)|(\s*$)/g, "") == "") {
this.errorTpye = 1
this.tipText = '请输入手机号'
return
}else if(!regPhone.test(this.phone)){
this.errorTpye = 1
this.tipText = '请输入正确手机号'
return
}
let phone = this.phone;
let self = this;
getCodeAPI({phone:phone}).then(res=>{
if(res.data.code == 0){
this.countDown = true;
this.$message.success(res.data.data.msg);
let timer = setInterval(() => {
if (self.restTime == 0) {
this.countDown = false;
clearInterval(timer);
self.restTime = RESET_TIME;
return;
} else {
self.restTime--;
}
}, 1000);
}else{
this.$message.error(res.data.msg);
}
})
},
6、替换favicon.ico浏览器标题小图标:
第一种方式:
首先:设计好设计图,然后在线上生成工具生成一下;
然后:找到项目的根目录 index.html,点进去就能设置title标题和小图标了
然后:如果需要在标题旁边加入自定义的图标,需要把自己的图片
放在static目录下(不要放在src目录下,浏览器会找不到)
将favicon.ico的图标文件放到static文件夹内,
在index.html的head中添加:
<link rel="icon" type="image/x-icon" href="static/favicon.ico">
保存并刷新浏览器,看浏览器图标已经正确设置上了。
最后:重启一下项目就可以了
还有第二种方式:
(1)、在项目index.html同级目录下添加favicon.ico文件
(2)、在项目index.html中引入
<link rel="icon" type="image/x-icon" href="static/favicon.ico">
第三种方式:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-08NgFvPx-1615774192077)(62C8A9D319274598AEBC5A075DDE2F50)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C3QaNgIo-1615774192087)(2968BF0307EA47679FEB0C139EF4EBDA)]
查看build的文件夹下:build/webpack.dev.conf.js中。(到这个步骤之前我的是出现了,并且正常显示,如果不显示,则配置一下吧。)
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true,
// favicon图标(这里需要图标的路径与页面中的路径一样)
// favicon: 'static/bitbug_favicon.ico'
// favicon: path.resolve('static/bitbug_favicon.ico')
favicon:'static/bitbug_favicon.ico'
}),
到这个时候,页面的favicon已经可以正常显示了。(重新运行项目)
7、Vue中post传值问题
(1)、vue中,采用post向后台传值时,如果是单个值时,直接传值即可,不需要以对象的形式传过去,只有要求为对象格式,才传对象。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3c5C89bz-1615774192088)(69EAC99043054E4193A183245A139313)]
这种情况传参形式为API({addressId:addressId,buyType:buyType…})
(2)、[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bO49jR52-1615774192089)(BB1F651F83C5463195E0C9BB93EEEBFE)]
这种情况传参形式为API(526) 即可
(3)、post传值时,如果要求传入的不是对象的形式,而是拼接的形式,则要具体传值
条件:post传值 —拼接形式
要求:
http://192.168.2.32:8080/v1/time_apply_member/login?name=duan&pass=123456
传值:
controllerLoginAPI({name:name,pass:pass}).then((res) => {
console.log(res.data,'33333333333333')
})
接口api设置:
export function controllerLoginAPI(data) {
return request({
url: `${requestPath.v1}/time_apply_member/login?name=${data.name}&pass=${data.pass}`,
method: 'post'
})
}
8、vuex的简单应用 :
网址链接:https://www.cnblogs.com/sunnysnowy/p/12395543.html
应用场景及基础属性:
(一)、使用Vuex的目的
实现多组件状态管理。多个组件之间需要数据共享时,Vuex是个很好的帮手哦
(二)、Vuex 的五大核心
1、其中state和mutation是必须的,其他可根据需求来加
state :负责状态管理,类似于vue中的data,用于初始化数据
mutation :专用于修改state中的数据,通过commit触发
action :可以处理异步,通过dispatch触发,不能直接修改state,首先在组件中通过dispatch触发action,然后在action函数内部commit触发mutation,通过mutation修改state状态值
getter :Vuex中的计算属性,相当于vue中的computed,依赖于state状态值,状态值一旦改变,getter会重新计算,也就是说,当一个数据依赖于另一个数据发生变化时,就要使用getter
module :模块化管理
2、实际应用:
(1).首先安装vuex :
npm install vuex
(2).引入并使用Vuex:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
(3).实例化一个Vuex对象–Store状态机 并抛出
const store = new Vuex.Store({})
export defaul store
(4).在main.js中引入并注入Vuex
import Vue from 'vue'
import App from './App.vue'
import store from './store'
new Vue({
render: h => h(App),
store
}).$mount('#app')
(5).通过this.$store访问Vuex的数据。到此,Vuex已准备完成,接下来就根据自己需要加入数据吧~
3、应用代码:
(1).首先准备至少两个组件,不然怎么数据共享呢
<template><div>我是组件1</div></template>
<script>
export default {}
</script>
<style scoped></style>
<template><div>我是组件2</div></template>
<script>
export default {}
</script>
<style scoped></style>
(2).在store.js中写Vuex相关代码
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {}, //状态管理
mutations: {}, //修改state
actions: {}, //异步操作
getters:{}, //计算属性
modules: {} //模块
})
export default store
注:别忘了在main.js里注入store呀(参考上面第三大点的第4小点)
(3).假设咱们现在需要共享一个数据data,初始值为0
const store = new Vuex.Store({
state: {
data:0
}
})
(4).组件1和组件2都可以通过$store拿到data
<div>我是组件1{{this.$store.state.data}} //浏览器中此处会显示data的值</div>
<div>我是组件2{{this.$store.state.data}} //浏览器中此处会显示data的值</div>
(5).那么怎么修改data呢,这时候就需要mutation出马了
mutation实质是一个函数,接收state和调用时传来的params参数
mutations: {
changeDataMut(state,params){
state.data = params
}
}
(6).mutation有了,接下来就需要在组件中调用它,记得要用commit触发
<template><div>我是组件1<button @click='changeData'>改数据</button></div></template>
<script>
export default {
data(){
return {
changeData(){
// 通过commit 触发 mutation 并传参
this.$store.commit('changeDataMut',10)
//此时组件1和组件2中data都是10啦
}
}
}
}
</script>
(7).action怎么用?
action也是函数。
前面已经说到,action不能直接修改state,首先要在组件中通过dispatch触发action,然后在action函数内部commit触发mutation,通过mutation修改state状态值。
注意action的参数
actions: {
changeDataAct(context,params){
//context是一个对象,从它里面把咱们需要的commit方法解构出来
let {commit} = context
commit('changeDataMut',params)
}
}
这时候可以在组件中触发action了,注意使用dispatch
<template><div>我是组件2<button @click='changeData'>改数据</button></div></template>
<script>
export default {
data(){
return {
changeData(){
// 通过dispatch 触发 action 并传参
this.$store.dispatch('changeDataAct',100)
//此时data就变成100啦,并且组件1和组件2是同步的
}
}
}
}
(8).getter的用法
getter 计算属性 ,依赖于state值,需要return
现在咱们假设一个值double,它是data的两倍,并且会随着data发生改变
getters:{
doubleGet(state){
return state.data*2
}
}
我们可以在组件中使用它了
<div>我是组件2{{this.$store.getters.doubleGet}}</div>
4、dispatch实际应用:
(1)在.vue文件中:
// 账号登录
accountLogin() {
let md5Data = Object.assign({}, this.accountLoginForm);
md5Data.password = md5(md5Data.password);
this.$store.dispatch('AccountLogin', {...md5Data})
.then(res => {
if (res.code == 0) {
this.loginCallBack(res);
} else {……}
})
},
(2)在api xxx.js文件中:
import { accountLogin } from '@/api/login'
const user = {
state: {
token: getToken(),
user: '',
userVip: '',
},
mutations: {
SET_TOKEN: (state, token) => {
state.token = token
},
……
},
actions: {
// 账户登录
AccountLogin({ commit }, params) {
return new Promise((resolve, reject) => {
accountLogin(params).then(response => {
const resData = response.data;
if (resData.code === 0) {
const { token, vip } = resData.data
commit('SET_TOKEN', token)
commit('SET_USER', resData)
commit('SET_USER_VIP', vip)
setToken(token)
setUserToken(resData)
setUserVipToken(vip)
}
resolve(resData) --成功返回
}).catch(error => {
reject(error) ---失败返回
})
})
},
}
export default user
9、验证表单提交
有验证规则时,最后保存提交时,首先要判断验证规则是否全部符合条件,全部符合时才可以保存成功
(1)、首先一般都是form表单进行验证,所以代码中:
<el-form
:rules="rules"
ref="dataForm"
:model="temp"
label-position="right"
label-width="120px"
width="400">
<el-form-item label="VIP会员类型:" prop="name">
<el-input v-model="temp.name" placeholder="请输入VIP"></el-input>
</el-form-item>
<el-form-item label="有效期:" prop="time">
<el-select v-model="temp.time" style="width:300px;">
<el-option v-for="(item,index) in periodList"
:key="item" :label="index" :value="item"></el-option>
</el-select>
</el-form-item>
</el-form>
(2)、在数据data中添加验证规则:
rules: {
name:[{type:'string',trigger: "change",required: true, message:'请输入会员类型'}],
synopsis:[{type:'string',trigger: "change",validator: validateValue}],
realPrice:[{required: true, trigger: "change", validator: validatePrice}],
},
(3)、最后保存时,进行最后验证:
saveVipEditData(){
this.$refs['dataForm'].validate((valid) => {
if(valid){
saveVipEditDataAPI(this.temp).then(res=>{
if(res.data.code == 0){
this.$message.success('保存成功')
this.getList()
this.dialogFormVisible = false
}
})
}
})
}
10、递归树处理空数组
递归树处理,配合vue的vueTreeselect组件使用。当数组有子集,但子集中又没有数据时,可将它删除。
getTree() {
getTreeAPI('医案').then(res => {
if(res.data.code === 0){
if(res.data.data.length>0){
let item = res.data.data;
this.diGuiTree(item);
this.treeSelectOptions = res.data.data[0].list;
}
} else {
this.$message.error('获取数据失败');
}
});
},
diGuiTree(item) { //递归便利树结构
item.forEach(item => {
item.list && item.list.length !=0 ?
this.diGuiTree(item.list) : delete item.list
})
},
}
11、获取当前鼠标位置
export const getMousePos = (event) => {
const e = event || window.event;
const scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
const scrollY = document.documentElement.scrollTop || document.body.scrollTop;
const x = e.pageX || e.clientX + scrollX;
const y = e.pageY || e.clientY + scrollY;
//alert('x: ' + x + '\ny: ' + y);
return { 'x': x, 'y': y };
}
12、获取选中的文本内容
let selectedText;
if (window.getSelection) {
selectedText = window.getSelection().toString();
} else if (document.selection && document.selection.createRange) {
selectedText = document.selection.createRange().text;
}
this.selectedText = selectedText;
13、将时间转换成正常的yy-mm-dd结构的时间
var d = new Date('Sat Feb 01 00:00:00 CST 2014');
var sd = d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate();
14、整个页面背景图固定不动,内容撑开有滚动条css
.boxContent{
width: 100%;
height: 100%;
background-image:url('a4.jpg');
background-size: 100% 100%;
background-repeat:no-repeat;
background-attachment:fixed;
}
15、以原来的项目作为底子,重新建一个新项目的步骤:
(1)、首先在gitLab上随便拉取某个项目
(2)、拉取完成后,重命名
(3)、在gitLab上创建新项目,输入项目名称,可见一般设为私有,点击创建,创建完成
(4)、然后按照已有文件夹的步骤,上传代码到gitLab上,上传之前先把原来的 .git 文件删除
(5)、这样一个独立的项目就创建好了,然后可以创建新的分支,继续各种开发
16、Vue中下载echarts插件,及应用
(1)、首先下载安装echarts依赖
npm install echarts -S
或者使用淘宝的镜像
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install echarts -S
(2)、创建图表
https://www.cnblogs.com/whblogs/p/10510701.html
全局引入:
main.js页面
import echarts from 'echarts'
Vue.prototype.$echarts = echarts
Hello.vue页面
<div id="myChart" :style="{width: '300px', height: '300px'}"></div>
按需引入:
// 引入基本模板
let echarts = require('echarts/lib/echarts')
// 引入柱状图组件
require('echarts/lib/chart/bar')
// 引入提示框和title组件
require('echarts/lib/component/tooltip')
require('echarts/lib/component/title')
export default {
name: 'hello',
data() {
return {
msg: 'Welcome to Your Vue.js App'
}
},
mounted() {
this.drawLine();
},
methods: {
drawLine() {
// 基于准备好的dom,初始化echarts实例
let myChart = echarts.init(document.getElementById('myChart'))
// 绘制图表
myChart.setOption({
title: { text: 'ECharts 入门示例' },
tooltip: {},
xAxis: {
data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]
},
yAxis: {},
series: [{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20]
}]
});
}
}
}
17、sessionStorage 存、取、删除、清空数据方法封装
链接:https://blog.csdn.net/qq_32678401/article/details/106807099
存数据:sessionStorage.setItem(name, saveStr)
取数据:sessionStorage.getItem(name)
删除某项缓存数据:sessionStorage.removeItem(name)
清除本地所有存储数据:sessionStorage.clear()
18、vue中filters过滤器:判断数字是否有小数,并且保留不超过两位小数
filters:{
numberNorm (value) {
if (!value) return ''
let y = String(value).indexOf(".") + 1;//获取小数点的位置
let count = String(value).length - y;//获取小数点后的个数
if(y > 0){
if(count <= 1) {
return value
} else {
return Number(value).toFixed(2)
}
}else{
return value
}
},
},
19、时间格式化
format(time, format) {
var t = new Date(time);
var tf = function (i) { return (i < 10 ? '0' : '') + i };
return format.replace(/yyyy|MM|dd|HH|mm|ss/g, function (a) {
switch (a) {
case 'yyyy':
return tf(t.getFullYear());
break;
case 'MM':
return tf(t.getMonth() + 1);
break;
case 'mm':
return tf(t.getMinutes());
break;
case 'dd':
return tf(t.getDate());
break;
case 'HH':
return tf(t.getHours());
break;
case 'ss':
return tf(t.getSeconds());
break;
}
})
}
//应用:
this.axios.post("personnelface/freq/getfreqstat", {
beginTime: this.format(me.dateValue1,'yyyy-MM-dd'),
endTime: this.format(me.dateValue2,'yyyy-MM-dd'),
..........
})
20、vue 的点击事件获取当前点击的元素
在点击的函数中 添加$event 参数就可以
<button @click = “clickfun($event)”>点击</button>
21、Vue中提交上传文件的数据
//工时申请列表--上传文件 data指当前上传文件点击元素
uploadFiles(data,id){
let file = data.target.files[0]
let formData = new FormData()
formData.append('file',file)
uploadFilesAPI(formData).then((res) => {
if(res.data.code == 0){
uploadPdfAPI({id:id,pdfLable:res.data.data}).then((res1) => {
if(res1.data.code == 0){
this.getapplyHourList()
}
})
}
})
},
22、以本地IP地址访问vue项目
1、若是有config文件,则在config文件夹下的index.js文件中设置host:‘0.0.0.0’,然后重启项目,即可按照本地ip地址访问项目
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {
'/api':{
target:`http://192.168.2.245:2018`,
changeOrigin:true,
pathRewrite:{
'^/api': ''
}
}
},
// Various Dev Server settings
host: '0.0.0.0',
port: 9527,
autoOpenBrowser: true,
errorOverlay: true,
notifyOnErrors: false,
poll: false,
showEslintErrorsInOverlay: false,
},
}
2、若是没有config文件,可以在vue.config.js文件中设置host:‘0.0.0.0’,然后在package.json文件中设置dev或者serve(针对yarn情况下),后面添加 --host 0.0.0.0
"scripts": {
"serve": "vue-cli-service serve --host 0.0.0.0",
"build": "vue-cli-service build",
"serve-prod": "vue-cli-service serve --mode production",
"build-dev": "vue-cli-service build --mode development",
"build-prod": "vue-cli-service build --mode production",
"lint": "vue-cli-service lint"
},
23、Vue中触发滚动条事件:
<script>
export default {
data (){
return{
headNeed:false,
navShow:false,
indexN:null,
indexId:null,
logo:'',
}
},
methods:{
handleScroll() {
let self = this
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
if( scrollTop>40 ){
self.headNeed = true
}else{
self.headNeed = false
}
}
},
mounted(){
//触发滚动条事件
window.addEventListener('scroll', this.handleScroll)
},
destroyed () {
//销毁滚动条事件
window.removeEventListener('scroll', this.handleScroll)
},
}
</script>
24、获取当前年、月、日:
addDate() {
nowDate = new Date();
let date = {
year: nowDate.getFullYear(),
month: nowDate.getMonth() + 1,
date: nowDate.getDate(),
}
console.log(date);
let systemDate = date.year + '-' + 0 + date.month + '-' + 0 + date.date;
}
25、打印出1-10000之间的所有对称数,如121,1331等
[...Array(10000).keys()].filter((x) => {
return x.toString().length > 1 && x === Number(x.toString().split('').reverse().join(''))
})
26、vue项目中,验证重置和验证通过
methods: {
getDetail(){
getDetailAPI(this.id).then(res=>{
if(res.data.code == 0){
this.imgForm = res.data.data;
if(this.imgForm.publishingTime){
this.imgForm.publishingTime = this.imgForm.publishingTime.slice(0,10);
}
//表单验证重置
this.$refs['ruleForm'].resetFields();
}
})
},
/*确认入库*/
dataSubmit(){
//表单验证开始
this.$refs['ruleForm'].validate((valid) => {
if(valid){
updateAPI(
{smallBankCount:this.imgForm.smallBankCount,
id:this.imgForm.id,}
).then(res=>{
if(res.data.status){
this.$message.success('入库成功');
this.$router.push('/newBook/storageRoom');
}else{
this.$message.error(res.data.msg);
}
})
}
})
},
}