目录
3、使用Vue.set更新数据(当数据更新视图不更新是可使用)
1、vue-router在query跳转时参数改变,页面不更新的办法
2、解决element-ui组件table里面嵌套el-image层级太低的问题
3、element-form表单提交验证,保存时未填项页面回滚到未填项处
4、element-form表单的el-cascader修改数据后不能通过validate验证
5、replaceAll浏览器不兼容问题(replaceAll方法在谷歌浏览器没有问题,但是在360极速浏览器会报错)
7、element-date的时间控件设置当前时间之前的时间不可以选择
8、element的MessageBox弹框,控制回车不提交数据
9、关于element-table的分页删除数据时在分页只有最后一条数据,这个时候分页有问题。
11、elemen-plus tree加载局部更新数据(先更新tree数据再更新视图)
vue系列
vue记录(vue2-vue3)
1、vue2、vue3全局通信
- Vue2.x使用EventBus进行组件通信,而Vue3.x推荐使用
mitt.js
。
1、安装mitt
npm install --save mitt
2、在项目中使用
2.1、在main.js挂到全局
import mitt from 'mitt'
const app = createApp(App)
// vue3.x的全局实例,要挂载在config.globalProperties上
app.config.globalProperties.$EventBus = new mitt()
2.2、封装一个公用方法,在utils文件新建一个bus.js
//bus.js
import mitt from 'mitt'
export default new mitt()
业务模块使用:
发送页面,业务页面调用方法
// a.vue
//在页面引入这个js
import bus from '/utils/bus.js'
//通过on监听/emit触发
const onClose = (i) =>{
bus.emit('closeTags', i)
}
接收页面(公用组件页面)
//tag.vue
//公用的组件
import {onBeforeUnmount} from 'vue'
export default {
setup(){
//在页面接收
bus.on('closeTags', data => {
closeTags(data)
})
const closeTags = i =>{
console.log(i)
}
onBeforeUnmount(() => {
// 移除指定事件
bus.off('closeTags')
// 移除全部事件
bus.all.clear()
})
}
}
API:参考mitt - npm
方法名称 | 作用 |
---|---|
on | 注册一个监听事件,用于接收数据 |
emit | 调用方法发起数据传递 |
off | 用来移除监听事件 |
on
的参数:
参数 | 类型 | 作用 |
---|---|---|
type | string | symbol | 方法名 |
handler | function | 接收到数据之后要做什么处理的回调函数 |
这里的 handler
建议使用具名函数,因为匿名函数无法销毁。
emit
的参数:
参数 | 类型 | 作用 |
---|---|---|
type | string | symbol | 与 on 对应的方法名 |
data | any | 与 on 对应的,允许接收的数据 |
off
的参数:
参数 | 类型 | 作用 |
---|---|---|
type | string | symbol | 与 on 对应的方法名 |
handler | function | 要删除的,与 on 对应的 handler 函数名 |
2、控制台报错[Violation] Added non-passive event listener to a scroll-blocking 'mousewheel' event. Consider marking event handler as 'passive' to make the page more responsive.
解决方式:
1、安装依赖
npm i default-passive-events -S
2、在main.js文件引入
import 'default-passive-events'
3、使用Vue.set更新数据(当数据更新视图不更新是可使用)
1、更新数组对象
this.$set(目标表,索引,新的值)
2、更新对象
this.$set(目标对象,对象名称,新的值)
//更新数组对象
for(let i=0;i<this.serviceNoteListNew.length;i++){
let item =this.serviceNoteListNew[i];
if(i===index){
item.play=!item.play;
this.$set(this.serviceNoteListNew,i,item)
}
}
或使用forceUpdate,(但是有的子组件不会更新,这个时候使用set方法比较好)
更新视图,强制更新。 this.$forceUpdate()
v-router记录
1、vue-router在query跳转时参数改变,页面不更新的办法
1.1对<router-view>标签添加key值,比如:
<template>
<div id="app">
<router-view :key="$route.fullPath"/>
</div>
</template>
fullPath:URL 编码与路由地址有关。包括
path
、query
和hash
关于 router-view 的 key 属性
由于 Vue 会复用相同组件, 比如 /page/1 => /page/2 或者 /page?id=1 =>
/page?id=2这类链接跳转, 将不在执行created, mounted之类的钩子, 这时候你需要在路由组件中,添加beforeRouteUpdate钩子来执行相关方法
1.2监听$router(不推荐,虽然重新请求了数据,但是没有给router-view添加key好用)
watch:{
'$route'(to,form){
if(to.query.state!=form.query.state){
this.stateType=to.query.state;
this.getDetail(); //获取详情
}
}
},
element记录
1、触发图片预览的方法(做个笔记)
第一种:(支持IE 使用elementUi官网文档中的组件)一般项目中需要点击触发事件才进行查看大图,elementUi组件库中并没有写触发需要执行的代码,这里在触发的方法中加this.$refs.preview.clickHandler()触发查看大图功能
第二种:( 不支持IE 使用el-image-viewer组件,是elementUi自带的但官网文档中可能因不兼容IE没有把它暴露出来,不需要下载包引入即可)
<el-button @click="onPreview">预览</el-button>
<el-image-viewer v-if="showViewer" :on-close="closeViewer" :url-list="srcList" />
import ElImageViewer from 'element-ui/packages/image/src/image-viewer'
export default {
components: { ElImageViewer },
data() {
return {
showViewer: true,
url: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
srcList: [
'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
'https://fuss10.elemecdn.com/8/27/f01c15bb73e1ef3793e64e6b7bbccjpeg.jpeg',
'https://fuss10.elemecdn.com/1/8e/aeffeb4de74e2fde4bd74fc7b4486jpeg.jpeg'
],
}
},
methods: {
onPreview() {
this.showViewer = true
},
closeViewer() {
this.showViewer = false
},
}
}
原创:elementUi 通过 previewSrcList 预览大图(两种方式) - 塞巴斯酱 - 博客园
2、解决element-ui组件table里面嵌套el-image层级太低的问题
解决方案:找到这个标签把这个z-index复写成z-index:auto
.el-table .el-table__cell{
z-index:auto
}
3、element-form表单提交验证,保存时未填项页面回滚到未填项处
this.$nextTick(() => {
var isError = document.getElementsByClassName("is-error");
isError[0].scrollIntoView({
// 滚动到指定节点
// 值有start,center,end,nearest
block: "center",
// 值有auto、instant,smooth,缓动动画
behavior: "smooth",
});
});
4、element-form表单的el-cascader修改数据后不能通过validate验证
<el-form-item label="服务类型:" prop="serviceType" label-width="110px">
<el-cascader clearable v-model="ruleForm.serviceType" :options="serviceOptions" :props="serviceProps" size="medium" ></el-cascader>
</el-form-item>
export default {
data() {
const validateOrg = (rule, value, callback) => {
if (this.ruleForm.serviceType.length === 0) {
callback(new Error("请选择!"));
} else {
callback();
}
};
return {
ruleForm: {
channel:'',
serviceType: [],//
},
rules: {
channel: [{ required: true, message: '请选择', trigger: 'change' }],
serviceType: [{ type: "array", validator: validateOrg,required: true, message: '请选择', trigger: 'change' }],
},
}
修改验证规则,PS:如果没有用再额外调用this.$refs.ruleForm.validate(() => {});
5、replaceAll浏览器不兼容问题(replaceAll方法在谷歌浏览器没有问题,但是在360极速浏览器会报错)
<el-table :data="tableData" border stripe>
<el-table-column align="center" prop="preArriveTime" label="预计到达时间" width="180px" :formatter="formatterTime"></el-table-column>
</el-table>
formatterTime(row){
let time = new Date(row.preArriveTime.replace(new RegExp('-',"gm"),'/')).getTime()
if(row.preArriveTime && Date.now()>time){
return <span class="red">{row.preArriveTime}</span>
}
return row.preArriveTime
}
解决方案:replace代替replaceAll
如:
let arrivalTime="2023-05-01 20:09:10"
let aa=arrivalTime.replace(new RegExp('-',"gm"),'/')
g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
m 执行多行匹配。
element-table使用formatter包含HTML代码 :如:<span class="red">{row.preArriveTime}</span>
效果图:
6、el-input的textarea保存时把换行一起保存
<el-input type="textarea" :autosize="{ minRows: 7}" v-model="checkResult" @input="Fninput"></el-input>
export default {
data() {
return {
checkResult:'',
textValue:''
}
},
methods: {
textareaP(centent){//转换为html样式
let str = centent.replace(/\n/g, '\\n')
console.log(str,'=----sss---')
this.textValue=str;
}
}
}
7、element-date的时间控件设置当前时间之前的时间不可以选择
<el-date-picker
v-model="form.bookTime" value-format="yyyy-MM-dd HH:mm:ss" :picker-options="pickerOptions"
type="datetime" default-time="9:00:00"
placeholder="选择日期时间">
</el-date-picker>
data() {
return {
pickerOptions:{
disabledDate(date) {//禁止选择当前日期之前的日期(今天可选)
return date.getTime() < Date.now() - 24 * 60 * 60 * 1000;
},
selectableRange: new Date().getHours() + ":" + (new Date().getMinutes()) + ":00 - 23:59:00",//禁止选择当前时间之前的时间
},
}
}
重点:
pickerOptions:{
disabledDate(date) {//禁止选择当前日期
let hours=new Date().getHours()
if(hours<16){//可以选择今天包含今天(16点之前可以选择今天的日期,16以后的不可以选择今天的日期)
return date.getTime() < Date.now() - 24 * 60 * 60 * 1000;
}else{//不可以选择今天,只能选择今天以后的
return date.getTime() <= Date.now();
}
},
selectableRange: new Date().getHours() + ":" + (new Date().getMinutes()) + ":00 - 23:59:00",//禁止选择当前时间之前的时间
},
8、element的MessageBox弹框,控制回车不提交数据
let _this=this;
this.$prompt('请输入', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern:/\S/,
inputErrorMessage: '不能为空',
beforeClose:(action, instance, done)=>{//MessageBox 关闭前的回调,会暂停实例的关闭
if(action=='confirm'){
let ahtml=instance.$refs['input'];//input输入框的值
instance.$refs['confirm'].$el.onclick=function(e){//点击确定按钮才提交数据,其他方法不执行
let query={
carNo:ahtml.value,
}
_this.$api.postUpdate(_this.res.id,query).then(res=>{
if(res.code===0){
done()//关闭弹出框
_this.$message.success(res.message)
}
})
}
}else{
done()//关闭弹出框
}
}
}).then(() => {
}).catch(() => {});
9、关于element-table的分页删除数据时在分页只有最后一条数据,这个时候分页有问题。
解决方案:
data(){
return{
page_index: 1, // 页数
page_total: 0, // 总页数
page_size: 10,
}
}
getPageSize(){//在删除成功后调用此方法
let totalPage = Math.ceil((this.page_total - 1) / this.page_size);
//计算出当前页码
this.page_index = this.page_index > totalPage ? totalPage : this.page_index;
//如果页码为1的话,则无效
this.page_index = this.page_index < 1 ? 1 : this.page_index;
}
10、element-table实现分页多选功能
selection-change事件选择后分页已经选择的数据会清空
解决方案:
<el-table :data="querylist" :row-key="getRowKeys" @selection-change="handleSelectionChange" >
<el-table-column type="selection" label="选择" align="center" :reserve-selection="true"></el-table-column>
</el-table>
export default {
data(){
return{
selectlist:[]
}
},
methods:{
getRowKeys(row) {
return row.id
},
handleSelectionChange(rows){
this.selectlist=rows;
},
}
}
注意:
需要在选择框的这一例加上::reserve-selection="true"
11、elemen-plus tree加载局部更新数据(先更新tree数据再更新视图)
<el-tree @node-click="nodeClick"
:data="state.datalist"
node-key="id"
:props="props"
:load="loadNode"
lazy ref="treeRef"
class="treeBox"
></el-tree>
const refreshTreeNode = (id) => {
let node = treeRef.value.getNode(id);
if (node) {
node.loaded = false; //告诉组件这个节点需要加载
node.expand(); //主动调用展开节点方法,重新查询该节点下的所有子节点
}
}
refreshTreeNode(id)//在数据更新后执行
参考: element-Plus el-tree 懒加载 vue3 局部刷新_vue3 el-tree懒加载编辑-优快云博客
其他vue功能记录
1、快速构建vite+vue3+ts项目命令
npm init @vitejs/app my-vue-app --template vue-ts
2、vue-cli 查看打包体积可视化命令
特别提示,不需要安装webpack-bundle-analyzer这个插件
只需要在vue.config.js里面配置一项"report": "vue-cli-service build --report",这个命令就可以了,它会在dist里面生成一个report.html文件,直接打开访问可查看
"report": "vue-cli-service build --report"
3、vue新开页面(浏览器重新打开页面)
let pathData=this.$router.resolve({
path: '/xxx/xxx',
query: {
id:''
}
})
window.open(pathData.href,'_blank')
4、服务器webpack打包压缩
4.1、vue2的webpack打包压缩
npm install -D compression-webpack-plugin
const CompressionWebpackPlugin = require("compression-webpack-plugin")
module.exports = {
configureWebpack:{
plugins: [
new CompressionWebpackPlugin(),
],
},
}
4.2、基于vite的webpack打包压缩
npm install -D vite-plugin-compression
import viteCompression from "vite-plugin-compression";
export default ({ command, mode }) =>{
return defineConfig({
plugins: [
viteCompression(),
],
})
})
4.3、nginx配置
/**找到nginx的目录**/
// 找到对应目录地址
cd /usr/local/nginx/conf
// 编辑配置
vi nginx.conf
/**修改配置**/
gzip on;
gzip_buffers 4 16k;
gzip_http_version 1.0;
gzip_comp_level 2;
gzip_types text/plain application/x-javascript text/css application/xml application/javascript;
gzip_vary on;
/**重启nginx**/
// 在sbin目录下面启动
./nginx -s reload