Advertisement

【vue】vue+avue+elementui项目问题汇总-持续更新ing

阅读量:

这里是目录标题鸭!

  • 一、报错

    • 1. 🍧报错不提示,只提示400
  • 二、滚轮

    • 1.🍦竖轴显示 横轴不显示
    • 2.avue表格增加竖列滚轮
    • 3.【自定义弹窗·带全屏】横轮
  • 三、avue

    • 1. 🎂新增按钮+弹窗事件
    • 2. ⛄️编辑弹窗内某输入框禁用,新增的该框不禁用
    • 3. 🫐删除操作栏图标
    • 4. 搜索框 放最右侧
  • 四、css

    • 1. 🌈其他界面样式被该界面影响
  • 五、小程序 vs PC(引入后端数据)

    • 1.🍕 小程序
    • 2. 🍥 PC(该项目)
  • 六、菜单

    • 1. 🍿点击某分组 其他分组关闭 就该分组打开 + 菜单项写法
  • 七、下拉框

    • 1. 【elementui】el-select 反显
    • 2. 【elementui】其他api方法拿到下拉框选到的值
    • 3.【avue】下拉框接后端数据+传参
    • 4.【avue】下拉框联动
  • 八、api

    • 1.【api格式转换】formdata转换
    • 2.【post、get】api
    • 3.api 简化
  • 九、JSON

    • 1.JSON
  • 十、搜索框

    • 1. avue 搜索框和列表同一个参数
    • 2. 【hide、showColumn】搜索框存在,列表和显隐都不存在(改变 框 长度)
    • 3.【filters、sortable】列表项箭头
  • 十一、异步

    • 【重要】async/await
  • 十二、问题判断

    • 1. 【js方法】好像没调用一样 就打出参数看看拿到参数没
    • 2.有问题
  • 十三、后端传num or 英文,前端改中文

    • 1.【列表】后端传num 前端中文显示
    • 2.【列表】后端给英文,前端显示中文
  • 十四、VScode

    • 1.格式化
  • 十五、表格

    • 1.elementui 表格表头变灰+边框+居中
    • 2.表格项数据

一、报错

1. 🍧报错不提示,只提示400

前提须知:

  • utils里先写全局方法,再在界面写你自己的判断
  • ∴ 自己界面写不写error都会报错(先走全局再走界面)
在这里插入图片描述
  • 先找到 然后打印 找到 后端提示 的中文提示位置
  • 更换message内容,别忘了[0]

二、滚轮

1.🍦竖轴显示 横轴不显示

  • style="height:460px" 👇
    一定要给定高度,这个高度就是>= 460px就开始出现滚轮
复制代码
    <el-scrollbar style="height:460px">
    </el-scrollbar>
复制代码
    .el-scrollbar__wrap {
      overflow-x: hidden !important;
      overflow-y: visible;
    }
    
    .el-scrollbar__bar.is-vertical {
      opacity: 1;
    }

🥨 注意: css样式可以写到app.vue里,全局变量

在这里插入图片描述

2.avue表格增加竖列滚轮

  • style="max-height: 300px;overflow-y: auto;"
    🥑 光写 max-height没用 ,得带 overflow-y
复制代码
    	<avue-crud 
     		:option="detailOption" 
     		:data="detailData" 
     		style="max-height: 300px;overflow-y: auto;" 
     		ref="detailCrud">
     	</avue-crud>
在这里插入图片描述

3.【自定义弹窗·带全屏】横轮

  • elementui * :visible.sync=“detailDrawer”
    👉 detailDrawer : 是自定义 确定 弹窗关闭和开启 的 标识 * width=“50%”
    👉 50% : 控制弹窗 宽度 通过控制弹窗宽度 如果avue表格 超过此宽 自动带 横轮 * :before-close=“handleClose”
    👉 handleClose : 关闭的方法,关闭弹窗和全屏
复制代码
    <!-- 自定义弹窗 -->
    <el-dialog :visible.sync="detailDrawer" width="50%" top="50px" :before-close="handleClose" append-to-body size="85%"
      :wrapperClosable="false" :fullscreen="dialogFullScreen"
      :class="[dialogFullScreen ? 'fullscreen' : 'no_fullscreen']">
      <template slot="title">
        <div class="custom_dialog_header">
          <span class="el_dialog_title">配送单详情</span>
          <div class="custom_dialog_menu" @click="dialogFullScreen = !dialogFullScreen">
            <i class="el-icon-full-screen"></i>
          </div>
        </div>
      </template>
      <!-- 内容 -->
      <!-- index【补】+ :model="'入库作业详情'"【改】 -->
      <div class="billOperationDetailDrawer">
        <detail-form :data="detailForm" :model="'配送单详情'" v-if="JSON.stringify(detailForm) !== '{}'"
          style="margin-left: 40px"></detail-form>
        <!-- 模拟page -->
        <!-- style="max-height: 320px;overflow-y: auto;"=>超过一定高度加滚轮 -->
        <avue-crud :option="detailOption" :data="detailData" style="max-height: 300px;overflow-y: auto;" ref="detailCrud"></avue-crud>
      </div>
    </el-dialog>
  • js
复制代码
      data() {
    return {
      //弹窗不弹出
      detailDrawer: false,
       //全屏
      dialogFullScreen: false,
      	}
      },
       methods: {
    // 弹窗关闭
    handleClose() {
      // this.detailForm = {};
      // this.detailData = [];
      this.dialogFullScreen = false;
      this.detailDrawer = false;
    },
       }
  • css
复制代码
    <style scoped>
    
    .fullscreen {
      .el-dialog {
    width: 100%;
      }
    }
    
    .no_fullscreen {
      .el-dialog {
    width: 40%;
      }
    }
    
    // 全屏
    .custom_dialog_header {
      display: flex;
      justify-content: space-between;
    }
    
    .custom_dialog_menu {
      padding: 1px 30px 0 0;
    }
    
    .custom_dialog_menu i {
      color: #909399;
      font-size: 15px;
    }
    
    .el-icon-full-screen {
      cursor: pointer;
    }
    </style>
在这里插入图片描述
  • css全局 (app)
    弹窗下的横杠
复制代码
    <style lang="scss">
    
    .material-avatar {
      width: 100px;
      height: 100px;
      line-height: 110px;
      border: 1px solid #ccc;
      text-align: center;
    }
    .material-avatar i {
      font-size: 32px;
      line-height: 32px;
    }
    </style>
在这里插入图片描述

三、avue

1. 🎂新增按钮+弹窗事件

  • 自定义新增按钮,获取到点击“新增”的事件
  • avue官网的 Methods rowAdd 打开表单新增窗口
  • 自定义新增按钮,获取到点击“新增”的事件

网址:https://v2.avuejs.com/crud/crud-btn-slot/

在这里插入图片描述
  • avue官网的Methods rowAdd 打开表单新增窗口

网址:https://v2.avuejs.com/crud/crud-doc/

在这里插入图片描述

🔔代码:

  • 自己写点击事件,而不是直接用$refs.crud.rowAdd()
    $refs.crud.rowAdd()只是个打开新增弹窗的方法罢了、
在这里插入图片描述
  • 写完点击事件,做拿到点击事件之后要做的事件,然后再调用打开弹窗$refs.crud.rowAdd()
复制代码
     <template slot="menuLeft">
        <!-- 左菜单左上角-新增 -->
        <el-button type="primary" icon="el-icon-plus" size="small" @click="rowAdd()">新增</el-button>
        <!-- 左菜单左上角-删除 -->
        <el-button type="danger" size="small" icon="el-icon-delete" plain @click="handleDelete">
          删 除
        </el-button>
      </template>
复制代码
       // 点击新增按钮
    rowAdd() {
      //不禁用
      this.option.column[0].disabled = false;
      console.log("我被点击啦!!!", this.option.column);
      // this.$forceUpdate();
      //调用打开弹窗的方法
      this.$refs.crud.rowAdd()
    },

2. ⛄️编辑弹窗内某输入框禁用,新增的该框不禁用

前提:

  • 编辑是用的avue内置方法 => editBtn: true, =>所以拿不到点击“编辑”的这个事件
  • 新增也是avue内置方法 => addBtn: true, =>同理

步骤:

  • 编辑自己写不好改,得引用后端数据
  • 改新增,拿到点击“新增”的方法

👆🏻上面两步见 1. 🎂新增按钮+弹窗事件

  • column 该项填好禁用开启 disabled: true,
复制代码
          {
            label: "任务模板编号",
            prop: "code",
            // 禁用
            disabled: true,
           }
  • 新增的点击事件找到 把禁用打开
复制代码
     // 点击新增按钮
    rowAdd() {
      //不禁用
      this.option.column[0].disabled = false;
    },
  • 拿到所有的关闭弹窗事件,让所有禁用在这时重新被禁用
    (不然就点击 新增之后 禁用按钮一直被打开了)
  • avue-crud 里添加 :before-close="handleCrudClose"
    (handleCrudClose是自己随便写的方法名)
复制代码
    <avue-crud :table-loading="loading" :data="tableData" :option="option"
     :before-close="handleCrudClose">
  • 要引入done + done(),让事件继续 done()下去 ,不然关闭功能不实现
复制代码
    // 关闭所有窗口的时候
    handleCrudClose(done) {
      this.option.column[0].disabled = true;
      done();
    },

3. 🫐删除操作栏图标

目标:

在这里插入图片描述

代码:

在这里插入图片描述
复制代码
        editBtnIcon: ' ',
        delBtnIcon: ' ',
        updateBtnIcon: ' ',
        cancelBtnIcon: ' ',

⭐️注意: 跟我写的 一样空格空格 不然 管用

4. 搜索框 放最右侧

在这里插入图片描述
在这里插入图片描述

avue 文档

在这里插入图片描述
  • JS
复制代码
    //搜索 按钮位置
        searchMenuPosition: 'right',
        searchMenuSpan: 17,
  • 先靠右,再调距离(最大24)

四、css

1. 🌈其他界面样式被该界面影响

  • 查看影响其他界面的那页代码
  • 把所有style 改成<style scoped>
  • ⭐️⭐️注意: 特别是这个界面所有引用的import界面全部改成<style scoped>

五、小程序 vs PC(引入后端数据)

1.🍕 小程序

2. 🍥 PC(该项目)

六、菜单

1. 🍿点击某分组 其他分组关闭 就该分组打开 + 菜单项写法

网址:https://element.eleme.cn/#/zh-CN/component/menu#ce-lan

在这里插入图片描述
  • <el-submenu index="1">index 要设置不同名,随便取,不同就行
  • el-menu-item index="/base/warehouse"index 写路径
  • 🍡一组 + 单个🥚 + 一组内多个🍡🍡🍡
在这里插入图片描述
复制代码
    <el-menu
      :default-active="$route.path"
      class="el-menu-vertical-demo"
      background-color="#112f50"
      text-color="#fff"
      active-text-color="#ffd04b"
      router
      :collapse="isCollapse"
    >
      <!-- 一组-->
      <el-submenu index="1">
        <template slot="title">
          <i class="el-icon-menu"></i>
          <span>导航一</span>
        </template>
        <el-menu-item-group>
          <el-menu-item index="/base/warehouse">
            <i class="el-icon-s-grid"></i>
            <span slot="title">111</span>
          </el-menu-item>
          <el-menu-item index="/base/cargo">
            <i class="el-icon-receiving"></i>
            <span slot="title">222</span>
          </el-menu-item>
       ...
        </el-menu-item-group>
      </el-submenu>
    
    	<!-- 单个-->
      <el-menu-item index="/base/map">
        <i class="el-icon-video-camera"></i>
        <span slot="title">333</span>
      </el-menu-item>
    
      <el-menu-item index="/base/callCargo">
        <i class="el-icon-microphone"></i>
        <span slot="title">444</span>
      </el-menu-item>
      
      <!-- 一组内多组-->
      <el-submenu index="2">
        <template slot="title">
          <i class="el-icon-location"></i>
          <span>导航二</span>
        </template>
        <el-menu-item-group>
         <template slot="title">分组一</template>
          <el-menu-item index="/base/task">选项1</el-menu-item>
        </el-menu-item-group>
        <el-menu-item-group title="分组2">
          <el-menu-item index="/base/childTask">选项3</el-menu-item>
        </el-menu-item-group>
    		...
      </el-submenu>
    </el-menu>

七、下拉框

1. 【elementui】el-select 反显

在这里插入图片描述

Vue.js中使用Element UIel-select组件时,如果需要实现选中项的返显,可以通过v-model指令绑定一个局部变量来控制选择的值。

以下是一个简单的例子:

复制代码
    <template>
      <el-select v-model="selectedValue" placeholder="请选择">
    <el-option
      v-for="item in options"
      :key="item.value"
      :label="item.label"
      :value="item.value">
    </el-option>
      </el-select>
    </template>
     
    <script>
    export default {
      data() {
    return {
      selectedValue: '', // 用于双向绑定选中的值
      options: [
        { label: '选项1', value: 'option1' },
        { label: '选项2', value: 'option2' },
        { label: '选项3', value: 'option3' },
      ]
    };
      }
    };
    </script>

在这个例子中,selectedValue是绑定到el-selectv-model上的变量,它会保存选中选项的值。当用户选择一个选项后,selectedValue的值会更新为所选择的itemvalue

如果需要在页面加载时设置默认选中的值,只需要在data函数中初始化selectedValue为对应的选项值即可。例如:

复制代码
    data() {
      return {
    selectedValue: 'option2', // 默认选中值为选项2
    options: [
      // ...
    ]
      };
    }

这样,当页面加载时,el-select将会显示默认选中的值。

2. 【elementui】其他api方法拿到下拉框选到的值

  1. localStorage :localStorage是用于 持久化 的 本地存储,除非 主动删除 数据,否则数据是 永远 不会过期的。在HTML5中新加入了localStorage的特性,它主要是用来作为本地存储,解决了cookie的缺陷问题,用来 替代 cookie

  2. 下次刷新 直接 读取缓存数据,显示之前选择的选项

  3. 存 :
    localStorage.setItem(key, value):将value存储到key字段,如果key存在时,就更新value
    取 :
    localStorage.getItem(key):获取指定key本地存储的值,如果key不存在就返回null

  4. 网址:JS中localStorage的使用

代码:

  • :model=“sortingDropList”el-form-itemmodel写列表List
  • v-model=“addrId”el-selectmodel是选中的数据,非List,写具体项
  • @change=“onAddrIdChange”@change是选中事件
  • :value=“item.addrId”selectedValue是绑定到el-selectv-model上的变量,它会保存选中选项的值。当用户选择一个选项后,selectedValue的值会更新为所选择的itemvalue。(见上一条)
  • v-model=“addrId” 的值更新为:value="item.addrId"
复制代码
     <el-form :inline="true" class="demo-form-inline">
                <el-form-item label="分拣站" :model="sortingDropList">
                    <el-select v-model="addrId" placeholder="请选择" @change="onAddrIdChange">
                        <el-option v-for="item in sortingDropList" :key="item.addrId" :label="item.addrName"
                            :value="item.addrId">
                        </el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="分拣员" :model="sorterDropList">
                    <el-select v-model="userId" placeholder="请选择" @change="onUserIdChange">
                        <el-option v-for="item in sorterDropList" :key="item.userId" :label="item.userName"
                            :value="item.userId">
                        </el-option>
                    </el-select>
                </el-form-item>
            </el-form>
  • 定义idname
复制代码
     data() {
        return {
            // 定义下拉框的id、name
            addrId: null,
            addrName: null,
            userId: null,
            userName: null,
            }
  • id可以直接拿到,name要通过id find
    • localStorage.setItem(‘addrId’, this.addrId) : keyvalue 不是 addridaddrname的关系,而是addridthis.addrid的关系,需注意
复制代码
        // 分拣台下拉框被选项
        onAddrIdChange() {
            // 根据选中的addrId在sortingDropList中查找对应的addrName
            const selectedItem = this.sortingDropList.find(item => item.addrId === this.addrId);
            if (selectedItem) {
                this.addrName = selectedItem.addrName;
                // 将addrId和addrName保存到localStorage
                localStorage.setItem('addrId', this.addrId)
                localStorage.setItem('addrName', this.addrName);
            }
            this.getList()
        },
  • this.addrId = ~~localStorage.getItem(‘addrId’) || ‘’ : 在JavaScript中,~~ 是一个 双位非操作符 的连续应用,它实际上执行了一个“双位取反 ”操作。这种操作经常用作一个快速的方式来将 一个浮点数转换为整数,或者将非数字值转换为0(如果它是假值的话)。
    • localStorage.getItem('addrId')返回一个值时,~~ 会尝试将其转换为一个整数。如果 localStorage.getItem('addrId') 返回一个 字符串 形式的数字,例如 “123”,~~ 会将其转换为整数 123。如果它返回一个 非数字字符串或null(当 localStorage 中没有 'addrId' 这个键时),~~ 会将其转换为 0
    • || '' 是一个逻辑或操作,如果前面的表达式(即 ~~localStorage.getItem(‘addrId’))的结果是一个假值(例如 0nullundefinedNaNfalse、空字符串等),则整个表达式的值将是后面的值,即空字符串 ‘’。
复制代码
     //加载表格数据
        onLoad(page, params = {}) {
            this.loading = true;
            // 【1】分拣站下拉框
            getFjzList().then(res => {
                this.sortingDropList = res.data.data;
                this.addrId = ~~localStorage.getItem('addrId') || ''
                this.getList()
            })
            // 【2】拣货员下拉框
            getJhyList().then(res => {
                this.sorterDropList = res.data.data;
                this.userId = ~~localStorage.getItem('userId') || ''
            })
        },
  • { sortId: this.addrId } : 其他api 调用的时候 直接 {参数:this.addrId } 找到addrid就行了
复制代码
    // 获取详情列表数据
        getList() {
            sortingDetail(
                { sortId: this.addrId }
            ).then(res => {
                //注意:别直接=res,自己找找内容到底放到哪层
                this.deliveryList = res.data.data;
    
                this.materialList = res.data.data.binInfoVo;
                this.tableData = res.data.data.sortingWallVoList;
    
                console.log("列表被打印啦:", res);
                this.loading = false;
            })
        },

3.【avue】下拉框接后端数据+传参

  1. get

dicUrl: ‘/api/sortingTable/getFjzList’,
//label: ‘addrName’ => 列表显示值
//value:‘addrId’ => 传参值
props: {
label: ‘addrName’,
value: ‘addrId’
},

代码:

复制代码
      {
                        label: '工作台',
                        prop: 'workBench',
                        type: 'select',
                        search: true,
                        searchSpan: 5,
                        searchPlaceholder: '--请选择--',
                        viewDisplay: false,
                        addDisabled: true,
                        screen: true,
                        hide: true,
                        showColumn: false,
                        dicUrl: '/api/sortingTable/getFjzList',
                        //label: 'addrName' => 列表显示值
                        //value:'addrId' => 传参值
                        props: {
                            label: 'addrName',
                            value: 'addrId'
                        },
                    },
  1. post

// {{key}}自动取到跟startName绑定的父的key(value) ,不一定这么写 ,看接口F12
dicUrl: ‘/api/orderTask/getCkOrGwList?addrType={{key}}’,
//label: ‘name’ => 列表显示值
//value:‘addrName’ => 传参值
props: {
label: ‘name’,
value: ‘addrName’
},

代码:

复制代码
      {
            label: '起点',
            prop: 'startName',
            type: 'select',
            search: true,
            searchslot: true,
            placeholder: '请先选择起点类型',
            searchSpan: 6,
            slot: true,
            sortable: true,
            // 【avue2】: Form组件-数据字典-字典联动
            cascaderIndex: 1,
            cell: true,
            // {{key}}自动取到跟startName绑定的父的key(value)
            dicUrl: '/api/orderTask/getCkOrGwList?addrType={{key}}',
            //label: 'name' => 列表显示值
            //value:'addrName' => 传参值
            props: {
              label: 'name',
              value: 'addrName'
            },
          },

4.【avue】下拉框联动

网址: 【avue2】: Form组件-数据字典-字典联动
https://v2.avuejs.com/form/form-dic/#字典联动

  • 目的:选择不同“终点类型”,终点显示不同内容和下拉框
    在这里插入图片描述
  • 父: cascader为需要联动的子选择框prop值,填写多个就会形成 一对多 的关系
  • cascaderIndex 设置默认选择 第几项
  • 代码:
复制代码
    		   {
            label: '终点类型',
            prop: 'endType',
            type: 'select',
            search: true,
            searchslot: true,
            placeholder: '请选择',
            searchSpan: 6,
            slot: true,
            sortable: true,
    
            // avue2-Form组件-数据字典-字典联动
            cascader: ['endName'],
            cascaderIndex: 1,
            dicData: [
              {
                label: '仓库',
                value: 'CK',
              },
              {
                label: '工位',
                value: 'GW',
              }
            ],
          },
           {
            label: '终点',
            prop: 'endName',
            type: 'select',
            search: true,
            searchslot: true,
            placeholder: '请先选择终点类型',
            searchSpan: 6,
            slot: true,
            sortable: true,
            // 【avue2】: Form组件-数据字典-字典联动
            cascaderIndex: 1,
            cell: true,
            // {{key}}自动取到跟startName绑定的父的key(value)
            dicUrl: '/api/orderTask/getCkOrGwList?addrType={{key}}',
            //label: 'name' => 列表显示值
            //value:'addrName' => 传参值
            props: {
              label: 'name',
              value: 'addrName'
            },
          },

八、api

1.【api格式转换】formdata转换

  • 参数格式转换(axios FormData):
    • 表单格式(post+请求参数格式是x-www-form-urlencoded)

代码:

  • import { axiosFormData } from ‘@/util/util’;
  • data: axiosFormData(data)
复制代码
    //api js
    
    import request from '@/router/axios';
    import { axiosFormData } from '@/util/util';
    
    export const sortingDetail = (data) => {
    return request({
        url: '/api/sortingTable/sortingDetail',
        method: 'post',
        data: axiosFormData(data)
    })
    }
  • 工具封装
复制代码
    // @/util/util
    
    export function axiosFormData(json) {
      const data = new FormData();
      Object.keys(json).forEach(key => {
    data.append(key, json[key]);
      })
    
      return data
    }

2.【post、get】api

  1. get
复制代码
    /** * 查询详情列表.
     * @param {*} data 
     * @returns 返参
     */
    export const queryList = (params) => {
    return request({
        url: '/api/orderTask/getOrderTaskDetail',
        method: 'get',
        params
    })
    }
  1. post
复制代码
    /** * 查询all列表 + 单个查询.
     * @param {*} data 
    * @returns 返参
    */
    export const getList = (page, pageSize, data) => {
    // 合并page、pageSize和data对象
    const requestData = {
        page,
        pageSize,
        ...data, // 将data对象的属性合并到requestData中
    };
    return request({
        url: '/api/orderTask/getOrderTaskPage',
        method: 'post',
        data: requestData, // 传递合并后的对象作为请求数据
    })
    }
复制代码
    /** * 任务完成或取消.
    * @param {*} data 
    * @returns 返参
    */
    export const taskStatus = (data) => {
    return request({
        url: '/api/orderTask/taskManualOrCancel',
        method: 'post',
        data
    })
    }

3.api 简化

请添加图片描述
请添加图片描述

  • 使用
复制代码
    getListcircuitApi.getPathConfig(
                page.currentPage, // 第一个参数:page
                page.pageSize,    // 第二个参数:pageSize
                params // 第三个参数:data
            ).then(res => {
                //总页数
                this.page.total = res.data.data.total;
                //注意:别直接=res,自己找找内容到底放到哪层
                this.tableData = res.data.data.records;
                console.log("res被打印啦:", res);
                console.log("列表被打印啦:", this.tableData);
            })

九、JSON

1.JSON

JSON.parse(JSON.stringify(this.warehouseDetailData))

十、搜索框

1. avue 搜索框和列表同一个参数

在这里插入图片描述
繁琐写法:

  • JS:
复制代码
     column: [
          {
            label: '单据日期',
            prop: 'documentDate',
            // width: 130,
            span: 8,
            showColumn: true,
            search: false,
            slot: true,
            sortable: true,
          },
          
          //搜索 专项
          {
            label: '单据日期',
            prop: 'date',//???????
            viewDisplay: false,
            sortable: true, //箭头排序-可以实现以该列为基准的排序(简单的升降序)
            search: true,
            hide: true,
            searchslot: true,
            searchSpan: 9,
            showColumn: false,
            minWidth: '100',
            span: 9,
          },
         ]

简便写法:

  • HTML:
复制代码
      <avue-crud
      :data="tableData"
      :option="tableOption"
      :page.sync="tablePage"
      :table-loading="tableLoading"
      @on-load="onLoad"
      @selection-change="selectionChange"
      @search-change="tableSearchChange"
      @search-reset="tableResetChange"
      @row-click="openDetailDrawer"
      ref="crud"
      @current-change="currentChange"
      @size-change="sizeChange"
      @refresh-change="refreshChange"
    >
       <!-- 日期 -->
      <template slot="createTimeSearch">
        <el-date-picker
          v-model="tableSearch.day"
          type="datetimerange"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          format="yyyy-MM-dd HH:mm:ss"
          value-format="yyyy-MM-dd HH:mm:ss"
          :default-time="['00:00:00', '23:59:59']"
          @input="datetimeChange"
        ></el-date-picker>
      </template>
    </avue-crud>
复制代码
    column: [
          {
            label: '生成时间',
            prop: 'createTime',
            sortable: true,//上下三角可排序
            search: true,//可搜索
            searchSpan: 8,//输入框所占用的列数
            searchLabel: '作业生成时间',//搜索项label
            searchLabelWidth: 100,//搜索标题label的宽度
            slot: true,//是否使用自定义的插槽来渲染表头
            minWidth: '100',
          },
         ]
复制代码
    // 查询项
      tableSearch: {},
复制代码
      created() {
    this.constOptionData = customConstant;
    if (getStore({ name: 'billOperation' })) {
      let data = getStore({ name: 'billOperation' });
      data.forEach((item) => {
        this.tableOption.column.forEach((chileItem) => {
          if (item.prop === chileItem.prop) {
            chileItem.hide = item.hide;
          }
        });
      });
    }
    const column = this.findObject(this.tableOption.column, 'type');
    // column.dicData = jobStyle();
    if (this.$route.params.id) {
      this.tableSearch.billCode = this.$route.params.id;
      this.tableSearch.day = '';
      this.onLoad(this.tablePage, this.tableSearch);
    } else {
      this.tableSearch.day = dateDay();
    }
      },
  • methods:
复制代码
    datetimeChange() {
      //强制刷新
      this.$forceUpdate();
    },
在这里插入图片描述

2. 【hide、showColumn】搜索框存在,列表和显隐都不存在(改变 框 长度)

  • JS:
复制代码
      //→搜索项
          {
            label: '物资',
            prop: 'materialCodeOrName',
            search: true,
            searchPlaceholder: '编号或名称',
            hide: true,//列表中隐藏
            showColumn: false,//在列显隐中不出现
            searchSpan: 6,//调整 框 的长度
          },
          //←

在这里插入图片描述
在这里插入图片描述

3.【filters、sortable】列表项箭头

在这里插入图片描述
复制代码
       {
            label: '拣货台',
            prop: 'pickAddressName',
            slot: true,
            filters: true,//下箭头-》筛序、重置
            sortable: true,//上下箭头-》排序
          },
  • filters:
    在这里插入图片描述

    • sortable:
      在这里插入图片描述

十一、异步

  • 异步是指在进行某个操作时,不需要等待该操作完成才能进行下一步操作。相反,可以继续执行其他任务,而在操作完成后再处理它。
  • 异步编程可以通过多种方式实现,常见的方式包括回调函数、Promise对象和async/await语法。
  • 当处理异步操作时,常见的方式是使用回调函数。回调函数是一种在异步操作完成后被调用的函数。例如,可以使用Node.js的setTimeout函数来模拟一个异步操作,并在操作完成后调用回调函数:
复制代码
    function asyncOperation(callback) {
      setTimeout(() => {
    // 模拟一个异步操作
    const result = 10;
    callback(result);
      }, 1000);
    }
    
    asyncOperation((result) => {
      console.log(result); // 输出:10
    });
  • 另一种常见的方式是使用Promise对象。Promise是JavaScript中处理异步操作的标准方式之一。Promise对象表示一个异步操作的最终结果,并提供了处理成功或失败的回调函数。
    • Promise对象是一种更为现代的方式,它提供了一种更结构化的方式来处理异步操作。我们可以将异步操作封装到一个Promise对象中,并使用then()方法来处理操作的结果。此外,Promise还提供了catch()方法来处理操作中可能出现的错误。以下是一个使用Promise的例子:
复制代码
    function asyncOperation() {
      return new Promise((resolve, reject) => {
    setTimeout(() => {
      // 模拟一个异步操作
      const result = 10;
      resolve(result);
    }, 1000);
      });
    }
    
    asyncOperation().then((result) => {
      console.log(result); // 输出:10
    }).catch((error) => {
      console.error(error);
    });
  • 最后,可以使用ES7引入的async/await语法来编写更清晰、易读的异步代码。async函数返回一个Promise对象,await关键字可以暂停代码的执行,直到异步操作完成。以下是使用async/await的例子:
复制代码
    function asyncOperation() {
      return new Promise((resolve, reject) => {
    setTimeout(() => {
      // 模拟一个异步操作
      const result = 10;
      resolve(result);
    }, 1000);
      });
    }
    
    async function example() {
      try {
    const result = await asyncOperation();
    console.log(result); // 输出:10
      } catch (error) {
    console.error(error);
      }
    }
    
    example();

所以:
.then 为异步 可跳过,跟他同级的会跳过异步直接执行 所以需要放在里面(如果需要先调用异步再拿数据的话)

复制代码
        getList() {
            // 初始化列表数据
            this.deliveryList = [];
            // 调用接口
            sortingDetail(
                { sortId: this.addrId }
            ).then(res => {
                //注意:别直接=res,自己找找内容到底放到哪层
                this.deliveryList = res.data.data;
    
                this.materialList = res.data.data.binInfoVo;
                this.tableData = res.data.data.sortingWallVoList;
    
                console.log("列表被打印啦:", res);
                console.log("this.deliveryList——", this.deliveryList);
                this.loading = false;
                this.judgeNextOrder()//正确的(√)
            })
           //总结 .then 为异步 可跳过,跟他同级的会跳过异步直接执行 所以需要放在里面(如果需要先调用异步再拿数据的话)
           //this.judgeNextOrder()【!!!与sortingDetail同级 大错特错 直接跳过sortingDetail执行该方法 拿不到deliveryList的数据就undefined】
        },

this.judgeNextOrder() 要拿到 deliveryList的数据后才能执行 就必须放在.then 里面 不能跟sortingDetail同级

【重要】async/await

  • 代码:
复制代码
    // strategyBtn() {
    //   this.strategyDrawer = true;
    //   queryStrategy().then((res) => {
    //     console.log('列表被打印啦:', res);
    //     this.strategyList = res.data;
    //     this.setSelectedStrategy();
    //   });
    // },
     // 拿到被选项
    setSelectedStrategy() {
      // 使用 find 方法在 strategyList 中查找 canChoose 属性为 true 的{}
      const selected = this.strategyList.find((strategy) => strategy.canChoose);
      // 如果{}存在,则将其 id 给 selectedStrategy
      if (selected) {
        this.selectedStrategy = selected.id;
      }
    },
    // 确定
    strategySave() {
      // 没找到
      console.log('this.selectedStrategy', this.selectedStrategy);
    
      saveStrategy(this.selectedStrategy).then((res) => {
        if (res.code === 0) {
          this.$message({
            type: 'error',
            message: res.msg,
          });
        } else {
          this.$message({
            type: 'success',
            message: res.msg,
          });
          this.onLoad(this.page, this.query);
          // 关闭弹窗
          this.strategyClose();
        }
      });
    },
  • strategyBtn()写成这样,strategySave() 就拿不到this.selectedStrategy
    • strategyBtn()写成async/awaitthis.selectedStrategy 就能拿到
复制代码
    async strategyBtn() {
      this.strategyDrawer = true;
        const res = await queryStrategy();
        console.log('列表被打印啦:', res);
        this.strategyList = res.data;
        this.setSelectedStrategy();
    },
  • 解释:

Promise 链式写法

  • 使用 Promise 链式写法时,我们通过 .then()方法逐步链接异步操作:
复制代码
    function fetchData() {
      return new Promise((resolve) => {
    setTimeout(() => {
      resolve('Data');
    }, 1000);
      });
    }
    
    fetchData().then((data) => {
      console.log(data); // 打印 'Data'
      return processData(data);
    }).then((processedData) => {
      console.log(processedData); // 打印处理后的数据
    }).catch((error) => {
      console.error('Error:', error);
    });
  • 虽然这种写法能按顺序执行异步操作,但当链条变长时,代码的可读性和可维护性会下降。

async/await 写法

  • 使用 async/await 可以使代码看起来像同步代码,更直观地表达 顺序执行 :
复制代码
    async function fetchData() {
      return new Promise((resolve) => {
    setTimeout(() => {
      resolve('Data');
    }, 1000);
      });
    }
    
    async function main() {
      try {
    const data = await fetchData();
    console.log(data); // 打印 'Data'
    const processedData = await processData(data);
    console.log(processedData); // 打印处理后的数据
      } catch (error) {
    console.error('Error:', error);
      }
    }
    
    main();
  • async/await 中,await 关键字会暂停函数的执行,直到 Promise 解析完成。这样可以确保在 await 之后的代码只有在前面的异步操作完成后才会执行。

确保顺序执行的具体应用

  • 在 Vue.js 组件方法中,使用 async/await 可以确保组件状态的更新和异步数据获取按预期顺序进行。例如:
复制代码
    async strategyBtn() {
      this.strategyDrawer = true; // 打开抽屉
      try {
    const res = await queryStrategy(); // 等待策略数据的获取
    console.log('列表被打印啦:', res);
    this.strategyList = res.data; // 更新策略列表
    this.setSelectedStrategy(); // 设置选中的策略
      } catch (error) {
    console.error('Failed to fetch strategies:', error);
      }
    }
  • 这样写可以确保 this.setSelectedStrategy()queryStrategy() 完成后再执行,从而避免未完成异步操作导致的错误。

总结

  • async/awaitawait queryStrategy() 之后方法调完了就是调完了,后面跟这个方法有关的数据都可以用
  • promise.then 写法, queryStrategy() 里面的数据必须在.then里面才能 顺序执行,放在外面就没用了
  • 比如:

正确的

复制代码
    strategyBtn() {
       this.strategyDrawer = true;
       queryStrategy().then((res) => {
         console.log('列表被打印啦:', res);
         this.strategyList = res.data;
         this.setSelectedStrategy();
       });
     },
      setSelectedStrategy() {
      // 使用 find 方法在 strategyList 中查找 canChoose 属性为 true 的{}
      const selected = this.strategyList.find((strategy) => strategy.canChoose);
      // 如果{}存在,则将其 id 给 selectedStrategy
      if (selected) {
        this.selectedStrategy = selected.id;
      }
    },
  • this.setSelectedStrategy(); 必须在.then里面调用才能拿到strategyList的数据、

错误的

复制代码
    strategyBtn() {
       this.strategyDrawer = true;
       queryStrategy().then((res) => {
         console.log('列表被打印啦:', res);
         this.strategyList = res.data;
       });
        this.setSelectedStrategy();//放外面
     },
  • 像这样放外面就没用了,因为 queryStrategy().then((res) => { });异步 ,可以 跳过 它执行下面的,确保这个不会影响别的内容执行(有好有坏吧

十二、问题判断

1. 【js方法】好像没调用一样 就打出参数看看拿到参数没

复制代码
       //判断是上一单还是下一单
        judgeNextOrder() {
            //【总结】好像没调用一样 就打出参数看看拿到参数没
            if (this.deliveryList.nextId === -1) {
                this.isNextOrder = false
            }
            if (this.deliveryList.upperId === -1 ) {
                this.isNextOrder = true
            }
            console.log(this.deliveryList.upperId,this.isNextOrder);
        },

别打印别的乱七八糟的 其他地方调用该接口 该接口就打印接口里面的参数 看看参数到底出没出问题 拿没拿到
console.log(this.deliveryList.upperId,this.isNextOrder);

2.有问题

  • 先看F12是否报错
  • 查看接口数据,看数据传没传过来等其他问题
  • 判断是前端问题还是后端问题
  • 遇到问题就 看接口 看接口 看接口 看参数

十三、后端传num or 英文,前端改中文

1.【列表】后端传num 前端中文显示

复制代码
       <el-form-item label="单位:">
             {{ cargoSpaceInfoForm.detail.unit }} 
          </el-form-item>
在这里插入图片描述
  • 现在 前端显示0或1或空
  • 当为0或空时,显示‘件’;当为1时,显示‘KG’

代码:

  • HTML:
复制代码
       <el-form-item label="单位:">
            <!-- {{ cargoSpaceInfoForm.detail.unit }} -->
            {{ cargoSpaceInfoForm.detail.unit === '0' || !cargoSpaceInfoForm.detail.unit ? '件' : 'KG' }}
          </el-form-item>

讲解:

  • 三元,如果cargoSpaceInfoForm.detail.unit的值是0或者是一个 假值 (如null、undefined、false、空字符串等),则显示“件”,否则显示“KG”。
  • 请注意 假值这个概念

问题:

  • 后端确实传过来的是数字0,但你的页面上显示的是“KG”
    1.数据未正确更新 :确保cargoSpaceInfoForm.detail.unit的值在模板渲染之前已经被后端数据正确更新了。如果你的组件在数据到达之前就渲染了,那么模板中可能会显示旧的值或者默认值。
    2.响应式问题 :如果cargoSpaceInfoForm对象或其子属性不是Vue实例的响应式数据(即不是在data函数中定义的,或者通过this.$set等方法动态添加的),Vue可能无法检测到其变化,并因此不会触发视图的更新。
    3.后端数据格式问题 :检查后端返回的数据是否真的是数字0,而不是字符串"0"。在JavaScript中,字符串"0"和数字0在严格比较时(===)是不相等的。如果后端返回的是字符串"0",那么cargoSpaceInfoForm.detail.unit === 0将返回false,因此会显示"KG"。
    4.计算属性或方法干扰 :如果在其他地方有计算属性或方法也影响到了cargoSpaceInfoForm.detail.unit的值,那么这也可能导致显示错误。
    5.异步数据加载问题 :如果数据是异步加载的(比如通过API调用),需要确保在数据到达并设置到cargoSpaceInfoForm.detail.unit之后,模板才进行渲染。
  • 我这次犯的是 0 格式问题, 后端传过来是 ‘0’

2.【列表】后端给英文,前端显示中文

  • 英文和num :把 {} 改成 type:'select', 再加 dicData,传参是后端要的数据,显示的我们自己规定的中文
  • 区别 :英 – value:‘abc’ ; num – value :1

改之前 代码:

复制代码
    {
            label: '单据状态',
            prop: 'status',
            width: 100,
            viewDisplay: false,
            span: 8,
            hide: false,
            showColumn: true,
            search: false,
            searchPlaceholder: '请输入订单编号',
            slot: true,
            sortable: true
          },
在这里插入图片描述

改之后 代码:

复制代码
    {
            label: '单据状态',
            prop: 'status',
            type: 'select',
            width: 100,
            viewDisplay: false,
            span: 8,
            hide: false,
            showColumn: true,
            search: false,
            searchPlaceholder: '请输入订单编号',
            slot: true,
            sortable: true,
            dicData: [
              {
                value: 'IDLE',
                label: '未执行',
              },
              {
                value: 'RUN',
                label: '执行中',
              },
              {
                value: 'FINISH',
                label: '已完结',
              },
              {
                value: 'LACK',
                label: '缺拣',
              },
            ],
          },
在这里插入图片描述

十四、VScode

1.格式化

  • Prettier
    在这里插入图片描述
    在这里插入图片描述

十五、表格

1.elementui 表格表头变灰+边框+居中

在这里插入图片描述

代码

复制代码
     
    
    <el-table :data="viewData" style="width: 100%" :header-cell-style="{background:'#F0F2F5',color:'#606266'}" border >
     			<el-table-column
              type="index"
              label="序号"
              width="100"
              align="center"
            ></el-table-column>
             <el-table-column label="名称" width="140" align="center">
              <template slot-scope="scope">
                <span v-if="currentView === 'point'">
                  {{ scope.row.name }}
                </span>
                <span v-if="currentView === 'line'">
                  {{ scope.row.name }}
                </span>
                <span v-if="currentView === 'siteType'">
                  {{ scope.row.name }}
                </span>
                <span v-if="currentView === 'site'">
                  {{ scope.row.name }}
                </span>
              </template>
            </el-table-column>
     </el-table>
  • 边框: border
    • 居中: align=“center”
    • 表头::header-cell-style=“{background:‘#F0F2F5’,color:‘#606266’}”
    • scope.row:viewData是[],要取数组里面的{},用scope.row拿行内数据

效果 :居中+表头变灰+有边框
在这里插入图片描述

2.表格项数据

  • 代码
复制代码
    <!-- 表格部分 -->
          <el-table
            :data="viewData"
            style="width: 100%"
            :header-cell-style="{background:'#F0F2F5',color:'#606266'}"
            border
            @selection-change="handleSelectionChange"
          >
            <!-- 多选框 -->
            <el-table-column
              type="selection"
              width="55"
              align="center"
            ></el-table-column>
            <el-table-column
              type="index"
              label="序号"
              width="100"
              align="center"
            ></el-table-column>
            <el-table-column label="名称" width="140" align="center">
              <template slot-scope="scope">
                <span v-if="currentView === 'point'">
                  {{ scope.row.name }}
                </span>
                <span v-if="currentView === 'line'">
                  {{ scope.row.name }}
                </span>
                <span v-if="currentView === 'siteType'">
                  {{ scope.row.name }}
                </span>
                <span v-if="currentView === 'site'">
                  {{ scope.row.name }}
                </span>
              </template>
            </el-table-column>
            <el-table-column :label="tableLabel" align="center">
              <template slot-scope="scope">
                <span v-if="currentView === 'line'">
                  {{ scope.row.detail }}
                </span>
                <span v-if="currentView === 'point'">
                  {{ scope.row.detail }}
                </span>
                <span v-if="currentView === 'siteType'">
                  {{ scope.row.detail }}
                </span>
                <span v-if="currentView === 'site'">
                  {{ scope.row.detail }}
                </span>
              </template>
            </el-table-column>
            <el-table-column
              fixed="right"
              label="操作"
              width="100"
              align="center"
            >
              <template slot-scope="scope">
                <el-button
                  type="text"
                  size="small"
                  @click="infoEdit(scope.row)"
                >
                  编辑
                </el-button>
              </template>
            </el-table-column>
          </el-table>
  • 讲解
    1.多选框 拿到勾选项row

HTML:

复制代码
      @selection-change="handleSelectionChange"
复制代码
    <!-- 多选框 -->
            <el-table-column
              type="selection"
              width="55"
              align="center"
            ></el-table-column>
复制代码
      data() {
    return {
      // 菜单-编辑弹窗被选择项
      multipleSelection: [],
      }

JS:

复制代码
    // 表格项被勾选
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },

this.multipleSelection就是 勾选的[]

  1. 操作栏 row
复制代码
    <template slot-scope="scope">
                <el-button
                  type="text"
                  size="small"
                  @click="infoEdit(scope.row)"
                >
                  编辑
                </el-button>
              </template>
复制代码
      data() {
    return {
    // 菜单-编辑弹窗内的编辑row
      editRowList: {},
      }
复制代码
     // 编辑
    infoEdit(row) {
      this.editRowList = row;
      }

@click=“infoEdit(scope.row)” : 直接用scope.row就行
this.editRowList :row数据 放到了editRowList里

全部评论 (0)

还没有任何评论哟~