日常遇到的问题-vue2

1.js变量后边加空格后边加

+"\xa0\xa0\xa0\xa0"

2.验证写法:

<!-- 电话号 -->
expertPhone:[
	{
		required: true,
		pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
		message: "请输入正确的手机号码",
		trigger: "blur"
	}
		],
// 邮箱
	expertEmai:[
		{required: true, message: "请输入联系人电话", trigger: ["blur", "change"] },
		{
			type: "email",
			message: "请输入正确的邮箱地址",
			trigger: ["blur", "change"]
		}
	],
		// 身份证号码
		corporate: [
          {
            required: true,
            pattern:
              /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/,
            message: "请填写正确的法人身份证号",
            trigger: "blur",
          },
        ],
		// 数字:只校验类型,不是必填
		projectNumber: [
          {
            required: false,
            pattern: /^[0-9]*$/,
            message: "项目编号为数字类型",
            trigger: "blur",
          },
        ],
		// 不是必填,校验大于0且只有一个小数点的数字
		<el-input
              type="text"
              v-model="form.lanBiaoPrice"
              oninput="this.value = this.value.replace(/[^\d.]/g, '').replace(/(\..*)\./g, '$1');"
              placeholder="请输入拦标价(只能输入大于0的数字)"
            ></el-input>

3.父组件调用子组件的方法

<!-- 父组件 -->
<el-button
	type="primary"
	icon="el-icon-plus"
	size="mini"
	@click="handleAdd"
	v-hasPermi="['basicLibrary:extendedMonitoringIndicators:add']"
	>添加</el-button
			 >
					handleAdd() {
						this.$refs.Add1.open();
					},

4.子组件调用父组件的方法

(1)直接在子组件中通过“this.$parent.event”来调用父组件的方法。

<template>
  <div>
    <child></child>
  </div>
</template>
<script>
  import child from './components/childcomponent';
  export default {
    components: {
      child
    },
    methods: {
      fatherMethod() {
        console.log('父组件方法');
      }
    }
  };
</script>
<!-- 子组件 -->
<template>
  <div>
    <button @click="childMethod()">点击按钮</button>
  </div>
</template>
<script>
  export default {
    methods: {
      childMethod() {
        this.$parent.fatherMethod();
      }
    }
  };
</script>

(2)子组件用“$emit”向父组件触发一个事件,父组件监听这个事件即可。

<!-- 父组件 -->
<template>
  <div>
    <child @fatherMethod="fatherMethod"></child>
  </div>
</template>
<script>
  import child from './components/childcomponent'
  export default {
    components: {
      child
    },
    methods: {
      fatherMethod() {
        console.log('父组件方法');
      }
    }
  };
</script>
<!-- 子组件 -->
<template>
  <div>
    <button @click="childMethod()">点击按钮</button>
  </div>
</template>
<script>
  export default {
    methods: {
      childMethod() {
        this.$emit('fatherMethod');
      }
    }
  };
</script>

(3)父组件把方法传入子组件中,在子组件里直接调用这个方法即可

<!-- 父组件 -->
<template>
  <div>
    <child :fatherMethod="fatherMethod"></child>
  </div>
</template>
<script>
  import child from './components/childcomponent';
  export default {
    components: {
      child
    },
    methods: {
      fatherMethod() {
        console.log('父组件方法');
      }
    }
  };
</script>
<!-- 子组件 -->
<template>
  <div>
    <button @click="childMethod()">点击按钮</button>
  </div>
</template>
<script>
  export default {
    props: {
      fatherMethod: {
        type: Function,
        default: null
      }
    },
    methods: {
      childMethod() {
          this.fatherMethod();
        }
      }
    }
  };
</script>

5.!import – 最高优先级

6.路径重写

7.JS中? ?和??=和?.和 ||的区别?

undefined和null是两个比较特殊的数据类型,是不能用点操作符去访问属性的,否则将会报错
?? 与 || 的区别
相同点:
?? 和 || 的用法相同,都是前后是值,中间用符号连接,根据前面的值来判断最终是返回前面的值还是后面的值。
A ?? B
A || B
不同点:
判断的方法不同:
使用 ?? 时,只有A为 null 或者 undefined 时才会返回 B;
使用 || 时,A会先转化为布尔值判断,为true时返回A , false 返回B

// ??
console.log(undefined ?? 2);  // 2
console.log(null ?? 2);   // 2
console.log(0 ?? 2);  // 0
console.log("" ?? 2);   // ''
console.log(true ?? 2);  // true
console.log(false ?? 2);   // false

// ||
console.log(undefined || 2);   // 2
console.log(null || 2);     // 2
console.log(0 || 2);        // 2
console.log("" || 2);     // 2
console.log(true || 2);     // true
console.log(false || 2);      // 2

空值合并操作符 ??
只有当左侧为null 或者undefined 时,才会返回右侧的值
可选链操作符 ?.
?. 允许读取连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。
?. 操作符的功能类似于. 链操作符,不同之处在于,在引用为空,即 null 或者 undefined 的情况下不会引起错误,该表达式短路返回值。
const obj = { a: { b: [{ name: “obj” }] } };

// 原本的写法
console.log(obj && obj.a && obj.a.b.length && obj.a.b[0].name); //obj

// 可选链写法
console.log(obj?.a?.b?.[0]?.name); // obj
console.log(obj?.b?.c?.d); // undefined
空值赋值运算符(??=)
当??=左侧的值为null、undefined的时候,才会将右侧变量的值赋值给左侧变量.其他所有值都不会进行赋值

let a = "你好";

let b = null;
let c = undefined;
let d = 0;
let e = "";
let f = true;
let g = false;

console.log((b ??= a)); // 你好
console.log((c ??= a)); // 你好
console.log((d ??= a)); // 0
console.log((e ??= a)); // ''
console.log((f ??= a)); // true
console.log((g ??= a)); // false

console.log(b); // 你好
console.log(c); // 你好
console.log(d); // 0
console.log(e); // ''
console.log(f); // true
console.log(g); // false

8.请假审批流程?

新增 – 页面 – 功能(提交、修改、下载、重新下载、查看详情)-- 搜索 – 导出(列表内容)
提交之前不出现重新提交,提交之后不出现提交和修改按钮,下载按钮下载的是附件

9.若依系统数据字典的使用?

1. ERP项目

1.1. 在函数中使用this.getDicts()方法
1.2. 在data函数中定义
1.3. 在页面中进行使用 – 固定写法 – 在页面以下拉选的方式展示

this.getDicts("字典类型").then((res) => {
	this.自定义名称 = res.data;
}),

	data(){
		return {
			自定义名称:[]
		}
	}

<el-select  v-model="form.字段"  placeholder="请选择文件类型" >
	<el-option v-for="dict in 自定义名称" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" ></el-option>
</el-select>
// 在表格中的使用
<el-table-column label="行业属性" align="center" prop="hangYeShuXing">
          <template slot-scope="scope">
            <span>
              {{
                replace(
                  infoIndustryeList,
                  "dictValue",
                  "dictLabel",
                  scope.row.hangYeShuXing
                )
              }}
            </span>
          </template>
        </el-table-column>

this.getDicts("info_Industry").then((response) => {
      this.infoIndustryeList = response.data;
    });
替换数字
//替换数组
    replace(dataList, coluem, coluemVal, val) {
      if (dataList.length != 0) {
        for (var i = 0; i < dataList.length; i++) {
          var temp = dataList[i]
          var t = temp[coluem]
          if (t == val) {
            return temp[coluemVal]
          }
        }
      }
    },

2. 其他项目

2.1. 在页面根据后台的返回直接展示
2.1.1. 直接定义
2.1.2. 页面直接使用

export default {
dicts: ["apply_status(给的字段)"],
}

<el-table-column label="审核状态" align="center" prop="processStatus">
<template slot-scope="scope">
	<dict-tag
		:options="dict.type.apply_status"
		:value="scope.row.processStatus"
		/>
</template>
						 </el-table-column>

2.2. 下拉选

dicts: ["leave_type"]
<el-form-item label="状态" prop="leaveType">
	<el-select
		v-model="queryParams.leaveType"
		placeholder="请选择请假类型"
		clearable
		>
		<el-option
			v-for="dict in dict.type.leave_type"
			:key="dict.value"
			:label="dict.label"
			:value="dict.value"
			/>
	</el-select>
</el-form-item>

10.若依按钮权限

需要管理员加权限,添加相应名称,才可以使用

v-hasPermi="['workflowLeave:workflowLeave:remove']"

11.时间字段问题?

情况:后端给了两个字段,前端页面只有一个字段

<!-- 1.在页面自己随便定义一个字段,写一个方法 -->
<el-form-item label="请假时间" prop="Time">
	<el-date-picker
		v-model="form.Time"
		type="daterange"
		style="width: 100%"
		range-separator="至"
		start-placeholder="开始日期"
		end-placeholder="结束日期"
		format="yyyy 年 MM 月 dd 日"
		value-format="yyyy-MM-dd"
		@change="handleDatePicker"
		>
	</el-date-picker>
</el-form-item>

<!-- 2.在方法里边分别获取两个状态 -->
handleDatePicker(e) {
	console.log(e, 99999);
	if (e) {
		this.form.leaveStartTime = e[0];
		this.form.leaveEndTime = e[1];
	}
},
	// 
	this.form.projectStage = `${this.form.projectStage[0]}${this.form.projectStage[1]}`;

	// 时间反显 后端返回来字符串
	 var splitAdd = data.projectStage.split("至");
   this.form.projectStage = [splitAdd[0], splitAdd[1]];

12.头部搜索状态问题?

情况:后端返回来的是0,1,2的状态–数据字典样式,但是页面需要根据汉字查找?
直接将状态根据数据字典写成下拉选的样式

<el-form-item label="状态" prop="leaveType">
	<el-select
		v-model="queryParams.leaveType"
		placeholder="请选择请假类型"
		clearable
		>
		<el-option
			v-for="dict in dict.type.leave_type"
			:key="dict.value"
			:label="dict.label"
			:value="dict.value"
			/>
	</el-select>
</el-form-item>

13.修改文本框内容?

情况:页面文本框和弹出修改页面文本框使用同一个字段,修改页面修改的同时页面会随之改变,不需要调用修改接口,但是这样是错误的?

<!-- 使用深拷贝方式,重新赋值 -->
 this.form = {
		 ...response.data, 
};

14.表单验证trigger属性的区别?

对el-input输入框的验证,trigger的值选blur,即失去焦点时进行验证。
下拉框(el-select)、日期选择器(el-date-picker)、复选框(el-checkbox)、单选框(el-radio)验证时,trigger的值选择change,即当值发生变化时就进行验证。

15.async、await请求发送?

1. async函数:

async用来修饰函数,async函数的返回值为Promise对象、这个promise对象的结果,由async函数执行的返回值决定。
(1)async函数的返回值为普通类型,那么对应的Promise对象的状态为成功。
(2)async函数的返回值为Promise对象,那么返回的Promise对象的状态由这个返回值决定。
(3)async函数通过throw语句抛出异常,那么返回的Promise对象的状态恒定为失败。

2. await

await用于异步请求、修饰一个表达式,用同步代码实现异步编程。
await -> 等await里边的所有执行结束才会进行下一步 – 方同步代码(没必要)/promise对象(只能放promise对象)-- await表达式返回的一般都是值,而非promise对象
(1)若await关键字右侧为Promise对象,那么await表达式返回的就是Promise成功的值;
(2)若await关键字右侧是其它值,那么会直接将此值作为await的返回值。
(3)此外,await表达式必须写在async函数中,否则会报错;如果await关键字右侧promise对象是失败的,那么可以使用try…catch…语句块中进行捕获处理。
async里边代码如果报错,就不会继续向下执行了。
如何在async里边获取错误

try{
	
}.catch(){
	错误代码;
}

16.样式穿透、深度选择器? – v-html解析的标签样式设置

::样式穿透:v-deep
深度选择器:

和 /deep/

17.时间格式化?

<el-table-column

	width="250px"
	label="上传时间"
	prop="reviewerTime"
	align="left"
	>
	<template slot-scope="scope">
		<span>{{ timeConversion(scope.row.reviewerTime) }}</span>
	</template>
</el-table-column>

<!-- timeConversion -->
// 时间转换

export function timeConversion(oldDate, fmt = true) {
  // 方式1 转换为'yyyy-MM-dd HH:mm:ss'
  function add0(num) {
    return num < 10 ? "0" + num : num;
  } // 个位数的值在前面补0
  const date = new Date(oldDate);
  const Y = date.getFullYear();
  const M = date.getMonth() + 1;
  const D = date.getDate();
  const h = date.getHours();
  const m = date.getMinutes();
  const s = date.getSeconds();

  const dateString1 = Y + '-' + add0(M) + '-' + add0(D) + '  ' + add0(h) + ':' + add0(m) + ':' + add0(s)
  const dateString2 = Y + "-" + add0(M) + "-" + add0(D);
  if (fmt) {
    return dateString1;
  } else {
    return dateString2;
  }
}
// 只去月份
export function timeConversionGetMonth(oldDate, fmt) {
  // 方式1 转换为'yyyy-MM-dd HH:mm:ss'
  function add0(num) {
    return num < 10 ? "0" + num : num;
  } // 个位数的值在前面补0
  const date = new Date(oldDate);
  const Y = date.getFullYear();
  const M = date.getMonth() + 1;
  const D = date.getDate();
  const h = date.getHours();
  const m = date.getMinutes();
  const s = date.getSeconds();

  // const dateString = Y + '-' + add0(M) + '-' + add0(D) + '  ' + add0(h) + ':' + add0(m) + ':' + add0(s)
  const dateString = add0(M)

  return dateString;
}

// 表格时间格式化
<el-form-item label="投标时间" prop="tenderTime">
	<el-date-picker
		clearable
		size="small"
		v-model="queryParams.tenderTime"
		type="date"
		value-format="yyyy-MM-dd-ss-ff-mm"
		placeholder="选择投标时间"
		>
	</el-date-picker>
</el-form-item>

18.使用find遍历?

changeSelect(val) {
	let newRow = this.inviteTendersList.find((item) => item.id == val);
	if (newRow) {
		this.form.invitePerson = newRow.customerName;
		this.form.invitePhone = newRow.customerPhone;
		this.form.belongDept = newRow.customerDepartment;
		this.form.biddingSubject = newRow.customerCompany;
	}
}

19.批量下载

// 批量下载
    handleDown() {
      console.log(this.ids)
      this.ids.forEach( items => {
        let newList= this.basicLibList.find(item=>item.id==items)
        console.log(newList,9999)
<!-- 		下载接口 -->
      this.downloadFileBoldName(newList.basicLibName, newList.path);
      });
    },

20.电脑下载git第一次使用流程?

git push -u origin master 远程仓库为空时,直接pull会报错,使用

20.1 使用步骤

21.高度的使用?

高度100%设置:所有父级元素高度100%

22.js中setTimeout和clearTimeout的使用

1、js中可以通过setTimeout函数设置定时器,让指定的代码在指定的时间运动. 如果我们希望在setTimeout之行前终止其运行就可以使用clearTimeout()。
2、clearTimeout()用于重置js定时器,如果你希望阻止setTimeout的运行,就可以使用clearTimeout方法。
(1)clearTimeout和clearInterval()区别?
clearTimeout()取消由setTimeout() 方法设置的 timeout。
clearInterval() ,这个函数只有一个作用,就是暂停setInterval()调用函数

23.多种判断方法?

v-if 和 v-else
使用时需要两个标签,才能完美配合
<el-form-item label="投标预览:">
	<div v-if="fileList.length == 0">暂无可预览文件</div>
	<div
		style="cursor: pointer"
		v-for="item in fileList"
		:key="item.id"
		@click="handleView(item.id)"
		>
			 {{ item.name ? item.name : "暂无可预览文件" }}
			<!-- <span v-if="item.name">{{ item.name }}</span>
				<span v-else>暂无可预览文件</span> -->
	</div>
</el-form-item>
三目运算符?
{{ item.name ? item.name : "暂无可预览文件" }}

24.获取元素?

<el-table-column
	label="状态"
	prop="expertIdcardStatus"
	align="center"
	>
	<template slot-scope="scope">
		{{ scope.row.expertIdcardStatus ? "暂停" : "正常" }}
	</template>
</el-table-column>
<el-form-item label="年度目标:" prop="projectPerformanceTarget">
	{{formData.projectPerformanceTarget}}
</el-form-item>

25.传给后台的状态?

后台没有给,但是给后端只能传0/1
<el-form-item label="机构认证情况:" prop="expertIdcardStatus">
	<el-radio-group v-model="formData.expertIdcardStatus">
		<el-radio label="0">未认证</el-radio>
		<el-radio label="1">已认证</el-radio>
	</el-radio-group>
</el-form-item>

26.直接赋值,视图不会更新?

this.$set(this.form,"joinManPeople",res.data[0].nickName)
	this.$set{元素,"字段",需要渲染的数据}
this.$delete(this.obj, 'propName', val)

27.封装弹框/组件?

<el-button
	type="primary"
	icon="el-icon-plus"
	size="mini"
	@click="handleAdd"
	v-hasPermi="['infoAssetApply:infoAssetApply:add']"
	>新增</el-button>

<!-- 新增/修改弹框 -->
<Add ref="Add" :title="title" @getlist="getList"></Add>

<!--  函数 -->
handleAdd() {
      this.reset();
      this.$refs.Add.open();
      this.title = "添加资产相关审批记录 调拨等";
    },
<!-- 新增 -->
<el-dialog
	:title="title"
	:visible.sync="dialogVisible"
	width="35%"
	append-to-body
	:close-on-click-modal="false"
	>
</el-dialog>

export default{
	data(){
			return {
					dialogVisible:false,
				}
	},
	methods:{
			open(){
					this.dialogVisible = true;
				}
	}
}

	// 修改
	open(row) {
		console.log(row.id, "row.id");
		// 赋值一个给rowData
		this.rowData = row;
		this.dialogVisible = true;
		// 根据有无id判断
		if (row) {
			this.getFirstProjectList(row.id);
		}
	},
	// 查询列表详情
	async getFirstProjectList(id) {
		let res = await getFirstProjectList(id);
		console.log(res, "res");
	},
	// 提交
	submitForm() {
		// 绑定form表单,获取form表单的值
		this.$refs.form.validate((valid) => {
			if (valid) {
				console.log(this.form, "reasonAdjust");
				// 查出来的是带id,点击的这一行的数据
				if (this.rowData) {
					console.log(this.rowData, "this.rowData");
				}
			}
		});
	},
2.透明度区别?
第一种:rgba(0,0,0,0.2);  透明度是不会被继承的,就不用考虑继承问题
第二种:opacity:0.5;  设置opacity属性后它的后代元素会随着一起具有透明度
第三种:filter:50; 
第四种:transparent;   表示全透明黑色

29.点击不同按钮,使用同一个弹框?

(1)新增和修改使用同一个?
同上:封装弹框 --> 都是使用两个按钮调用同一个弹框,但是这个弹框里边只有一个内容,只是一个有数据,一个没有数据
(2)两个完全没有关系的按钮使用同一个弹框?

<template>
  <div>
    <el-dialog
      :title="title"
      :visible.sync="dialogVisible"
      width="30%"
      append-to-body
      :close-on-click-modal="false"
    >
      <!-- 申请调整 -->
      <template v-if="title == '审核'">
        <el-form
          :model="ruleForm"
          status-icon
          :rules="rules"
          ref="ruleForm"
          label-width="100px"
          class="demo-ruleForm"
          style="padding: 0 30px"
        >
          
        </el-form>
      </template>
      <!-- 查看详情 -->
      <template v-else>
        <el-form label-width="100px" :model="form">
          
        </el-form>
      </template>
    </el-dialog>
  </div>
</template>
30.表格套表格?

<template>
	<el-row :gutter="10" class="mb8">
		<right-toolbar :show-search.sync="showSearch" @queryTable="getList" />
		</el-row>

	<el-table
		v-loading="loading"
		:data="projectList"
		@expand-change="expandChange"
		>
		<!-- 展开键 -->
		<el-table-column type="expand">
			<template slot-scope="scope">
				<el-table
					style="width: 95%; margin: auto"
<!-- 子集写法 -->
					:data="scope.row.infoProjectTargetAdjust"
					>
					<el-table-column
						prop="createTime"
						align="center"
						label="申请时间"
						>
					</el-table-column>
				</el-table>
			</template>
									 </el-table-column>

										 <!-- 数据列表 -->
										 <el-table-column
				show-overflow-tooltip
				width="300"
				label="项目名称"
				// 父级写法
				prop="infoBaseProjects.projectName"
					/>

					<el-table-column
				show-overflow-tooltip
				width="300"
				label="建设内容与规模"
				prop="projectMoney"
					</el-table>

					</template>
let { rows } = await getshProjectList(this.queryParams);


	this.projectList = rows.infoBaseProjects;
	getshProjectList(this.queryParams).then((res) => {
		console.log(res.total, res, "res");
		let list = res.rows;
		console.log(list, "list");
		this.projectList = list.map((item) => {
			return {
				isWho: item.isWho,
				...item.infoBaseProjects,
				childrenList: item.infoProjectTargetAdjust,
			});	

31.部署前端项目

1.设置publicPath:process.env.NODE_ENV===“production” ? " ./ : "/ "

32.高级按钮写法?

33.解构赋值

(1)对象解构赋值

(2)数组解构赋值

34.数据插值

this.$set(原始数据,插入数据字段,“插入的数据”)

35.防止图片被挤压变形

object-fit: cover;

36.javascript中的function 函数名(){}与函数名:function(){}?

function 函数名(){} --> 定义一个函数
函数名:function(){}; --> 设置一个对象的方法 --> 简写写法 函数名( ){ }

37.路由的使用?

{
path: 'projectLibrary/indexCopy/:projectIds/:isAddChild',   // path必须是唯一的
	name: 'ManyAddProject', // name也必须是唯一的
		component: () => import('@/views/baseLibrary/projectLibrary/components/addProject/indexCopy'),
		meta: { // 用来记录地址
		activeMenu: '/baseLibrary/projectLibrary'
	}
	},
37.1 二级路由的写法
<!-- 第一种 -->
<!-- 一级路由        二级路由 -->
path:"/index"       path:"/two"
// 第二种
// <!-- 一级路由        二级路由 -->
	path:"index"      path:"/index/two"

38.处理二进制流

第一步:请求接口设置responseType为blob

第二步,在拿到文件流后生成一个URL来是先下载。  传递row.id


封装文件下载方法
// 下载模板
export function downTemplate(query) {
	return request({
		url: '/common/download/downName',
		method: 'get',
		params: query,
		responseType: 'blob'
	})
}

/**
 * 下载文件
 * @param url 文件路径
 * @param fileName 文件名
 * @param parameter
 * @returns {*}
 */
export function downloadFile(path, name) {
	var params = {
		path: path,
		downName: name
	}
	return downTemplate(params).then((data) => {
		if (!data || data.size === 0) {
			alert("文件下载失败")
			return
		}
		if (typeof window.navigator.msSaveBlob !== 'undefined') {
			window.navigator.msSaveBlob(new Blob([data]), name)
		} else {
			let url = window.URL.createObjectURL(new Blob([data]))
			let link = document.createElement('a')
			link.style.display = 'none'
			link.href = url
			link.setAttribute('download', name)
			document.body.appendChild(link)
			link.click()
			document.body.removeChild(link) //下载完成移除元素
			window.URL.revokeObjectURL(url) //释放掉blob对象
		}
	})
}
// 下载模板
export function downTemplate(query) {
  return request({
    url: '/common/download/downName',
    method: 'get',
    params: query,
    responseType: 'blob'
  })
}

/**
 * 下载文件
 * @param url 文件路径
 * @param fileName 文件名
 * @param parameter
 * @returns {*}
 */
export function downloadFile(path, name) {
  var params = {
    path: path,
    downName: name
  }
  return downTemplate(params).then((data) => {
    if (!data || data.size === 0) {
      alert("文件下载失败")
      return
    }
    if (typeof window.navigator.msSaveBlob !== 'undefined') {
      window.navigator.msSaveBlob(new Blob([data]), name)
    } else {
      let url = window.URL.createObjectURL(new Blob([data]))
      let link = document.createElement('a')
      link.style.display = 'none'
      link.href = url
      link.setAttribute('download', name)
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link) //下载完成移除元素
      window.URL.revokeObjectURL(url) //释放掉blob对象
    }
  })
}
/**
 * 通用js方法封装处理
 * Copyright (c) 2019 ruoyi
 */
const baseURL = process.env.VUE_APP_BASE_API
import { getToken } from '@/utils/auth'

// 日期格式化
export function parseTime(time, pattern) {
  if (arguments.length === 0 || !time) {
    return null
  }
  const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
  let date
  if (typeof time === 'object') {
    date = time
  } else {
    if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
      time = parseInt(time)
    } else if (typeof time === 'string') {
      time = time
        .replace(new RegExp(/-/gm), '/')
        .replace('T', ' ')
        .replace(new RegExp(/\.[\d]{3}/gm), '')
    }
    if (typeof time === 'number' && time.toString().length === 10) {
      time = time * 1000
    }
    date = new Date(time)
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay()
  }
  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
    let value = formatObj[key]
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') {
      return ['日', '一', '二', '三', '四', '五', '六'][value]
    }
    if (result.length > 0 && value < 10) {
      value = '0' + value
    }
    return value || 0
  })
  return time_str
}

// 表单重置
export function resetForm(refName) {
  if (this.$refs[refName]) {
    this.$refs[refName].resetFields()
  }
}

// 添加日期范围
export function addDateRange(params, dateRange, propName) {
  const search = params
  search.params =
    typeof search.params === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {}
  dateRange = Array.isArray(dateRange) ? dateRange : []
  if (typeof propName === 'undefined') {
    search.params['beginTime'] = dateRange[0]
    search.params['endTime'] = dateRange[1]
  } else {
    search.params['begin' + propName] = dateRange[0]
    search.params['end' + propName] = dateRange[1]
  }
  return search
}

// 回显数据字典
export function selectDictLabel(datas, value) {
  var actions = []
  Object.keys(datas).some((key) => {
    if (datas[key].value == '' + value) {
      actions.push(datas[key].label)
      return true
    }
  })
  return actions.join('')
}

// 回显数据字典(字符串数组)
export function selectDictLabels(datas, value, separator) {
  var actions = []
  var currentSeparator = undefined === separator ? ',' : separator
  var temp = value.split(currentSeparator)
  Object.keys(value.split(currentSeparator)).some((val) => {
    Object.keys(datas).some((key) => {
      if (datas[key].value == '' + temp[val]) {
        actions.push(datas[key].label + currentSeparator)
      }
    })
  })
  return actions.join('').substring(0, actions.join('').length - 1)
}

// 字符串格式化(%s )
export function sprintf(str) {
  var args = arguments
  var flag = true
  var i = 1
  str = str.replace(/%s/g, function () {
    var arg = args[i++]
    if (typeof arg === 'undefined') {
      flag = false
      return ''
    }
    return arg
  })
  return flag ? str : ''
}

// 转换字符串,undefined,null等转化为""
export function praseStrEmpty(str) {
  if (!str || str == 'undefined' || str == 'null') {
    return ''
  }
  return str
}

// 数据合并
export function mergeRecursive(source, target) {
  for (var p in target) {
    try {
      if (target[p].constructor == Object) {
        source[p] = mergeRecursive(source[p], target[p])
      } else {
        source[p] = target[p]
      }
    } catch (e) {
      source[p] = target[p]
    }
  }
  return source
}

/**
 * 构造树型结构数据
 * @param {*} data 数据源
 * @param {*} id id字段 默认 'id'
 * @param {*} parentId 父节点字段 默认 'parentId'
 * @param {*} children 孩子节点字段 默认 'children'
 */
export function handleTree(data, id, parentId, children) {
  const config = {
    id: id || 'id',
    parentId: parentId || 'parentId',
    childrenList: children || 'children'
  }

  var childrenListMap = {}
  var nodeIds = {}
  var tree = []

  for (const d of data) {
    const parentId = d[config.parentId]
    if (childrenListMap[parentId] == null) {
      childrenListMap[parentId] = []
    }
    nodeIds[d[config.id]] = d
    childrenListMap[parentId].push(d)
  }

  for (const d of data) {
    const parentId = d[config.parentId]
    if (nodeIds[parentId] == null) {
      tree.push(d)
    }
  }

  for (const t of tree) {
    adaptToChildrenList(t)
  }

  function adaptToChildrenList(o) {
    if (childrenListMap[o[config.id]] !== null) {
      o[config.childrenList] = childrenListMap[o[config.id]]
    }
    if (o[config.childrenList]) {
      for (const c of o[config.childrenList]) {
        adaptToChildrenList(c)
      }
    }
  }
  return tree
}

/**
 * 参数处理
 * @param {*} params  参数
 */
export function tansParams(params) {
  let result = ''
  for (const propName of Object.keys(params)) {
    const value = params[propName]
    var part = encodeURIComponent(propName) + '='
    if (value !== null && typeof value !== 'undefined') {
      if (typeof value === 'object') {
        for (const key of Object.keys(value)) {
          if (value[key] !== null && typeof value[key] !== 'undefined') {
            const params = propName + '[' + key + ']'
            var subPart = encodeURIComponent(params) + '='
            result += subPart + encodeURIComponent(value[key]) + '&'
          }
        }
      } else {
        result += part + encodeURIComponent(value) + '&'
      }
    }
  }
  return result
}

// 验证是否为blob格式
export async function blobValidate(data) {
  try {
    const text = await data.text()
    JSON.parse(text)
    return false
  } catch (error) {
    return true
  }
}

// 通用下载方法
// export function downLoadFile(fileName, filePath) {
//   window.location.href =
//     baseURL + '/common/download/downName?downName=' + encodeURI(fileName) + '&path=' + encodeURI(filePath)
// }
export function downLoadFile(fileName, filePath) {
  const url = baseURL + '/common/download/downName?downName=' + encodeURI(fileName) + '&path=' + encodeURI(filePath)
  const xhr = new XMLHttpRequest()
  xhr.open('get', url)
  xhr.responseType = 'blob' //设置后端返回类型为二进制流,不设置会返回乱码
  xhr.setRequestHeader('Authorization', 'Bearer ' + getToken()) // 若依的鉴权token
  xhr.onload = function () {
    if (this.status == 200) {
      //接受二进制文件流
      var blob = this.response
      const blobUrl = window.URL.createObjectURL(blob)
      // 这里的文件名根据实际情况从响应头或者url里获取
      const a = document.createElement('a')
      a.href = blobUrl
      a.download = fileName
      a.click()
      window.URL.revokeObjectURL(blobUrl)
    }
  }
  xhr.send()
}

/** 根据文件名下载 */
export function downLoadFileByName(fileName) {
  const url = baseURL + '/common/download?fileName=' + encodeURI(fileName) + '&delete=false'
  const xhr = new XMLHttpRequest()
  xhr.open('get', url)
  xhr.responseType = 'blob' //设置后端返回类型为二进制流,不设置会返回乱码
  xhr.setRequestHeader('Authorization', 'Bearer ' + getToken()) // 若依的鉴权token
  xhr.onload = function () {
    if (this.status == 200) {
      //接受二进制文件流
      var blob = this.response
      const blobUrl = window.URL.createObjectURL(blob)
      // 这里的文件名根据实际情况从响应头或者url里获取
      const a = document.createElement('a')
      a.href = blobUrl
      a.download = fileName
      a.click()
      window.URL.revokeObjectURL(blobUrl)
    }
  }
  xhr.send()
}

/** 根据路径下载 */
export function downLoadFileByPath(filePath) {
  const url = baseURL + '/common/download/downloadFundDocument?path=' + encodeURI(filePath)
  const xhr = new XMLHttpRequest()
  xhr.open('get', url)
  xhr.responseType = 'blob' //设置后端返回类型为二进制流,不设置会返回乱码
  xhr.setRequestHeader('Authorization', 'Bearer ' + getToken()) // 若依的鉴权token
  xhr.onload = function () {
    if (this.status == 200) {
      //接受二进制文件流
      var blob = this.response
      const blobUrl = window.URL.createObjectURL(blob)
      // 这里的文件名根据实际情况从响应头或者url里获取
      const a = document.createElement('a')
      a.href = blobUrl
      a.download = filePath
      a.click()
      window.URL.revokeObjectURL(blobUrl)
    }
  }
  xhr.send()
}

/** 精确计算加法 */
export function accutateAdd(num1, num2) {
  if (typeof num1 !== 'number') {
    num1 = parseFloat(num1) || 0
  }
  if (typeof num2 !== 'number') {
    num2 = parseFloat(num2) || 0
  }
  // 获取数字1和2的小数位长度得到小数位多的x, 给两个数乘10的x次方, 保证了两个数都是整数
  const ext1Len = num1.toString().split('.')[1] ? num1.toString().split('.')[1].length : 0
  const ext2Len = num2.toString().split('.')[1] ? num2.toString().split('.')[1].length : 0
  const m = Math.pow(10, Math.max(ext1Len, ext2Len))
  return (num1 * m + num2 * m) / m
}

/**
 * 精确计算
 * @param {*} num1 数字1
 * @param {*} num2 数字2
 * @param {*} method  计算方法  plus加法 minus减法 times乘法 divide除法
 */
export function accutateCalc(num1, num2, method) {
  if (!method) {
    return NaN
  }
  if (typeof num1 !== 'number') {
    num1 = parseFloat(num1) || 0
  }
  if (typeof num2 !== 'number') {
    num2 = parseFloat(num2) || 0
  }
  // 获取数字1和2的小数位长度得到小数位多的x, 给两个数乘10的x次方, 保证了两个数都是整数
  const ext1Len = num1.toString().split('.')[1] ? num1.toString().split('.')[1].length : 0
  const ext2Len = num2.toString().split('.')[1] ? num2.toString().split('.')[1].length : 0
  const m = Math.pow(10, Math.max(ext1Len, ext2Len))
  switch (method) {
    case 'plus':
      return (num1 * m + num2 * m) / m
    case 'minus':
      return (num1 * m - num2 * m) / m
    case 'times':
      return (num1 * m * (num2 * m)) / Math.pow(m, 2)
    case 'divide':
      return (num1 * m) / (num2 * m)
    default:
      return NaN
  }
}

39.Echarts使用?

1.设置容器大小
<template>
  <div class="echart" id="mychart" :style="myChartStyle"></div>
</template>
2.引用
import * as echarts from "echarts";
import Apis from "@/api/index.js";
3.定义使用方法及使用
initEcharts() {
      const mulColumnZZTData = {
        color: ["#0A88F5", "#FF7878"],
        grid: {
          left: "5%", //距离左边的距离
          right: "5%", //距离右边的距离
          bottom: "8%", //距离下边的距离
          top: "12%", //距离上边的距离
        },
        xAxis: {
          data: this.xData,
        },
        yAxis: {},
        series: [
          {
            type: "line", //形状为折线图
            data: this.taskDate,
            barWidth: 15,
            smooth: true,

            name: "任务数", // legend属性
            label: {
              // 柱状图上方文本标签,默认展示数值信息
              show: true,
              position: "top",
            },
          },
        ],
      };
      const myChart = echarts.init(document.getElementById("mychart"));
      myChart.clear();
      myChart.setOption(mulColumnZZTData);
      //随着屏幕大小调节图表
      window.addEventListener("resize", () => {
        myChart.resize();
      });
    },
4.发送请求
async projectSum(year) {
      let { data, code } = await Apis.projectSum({
        year,
      });
      // console.log(data.projects, data.statisticsVos, "data123");
      if (code == 200) {
        this.clearEchart();
        for (let y = 1; y <= 12; y++) {
          const a = data.statisticsVos.filter((item) => {
            return Number(item.ym) == y;
          });
          // console.log(a);
          if (a.length) {
            this.taskDate.push(a[0].totalSum);
          } else {
            this.taskDate.push(null);
          }
          this.xData.push(Number(y) + "月");
        }
        this.initEcharts();
      }
      // console.log(this.yData);
      // console.log(this.taskDate);
      // console.log(this.xData);
    },

40.icon图标的使用

npm install css-loader -D
import "./assets/fontIcon/iconfont.css"
1.添加到项目库
2.将生成的图标库下载至本地,并解压,文件目录如下:

3.在项目中使用
对应Unicode编码,点击复制
引入iconfont.css
@font-face {
  font-family: "iconfont"; /* Project id 3434668 */
  src: url('iconfont.woff2?t=1653710624498') format('woff2'),
       url('iconfont.woff?t=1653710624498') format('woff'),
       url('iconfont.ttf?t=1653710624498') format('truetype');
}

.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* 最主要的部分 */
.icon-quanxuan:before { /* 全选Icon,class为icon-quanxuan,content对应的是unicode编码*/
  content: "\100d9";
}
4.页面使用
<i class:"icon iconfont icon-quanxuan></i>
41.点击新增弹框清楚原本数据?
有时候清空表单数据不起作用,使用此方法->在弹框加上v-if="dialogVisible",同时:visible.sync="dialogVisible"改为:visible="dialogVisible"
<el-dialog
	title="新增"
	v-if="dialogVisible"
	:visible="dialogVisible"
	width="100%"
	:before-close="handleClose"
	:fullscreen="true"
	>
</el-dialog>

42.点击新增按钮新增一行表单,删除按钮删除一行表单

<div style="display: flex; margin: auto">
	<el-form ref="formData" :model="{ formData }" label-width="140px">
		<div v-for="(item, index) in formData" :key="index" class="flex">
			<el-form-item label="中标单位">
				<el-input
					v-model="item.Winning"
					placeholder="请输入中标单位"
					></el-input>
			</el-form-item>
			<el-form-item label="中标金额">
				<el-input
					v-model="item.amount"
					placeholder="请输入中标金额"
					></el-input>
			</el-form-item>
			<i
				class="el-icon-remove-outline"
				style="
				font-size: 24px;
				font-weight: bold;
				margin-left: 20px;
				line-height: 30px;
				"
				v-if="index != 0"  // 第一行不显示删除按钮
				@click="deleteNextTarget(index)"
				></i>
		</div>
	</el-form>
</div>
<div style="display: flex; justify-content: center">
	<el-button
		icon="el-icon-plus"
		plain
		size="small"
		@click="addNextTarget"
		></el-button>
</div>
formData: [
	{
		Winning: "",
		amount: "",
		participants: "",
		participant: "",
	},
],
	// 新增投标后项目信息
	addNextTarget() {
	this.formData.push({
		Winning: "",
		amount: "",
		participants: "",
		participant: "",
	});
},
// 删除
deleteNextTarget(index) {
	if (this.formData.length > 1) {
		this.formData.splice(index, 1);
	}
},

43.鼠标事件

@keyup.enter.native和@click.native.prevent
@keyup.enter.native
一般监听写法 
<input v-on:keyup.enter="submit">  <input @keyup.enter="submit">
 如果用了封装组件的话,比如element,这个时候使用按键修饰符需要加上.native
<el-input v-model="account" placeholder="请输入账号" @keyup.enter.native="search()"></el-input>
@click.native.prevent
1.在封装好的组件上使用,所以要加上.native才能click
2.prevent就相当于event.preventDefault()
preventDefault() 方法阻止元素发生默认的行为(例如,当点击提交按钮时阻止对表单的提交)
44.时间轴组件 -- el-timeline -> <el-timeline-item></el-timeline-item>
<el-timeline>
	<el-timeline-item
		v-for="(activity, index) in activities"
		:key="index"
		:icon="activity.icon"
		:type="activity.type"
		:color="activity.color"
		:size="activity.size"
		:timestamp="activity.timestamp"
		@click.native="handleChangeVideo(activity)"
		>
		<div>{{ activity.content }}</div>
	</el-timeline-item>
</el-timeline>

45.全局组件、方法及样式配置

// 引入组件路径
import Pagination from '@/components/Pagination'
// 组件挂载
Vue.component('Pagination', Pagination)
// 引入方法路径--使用{ }解构
import { handlePreview } from '@/utils/ruoyi'
// 方法挂载
Vue.prototype.handlePreview = handlePreview
// 引用路径
import '@/assets/styles/index.scss' //

46.this指向&变量提升

1.普通this
window是js中的全局对象,我们创建的变量实际上是给window添加属性,所以这里可以用window点o对象
全局环境下,this指向window
浏览器中,this指向window
this 默认指向全局对象window,严格模式下,thisundefined;如果有定义,this最终指向的是调用它的对象
// a()没有定义指向,所以指向window,所以this.user为undefined
function a() {
	var user = "追梦子";
	console.log(this.user); //undefined
	console.log(this); //Window
}
a();

this的指向在函数创建的时候是决定不了的,在调用的时候才能决定,谁调用的就指向谁
this指向 o 对象
var o = {
	user:"追梦子",
	fn:function(){
		console.log(this.user);  //追梦子
	}
}
o.fn();
this只会指向它的上一级对象,不管这个对象中有没有this要的东西
var o = {
	a:10,
	b:{
		// a:12,
		fn:function(){
			console.log(this.a); //undefined
		}
	}
}
o.b.fn();

47.文字间距

p {
  word-spacing: 0.2em;   // 单词
	letter-spacing: 0.1em;   // 文字
}

48.自定义表格校验

data(){
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.ruleForm.pass) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
return{
rules: {
checkPass: [
{ validator: validatePass2, trigger: 'blur' }
],
}
}

49.通用方法-首字母大小-下划转驼峰-金额自动添加两位小数-金额千分位加逗号-合并方法

// 首字母大小
export function titleCase(str) {
  return str.replace(/( |^)[a-z]/g, (L) => L.toUpperCase());
}

// 下划转驼峰
export function camelCase(str) {
  return str.replace(/_[a-z]/g, (str1) => str1.substr(-1).toUpperCase());
}

export function isNumberStr(str) {
  return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str);
}

// 金额自动添加两位小数
export function fundPut(num) {
  let result = Number(num).toFixed(4);
  if (isNaN(result)) {
    return null;
  } else {
    return result;
  }
}

// 金额千分位加逗号
export function thousands(num) {
  // console.log(num, isNaN(num));
  if (num == null || num == undefined) {
    return null
  } else {
    var str = num.toString();
    var reg = str.indexOf(".") > -1 ? /(\d)(?=(\d{3})+\.)/g : /(\d)(?=(?:\d{3})+$)/g;
    return str.replace(reg, "$1,");
  }
}

	// 逗号隔开
export function toThousands(num) {
  if (num != null) {
    var a = parseInt(num)
    var b = String(num).substring(String(num).lastIndexOf("."))
    var result = [], counter = 0;
    a = (a || 0).toString().split('');
    for (var i = a.length - 1; i >= 0; i--) {
      counter++;
      result.unshift(a[i]);
      if (!(counter % 3) && i != 0) { result.unshift(','); }
    }
    if (String(num).lastIndexOf(".") == -1) {
      return result.join('')
    } else {
      return result.join('') + b
    }
  }
  else {
    return 0
  }

}
			
// 合并方法
export function setdates(row, rowIndex, data) {
  const len = data.length;
  const arr = [];
  if (!this.setdatesObj[row]) {
    const obj = {};
    let k;
    for (let i = 0; i < len; i++) {
      k = data[i][row];
      if (obj[k]) obj[k]++;
      else obj[k] = 1;
    }
    this.setdatesObj[row] = obj;
  }

  for (const key in this.setdatesObj[row]) {
    for (let i = 0; i < this.setdatesObj[row][key]; i++) {
      if (i === 0) arr.push([this.setdatesObj[row][key], 1]);
      else arr.push([0, 0]);
    }
  }
  return arr[rowIndex];
}

50.动态修改表格数据

页面:

<template>
    <el-table
      :data="tableData"
      border
      style="width: 100%"
      @cell-click="handleRowClick"
    >
      <el-table-column type="index" label="序号" width="50" align="center">
      </el-table-column>
      <el-table-column prop="entryWeek" label="本周进场数" align="center">
        <template slot-scope="scope">
          <div v-if="scope.row.entryWeekEdit">
            <el-input
              v-model="scope.row.entryWeek"
              @blur="handleBlur(scope.row, 'entryWeekEdit')"
            />
          </div>
          <div v-else>{{ scope.row.entryWeek }}</div>
        </template>
      </el-table-column>
    </el-table>
</template>

方法:

<script>
export default {
  data() {
    return {
    // 表格数据
      tableData: [],
	}
}
 methods: {
    /**
     * 表格点击事件
     */
    handleRowClick(row, column) {
      console.log(121212121);
      // 将当点击的属性处改为true
      const prop = column.property + "Edit";
      this.$set(row, prop, true);
    },
    /**
     * 输入失去焦点事件
     */
    handleBlur(row, prop) {
      console.log(34343434343);
      // 将当前可编辑处改为false
      this.$set(row, prop, false);
      // 新增的指标不处理,非新增的调用接口
      if (!row.isNewAdd) {
        // 如果是已存在的指标
       // 这个地方调用修改接口
      }
    },
};
</script>
  • 15
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值