2017-03-08 25 views
2

Vue.js計算されたプロパティを使用していますが、問題が発生しています。計算されたメソッドISが正しい時刻に呼び出されましたが、計算されたメソッドによって返された値が無視されました! console.log文でプリントアウトVue.js計算されたプロパティが更新されない

私の方法

computed: { 
    filteredClasses() { 
     let classes = this.project.classes 
     const ret = classes && classes.map(klass => { 
      const klassRet = Object.assign({}, klass) 
      klassRet.methods = klass.methods.filter(meth => this.isFiltered(meth, klass)) 
      return klassRet 
     }) 
     console.log(JSON.stringify(ret)) 
     return ret 
    } 
} 

値は正しいですが、私はテンプレートでfilteredClassesを使用する場合、それだけで最初にキャッシュされた値を使用し、テンプレートを更新したことがありません。これはVue chrome devtools(filteredClassesは最初のキャッシング後に変更されません)によって確認されています。

誰も私にこのことが起こっている理由に関する情報を教えてもらえますか?

Project.vue

<template> 
<div> 
    <div class="card light-blue white-text"> 
     <div class="card-content row"> 
      <div class="col s4 input-field-white inline"> 
       <input type="text" v-model="filter.name" id="filter-name"> 
       <label for="filter-name">Name</label> 
      </div> 
      <div class="col s2 input-field-white inline"> 
       <input type="text" v-model="filter.status" id="filter-status"> 
       <label for="filter-status">Status (PASS or FAIL)</label> 
      </div> 
      <div class="col s2 input-field-white inline"> 
       <input type="text" v-model="filter.apkVersion" id="filter-apkVersion"> 
       <label for="filter-apkVersion">APK Version</label> 
      </div> 
      <div class="col s4 input-field-white inline"> 
       <input type="text" v-model="filter.executionStatus" id="filter-executionStatus"> 
       <label for="filter-executionStatus">Execution Status (RUNNING, QUEUED, or IDLE)</label> 
      </div> 
     </div> 
    </div> 
    <div v-for="(klass, classIndex) in filteredClasses"> 
     <ClassView :klass-raw="klass"/> 
    </div> 
</div> 
</template> 

<script> 
import ClassView from "./ClassView.vue" 

export default { 
    name: "ProjectView", 

    props: { 
     projectId: { 
      type: String, 
      default() { 
       return this.$route.params.id 
      } 
     } 
    }, 

    data() { 
     return { 
      project: {}, 
      filter: { 
       name: "", 
       status: "", 
       apkVersion: "", 
       executionStatus: "" 
      } 
     } 
    }, 

    async created() { 
     // Get initial data 
     const res = await this.$lokka.query(`{ 
      project(id: "${this.projectId}") { 
       name 
       classes { 
        name 
        methods { 
         id 
         name 
         reports 
         executionStatus 
        } 
       } 
      } 
     }`) 

     // Augment this data with latestReport and expanded 
     const reportPromises = [] 
     const reportMeta  = [] 
     for(let i = 0; i < res.project.classes.length; ++i) { 
      const klass = res.project.classes[i]; 
      for(let j = 0; j < klass.methods.length; ++j) { 
       res.project.classes[i].methods[j].expanded = false 
       const meth = klass.methods[j] 
       if(meth.reports && meth.reports.length) { 
        reportPromises.push(
         this.$lokka.query(`{ 
          report(id: "${meth.reports[meth.reports.length-1]}") { 
           id 
           status 
           apkVersion 
           steps { 
            status platform message time 
           } 
          } 
         }`) 
         .then(res => res.report) 
        ) 
        reportMeta.push({ 
         classIndex: i, 
         methodIndex: j 
        }) 
       } 
      } 
     } 

     // Send all report requests in parallel 
     const reports = await Promise.all(reportPromises) 

     for(let i = 0; i < reports.length; ++i) { 
      const {classIndex, methodIndex} = reportMeta[i] 
      res.project.classes[classIndex] 
         .methods[methodIndex] 
         .latestReport = reports[i] 
     } 

     this.project = res.project 

     // Establish WebSocket connection and set up event handlers 
     this.registerExecutorSocket() 
    }, 

    computed: { 
     filteredClasses() { 
      let classes = this.project.classes 
      const ret = classes && classes.map(klass => { 
       const klassRet = Object.assign({}, klass) 
       klassRet.methods = klass.methods.filter(meth => this.isFiltered(meth, klass)) 
       return klassRet 
      }) 
      console.log(JSON.stringify(ret)) 
      return ret 
     } 
    }, 

    methods: { 
     isFiltered(method, klass) { 
      const nameFilter = this.testFilter(
       this.filter.name, 
       klass.name + "." + method.name 
      ) 
      const statusFilter = this.testFilter(
       this.filter.status, 
       method.latestReport && method.latestReport.status 
      ) 
      const apkVersionFilter = this.testFilter(
       this.filter.apkVersion, 
       method.latestReport && method.latestReport.apkVersion 
      ) 
      const executionStatusFilter = this.testFilter(
       this.filter.executionStatus, 
       method.executionStatus 
      ) 
      return nameFilter && statusFilter && apkVersionFilter && executionStatusFilter 
     }, 
     testFilter(filter, item) { 
      item = item || "" 
      let outerRet = !filter || 
      // Split on '&' operator 
      filter.toLowerCase().split("&").map(x => x.trim()).map(seg => 
       // Split on '|' operator 
       seg.split("|").map(x => x.trim()).map(segment => { 
        let quoted = false, postOp = x => x 
        // Check for negation 
        if(segment.indexOf("!") === 0) { 
         if(segment.length > 1) { 
          segment = segment.slice(1, segment.length) 
          postOp = x => !x 
         } 
        } 
        // Check for quoted 
        if(segment.indexOf("'") === 0 || segment.indexOf("\"") === 0) { 
         if(segment[segment.length-1] === segment[0]) { 
          segment = segment.slice(1, segment.length-1) 
          quoted = true 
         } 
        } 
        if(!quoted || segment !== "") { 
         //console.log(`Item: ${item}, Segment: ${segment}`) 
         //console.log(`Result: ${item.toLowerCase().includes(segment)}`) 
         //console.log(`Result': ${postOp(item.toLowerCase().includes(segment))}`) 
        } 
        let innerRet = quoted && segment === "" ? 
         postOp(!item) : 
         postOp(item.toLowerCase().includes(segment)) 

        //console.log(`InnerRet(${filter}, ${item}): ${innerRet}`) 

        return innerRet 
       }).reduce((x, y) => x || y, false) 
      ).reduce((x, y) => x && y, true) 

      //console.log(`OuterRet(${filter}, ${item}): ${outerRet}`) 
      return outerRet 
     }, 
     execute(methID, klassI, methI) { 
      this.project.classes[klassI].methods[methI].executionStatus = "QUEUED" 
      // Make HTTP request to execute method 
      this.$http.post("/api/Method/" + methID + "/Execute") 
      .then(response => { 
      }, error => 
       console.log("Couldn't execute Test: " + JSON.stringify(error)) 
      ) 
     }, 
     registerExecutorSocket() { 
      const socket = new WebSocket("ws://localhost:4567/api/Executor/") 

      socket.onmessage = msg => { 
       const {methodID, report, executionStatus} = JSON.parse(msg.data) 

       for(let i = 0; i < this.project.classes.length; ++i) { 
        const klass = this.project.classes[i] 
        for(let j = 0; j < klass.methods.length; ++j) { 
         const meth = klass.methods[j] 
         if(meth.id === methodID) { 
          if(report) 
           this.project.classes[i].methods[j].latestReport = report 
          if(executionStatus) 
           this.project.classes[i].methods[j].executionStatus = executionStatus 
          return 
         } 
        } 
       } 
      } 
     }, 
     prettyName: function(name) { 
      const split = name.split(".") 
      return split[split.length-1] 
     } 
    }, 

    components: { 
     "ClassView": ClassView 
    } 
} 
</script> 

<style scoped> 
</style> 
+0

'filtered.Classes'メソッドが' project.classes'データが変更されるたびに実行されていますが、戻り値 'ret'は更新されません。 – Adam

+0

@Adamローカル変数 'ret'が正しく変更されています。 Vueはその値を取っておらず、 'vm.computed.filteredClasses'を更新していません –

+0

' console.log(JSON.stringify(ret)) 'は正しい値を示していますが、' return ret'は壊れているというのは非常に奇妙です。何か他のことが起こっている必要があります、そこに問題がある必要はありません。あなたが "' filteredClasses'が最初のキャッシュの後に決して変化しないと言うとき。あなたはどういう意味ですか? UIでは?最後に、あなたは 'filteredClasses'とも呼ばれるメソッドやデータプロパティを持っていないのでしょうか? – Adam

答えて

3

私は前に同様の問題に遭遇して、代わりに計算されたプロパティの定期的な方法を使って、それを解決してきました。メソッドにすべてを移動し、あなたのretを返します。 Official docs.

+1

リンクには、comp。プロパティとメソッド。メソッドを使用するとこの問題は解決する可能性がありますが、メソッドではキャッシュを使用しないため理想的なソリューションではありません。 –

+2

ありがとう!私は 'this。$ forceUpdate()'も使用しました。 – Ehvince

0

v-forのリスト項目に一意のキー値を割り当てる必要があります。そうですね。

<ClassView :klass-raw="klass" :key="klass.id"/> 

そうしないと、Vueはどのアイテムを流失させるのかわかりません。ここでの説明https://vuejs.org/v2/guide/list.html#key

関連する問題