使用vue.js我正在尝试构建一个简单的任务管理器。
当用户点击"完成"复选框我想要发生两件事:
无效部分如下所示:
<div id="tasks-app">
<input type="checkbox" id="checkbox" v-model="show_all">
<label for="checkbox">Show all tasks</label><br>
<table class="table">
<tr><th v-for="column in table_columns" v-text="column"></th><tr>
<tr v-for="row in visibleTasks" :class="{danger: !row.daily_task.complete && row.daily_task.delayed, success: row.daily_task.complete}">
<td v-text="row.task.name"></td>
<td v-text="row.task.deadline"></td>
<td v-text="row.daily_task.status"></td>
<td v-text="row.daily_task.task_user"></td>
<td>
<input type="checkbox" v-on:change="updateStatus(row)" v-model="row.daily_task.complete" >Complete</input>
</td>
<td><input v-model="row.daily_task.delay_reason"></input></td>
</table>
</div>
和VUE.js代码:
app = new Vue({
el: '#tasks-app',
data: {
table_columns: ['Task','Deadline','Status','User','Actions','Reason'],
tasks: [],
filter_string: '',
show_all: false
},
computed: {
visibleTasks() {
show_all = this.show_all
if(show_all){
search_filter = this.tasks
}else{
search_filter = _.filter(this.tasks,function(task){
return !task.daily_task.complete;
})
}
return search_filter
}
},
methods: {
updateStatus(row){
var id = row.daily_task.id
var complete = row.daily_task.complete
if(complete){
axios.get('set_task_complete/' + id)
}else{
axios.get('set_task_open/' + id)
}
}
}
})
如果选中show all复选框,则按预期工作。数据发生变化,然后调用updateStatus
函数。
如果未选中show all复选框,则会触发visibleTasks并且updateStatus
的逻辑将失败,因为该行将被隐藏,并且发送到服务器的ID将被关闭。如果在调用updateStatus
之前隐藏行,则会将错误的行传递给updateStatus
函数。
我可以通过在updateStatus
函数末尾添加过滤器更新来解决这个问题,但似乎没有使用Vue.js库。有人可以帮助我使用哪些Vue组件来解决这个问题吗?
答案 0 :(得分:1)
您的问题是同时使用更改事件句柄和模型。实际上,当您单击复选框时,同时触发。
<input type="checkbox" v-on:change="updateStatus(row)" v-model="row.daily_task.complete" >Complete</input>
您应该仅使用v-on:change="updateStatus(row)"
编辑代码。在updateStatus完成ajax调用后,切换row.daily_task.complete
以触发visibleTasks
更新您的视图。
updateStatus(row){
var id = row.daily_task.id
var complete = !row.daily_task.complete
var p;
if(complete){
p = axios.get('set_task_complete/' + id)
}else{
p = axios.get('set_task_open/' + id)
}
p.then(() => row.daily_task.complete = complete)
}
答案 1 :(得分:1)
如果你将逻辑分开,你可以简化很多:
show_all
)v-on:click="updateStatus(row)"
tr
上添加v-show="show_all || !row.status.complete"
答案 2 :(得分:1)
我稍微重构了你的代码,似乎工作正常:
您不应该使用v-on:change
,而是使用<input type="checkbox" v-on:click="updateStatus(row)" v-bind:checked="row.daily_task.complete">
不要立即更新row.daily_task.complete
,只有在异步axios完成时才更新它。
const fakeUpdateComplete = (id) => {
return new Promise((resolve, reject) => { resolve(true); });
};
const fakeUpdateIncomplete = (id) => {
return new Promise((resolve, reject) => { resolve(true); });
};
const app = new Vue({
el: '#tasks-app',
data: {
history: [],
table_columns: ['Task','Deadline','Status','User','Actions','Reason'],
tasks: [
{
task: {
name: 'A',
deadline: '2017-01-01',
},
daily_task: {
id: 1,
status: '',
task_user: '',
complete: true,
delayed: false,
delay_reason: ''
}
},
{
task: {
name: 'B',
deadline: '2017-01-02',
},
daily_task: {
id: 2,
status: '',
task_user: '',
complete: false,
delayed: false,
delay_reason: ''
}
},
{
task: {
name: 'C',
deadline: '2017-01-03',
},
daily_task: {
id: 3,
status: '',
task_user: '',
complete: false,
delayed: false,
delay_reason: ''
}
},
{
task: {
name: 'D',
deadline: '2017-01-03',
},
daily_task: {
id: 4,
status: '',
task_user: '',
complete: true,
delayed: false,
delay_reason: ''
}
},
{
task: {
name: 'E',
deadline: '2017-01-03',
},
daily_task: {
id: 5,
status: '',
task_user: '',
complete: false,
delayed: false,
delay_reason: ''
}
}
],
filter_string: '',
show_all: true
},
computed: {
visibleTasks() {
const show_all = this.show_all
let search_filter;
if(show_all){
search_filter = this.tasks
}else{
console.log(this.tasks);
search_filter = this.tasks.filter(task => {
return !task.daily_task.complete
});
}
return search_filter
}
},
methods: {
updateStatus(row){
const id = row.daily_task.id;
const complete = !row.daily_task.complete;
if (complete) {
fakeUpdateComplete(id).then(() => {
this.history.push(`Task ${row.task.name} with id ${row.daily_task.id} is marked as complete`);
row.daily_task.complete = !row.daily_task.complete;
});
} else {
fakeUpdateIncomplete(id).then(() => {
this.history.push(`Task ${row.task.name} with id ${row.daily_task.id} is marked as incomplete`);
row.daily_task.complete = !row.daily_task.complete;
});
}
/*
if(complete){
axios.get('set_task_complete/' + id)
}else{
axios.get('set_task_open/' + id)
}
*/
}
}
})
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.js"></script>
<div id="tasks-app">
<input type="checkbox" id="checkbox" v-model="show_all">
<label for="checkbox">Show all tasks</label><br>
<table class="table">
<tr><th v-for="column in table_columns" v-text="column"></th><tr>
<tr
v-for="row in visibleTasks"
:class="{danger: !row.daily_task.complete && row.daily_task.delayed, success: row.daily_task.complete}"
>
<td>{{row.task.name}}</td>
<td>{{row.task.deadline}}</td>
<td>{{row.daily_task.status}}</td>
<td>{{row.daily_task.task_user}}</td>
<td>
<input type="checkbox" v-on:click="updateStatus(row)" v-bind:checked="row.daily_task.complete">
<label for="complete">Complete</label>
</td>
<td><input v-model="row.daily_task.delay_reason" /></td>
</tr>
</table>
<div>
<div><b>Data:</b></div>
<div>{{this.tasks}}</div>
</div>
<div>
<div><b>History:</b></div>
<div v-for="item in history">
{{item}}
</div>
</div>
</div>
&#13;