一、多选框单选
<el-table :data="items" ref="multipleTable" @select-all="onSelectAll" @selection-change="selectItem" @row-click="onSelectOp" > <el-table-column type="selection" :reserve-selection="false" />
@select-all="onSelectAll" 全选是触发的事件
@selection-change="selectItem" 单个去勾选时触发的事件(勾选有变化时触发)
@row-click="onSelectOp" 点击那一行数据触发的事件
ref="multipleTable"
ref 被用来给DOM元素或子组件注册引用信息。引用信息会根据父组件的 $refs 对象进行注册。如果在普通的DOM元素上使用,引用信息就是元素; 如果用在子组件上,引用信息就是组件实
注意:只要想要在Vue中直接操作DOM元素,就必须用ref属性进行注册
1、@select-all="onSelectAll"
全选是触发自定义的onSelectAll() 函数,把所有选项清空,
this.$refs.multipleTable.clearSelection();
clearSelection()这个函数是自带的,比如日期的getFullYear()
2、@selection-change="selectItem"
单个去勾选时触发自定义的selectItem函数
@selection-change事件会默认传行数据进去,用selectItem(rows)的rows接收就好,rows所选行数据的数组
this.$refs.multipleTable.toggleRowSelection(it, true);
toggleRowSelection这个函数需要传某行数据,true表示勾选,false表示不勾选,
@selection-change默认是勾选的,也就是说这个事件传进来被选中的数据如果你还是想勾选,那么不需要任何操作,除非你想不勾选,那么就把那条数据用false来去掉勾选。
selectItem这个函数我自定义了,一旦勾选多于一行数据,就把上一个勾选去掉,保留最后一个勾选,用过滤器来过滤,把新的(只有一行数据)的数组赋给自定义的数组,方便调用
3、@row-click="onSelectOp"
点击那一行数据触发的事件默认传点击那行的数据,自定义onSelectOp(row)函数,
用row来接收点击的那行数据,
先把所有的选项清空this.$refs.multipleTable.clearSelection();
再把点击的那行勾选this.$refs.multipleTable.toggleRowSelection(row, true);
把自定义数组清空this.selectlist = [];
把新勾选的数据push进数组this.selectlist.push(row);
methods: { onSelectAll() { this.$refs.multipleTable.clearSelection(); }, selectItem(rows) { if (rows.length > 1) { var newRows = rows.filter((it, index) => { if (index == rows.length - 1) { this.$refs.multipleTable.toggleRowSelection(it, true);//这行可以不要 return true; } else { this.$refs.multipleTable.toggleRowSelection(it, false); return false; } }); this.selectlist = newRows; } else { this.selectlist = rows; } }, onSelectOp(row) { //this.$refs.multipleTable.clearSelection();不需要 this.$refs.multipleTable.toggleRowSelection(row, true);//有这个就够了,因为一旦勾选的内容有变化,那么就会触发selectItem(rows)这个函数
//this.selectlist = [];不需要
//this.selectlist.push(row);不需要
},
二、数据回显toggleRowSelection失效问题
失效例子:
comeBackfromEidt() { let id = parseInt(this.$route.params.id); this.items.forEach(x => { if (x.id == id) { this.$refs.multipleTable.toggleRowSelection(x, true); } }); },
我是从这个页面勾选数据然后跳转到另一个页面,然后返回的时候想回显勾选的数据,写了上面代码,发现回显不了!!!
后来查到需要加上$nextTick才可以
以下代码可行:
comeBackfromEidt() { let id = parseInt(this.$route.params.id); this.items.forEach(x => { if (x.id == id) { this.$nextTick(() => { this.$refs.multipleTable.toggleRowSelection(x, true); }); } }); },
或者把$nextTick放在forEach外面也可以。
$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM
在我们用vue时,我们经常用到一个方法是this.$nextTick,相信你也用过。我常用的场景是在进行获取数据后,需要对新视图进行下一步操作或者其他操作时,发现获取不到dom。
因为赋值操作只完成了数据模型的改变并没有完成视图更新
三、$nextTick不生效?
之前遇到过一种情况,如下图所示
<el-checkbox v-model="checked" @change="selectData" style="margin-left: 20px" >无数据不显示</el-checkbox >
checked初始化为true,即通过值为true或者false来判断打勾没打勾。
这种单选打勾的,由于前端用sessionStorage做数据缓存,刷新页面回显时,发现勾勾没打上,即数据回显有问题。
经过多次测试,才想到,sessionStorage缓存时,缓存的数据都会变成文本,对于boolean类型的值true和false同样也会变成文本的"true"和"false",所以回显缓存的数据时,不能直接赋值回去,需要判断缓存的是"true"或"false"来分别赋值boolean类型的值true和false。
最好我的解决办法是加一层判断
let getChecked = sessionStorage.getItem("sif-rwhz-checked"); if (getChecked != null) { if (getChecked == "true") { this.checked = true; } else { this.checked = false; } }
于是就解决了,或许我这种办法不是最好的,但却是我目前能想到的最简单的。
说到这,顺便说一下缓存对象集合时,先把集合变成JSON,然后用到的时候再转回来
sessionStorage.setItem("sif-rwhz-data", JSON.stringify(this.items));
let data = sessionStorage.getItem("sif-rwhz-data"); if (data != null) { this.items = JSON.parse(data); }