在做一个类似与多级菜单多选的组件,发现有3级菜单是,第二级:checked属性绑定失败
html:
<div id="scope">
<!--全选框-->
<label for="all1">全选</label>
<input id="all1" type="checkbox" name="all" v-bind:checked="isAllChecked()" @change="changeAllChecked($event)">
<!--每一个列表-->
<div v-for="item in list">
<!--父标题-->
<div>
<label v-bind:for="item.listTitle">parent{{item.listTitle}}</label>
<input type="checkbox" v-bind:name="item.listTitle" v-bind:checked="isTitleChecked(item)" @change="changeTitleChecked(item,$event)">
</div>
<p>{{isTitleChecked(item)}}</p>
<!--子列表-->
<div v-for="chk in item.listItem">
<label v-bind:for="chk.id">son{{chk.name}}</label>
<input type="checkbox" v-bind:id="chk.id" v-bind:value="chk.id" v-bind:checked="isTitleChecked(chk)" v-model="item.selected" @change="changeTitleChecked(chk,$event)">
<p>{{isTitleChecked(chk)}}</p>
<div v-for="subchk in chk.listItem">
<label v-bind:for="subchk.id">sub{{subchk.name}}</label>
<input type="checkbox" v-bind:id="subchk.id" v-bind:value="subchk.id" v-model="chk.selected">
</div>
<p>{{chk.selected}}</p>
</div>
</div>
</div>
Javascript:
var scope = new Vue({
el:"#scope",
data : {
list:[
{
//用于判断是否展示子列表
isShowListItem : false,
//用于记录选中了哪些子项
selected : [],
//父标题
listTitle : "保利南悦湾",
//子列表
listItem : [
{ //chk
id : 1,
name : "李小龙",
selected:[],
listItem:[
{ //subchk
id:11,
name:"叶问",
},
{
id:12,
name:"彭于晏",
}
]
},
/*{
id : 2,
name : "周星驰",
selected:[],
listItem:[
{
id:4,
name:"吴孟达"
}
]
},
{
id : 3,
name : "周杰伦",
selected:[],
listItem:[
{
id:5,
name:"费玉清"
}
]
}*/
]
}/*,
{
isShowListItem : false,
selected : [],
listTitle : "南庄万科城",
listItem : [
{
id : 4,
name : "大魔王"
},
{
id : 5,
name : "老妖怪"
}
]
}*/
]
},
methods:{
/**
* 当父标题状态变化时的处理方法
* @param data [当前项的data]
* @param event [当前项的event]
*/
changeTitleChecked : function (data,event) {
if (event.target.checked === true) {
data.listItem.forEach(function (item) {
data.selected.indexOf(item.id) === -1 && data.selected.push(item.id);
})
}else {
data.selected = [];
}
},
/**
* 判断父标题选择状态
* @param data [当前项的data]
* @returns {boolean}
*/
isTitleChecked : function (data) {
var _selected = data.selected;
var _listItem = data.listItem;
// 验证selected中是否含有全部的item的id 如果是 证明title要选中
return _listItem.every(function (item) {
return _selected.indexOf(item.id) != -1;
});
},
/**
* 全选框change事件的回调处理方法
* @param event
*/
changeAllChecked : function (event) {
if (event.target.checked === true) {
this.list.forEach(function (data) {
data.listItem.forEach(function (item) {
data.selected.indexOf(item.id) === -1 && data.selected.push(item.id);
})
})
}else {
this.list.forEach(function (data) {
data.selected = [];
})
}
},
/**
* 判断全选框选择状态
* @returns {boolean}
*/
isAllChecked : function () {
return this.list.every(function (data) {
return data.selected.length === data.listItem.length;
});
},
}
})
son的那个checkbox 的checked属性绑定失败当把son那级下面的2个checkbox够勾选上了以后,son不能自动勾选上,但是把son勾选上,它下级的2个checkbox是可以勾选上的
你代码里面的问题:
v-model
其实就是v-bind:checked
的语法糖(参考官方文档),所以你代码里面混用的v-bind:checked="xxx"
和v-model="xxx"
的用法不是正确的,在subchk节点的操作被Vue内部处理成了v-model
相关的逻辑了。所以你采用v-bind:checked
来验证当前节点是否被选中的实现方式,我个人觉得这样是不对的个人感觉,对于
这段代码,vue应该是根据v-model去判断了当前的checkbox是否被选中的逻辑(即简单粗暴的理解为v-model比v-bind:checked的优先级更高,假如 v-bind:checked 先告诉了 vue 当前的input为checked=true, 但是之后v-model又告诉 vue 当前的input为checked=false, 最后vue以v-model的结果为准)。而接下来的
因为它的结果是什么就是什么,没人来反对(覆盖)它,所以它就很简单的返回结果就好了。因而最终的结果就是你看到的同一个
isTitleChecked(chk)
, 在<input>
里面不生效,而在<p>
里面生效了。你这种写法导致的这种错误现象,我还没理清楚~~~,待我后续再观察观察....