代码之家  ›  专栏  ›  技术社区  ›  hirolau

Vue.js中的模型和计算属性交互

  •  0
  • hirolau  · 技术社区  · 9 年前

    当用户单击“完成”复选框时,我希望发生两件事:

    1. 如果未选中“显示所有任务”,则隐藏任务。
    2. 向服务器发送ajax请求,将任务标记为完成/打开。

    <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>
    

    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)
          }
        }
    
      }
    
    })
    

    updateStatus 函数被调用。

    但是,如果未选中show all复选框,则会触发visibleTasks,并且 更新状态 调用时,将错误的行传递给 更新状态 作用

    更新状态

    3 回复  |  直到 9 年前
        1
  •  1
  •   François Romain    9 年前

    如果将逻辑分离开来,可以大大简化:

    1. 循环每个任务(完成或未完成)以显示它们(不考虑 show_all
    2. 使用更新任务 v-on:click="updateStatus(row)"
    3. tr 添加 v-show="show_all || !row.status.complete"
        2
  •  1
  •   Giap Nguyen    9 年前

    <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)
        }
    
        3
  •  1
  •   kevguy    9 年前

    1. 你不应该使用 v-on:change ,而使用 <input type="checkbox" v-on:click="updateStatus(row)" v-bind:checked="row.daily_task.complete">

    2. 不更新 row.daily_task.complete

    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)
          }
          */
        }
    
      }
    
    })
    <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>
    推荐文章