在 Vue 中反跳计算属性/getter

Posted

技术标签:

【中文标题】在 Vue 中反跳计算属性/getter【英文标题】:Debounce computed properties/getters in Vue 【发布时间】:2017-11-30 01:20:16 【问题描述】:

我似乎无法去抖动(lodash)计算属性或 vuex getter。去抖动的函数总是返回 undefined。

https://jsfiddle.net/guanzo/yqk0jp1j/2/

html

<div id="app">
  <input v-model="text">
  <div>computed:  textComputed  </div>
  <div>debounced:  textDebounced  </div>
</div>

JS:

new Vue(
    el:'#app',
  data:
    text:''
  ,
  computed:
    textDebounced: _.debounce(function()
      return this.text
    ,500),
    textComputed()
        return this.text
    
  

)

【问题讨论】:

您对替代解决方案持开放态度还是要求将去抖动应用于计算项? 好吧,我想知道为什么它不起作用,但是你确定你有什么样的替代解决方案? 看看这个有趣的小提琴:jsfiddle.net/yqk0jp1j/3 去抖动是一种控制函数调用频率的方法。它本质上是异步的,不能返回值。这就是为什么它不能用于计算。 您到底想在这里尝试什么? _.debounce 本身没有任何返回值,因此您当然会看到 undefined 作为结果。内部函数内的去抖动返回值被丢弃了。 【参考方案1】:

我不知道为什么 debounce 函数不适用于计算属性。但是,另一种解决方案是将 debounce 放在 methods 部分中的函数上,并通过 watch 调用它。

https://jsfiddle.net/vsc4npv3/

HTML:

<div id="app">
<input v-model="text">
<div>computed:  textComputed  </div>
<div>debounced:  debouncedText  </div>
</div>

javascript

var x = new Vue(
    el:'#app',
  data:
    text:'',
    debouncedText: ''
  ,
  watch: 
    text: function (val) 
        this.debouncer();
    
  ,
  computed:
    textComputed()
        return this.text;
    
  ,
  methods: 
    debouncer: _.debounce(function()
      this.debouncedText = this.text;
    ,500)
  

)

【讨论】:

【参考方案2】:

正如我在评论中提到的,去抖动本质上是异步操作,因此不能返回值。根据您的需要,您可能希望在 input 端进行去抖动。 text中的值和textComputed中的值没有区别,但是如果你v-model="textComputed",值设置会去抖动。

如果您特别想要变量的去抖动版本,mrogers 提供了一个很好的解决方案。

var x = new Vue(
  el: '#app',
  data: 
    text: 'start'
  ,
  computed: 
    textComputed: 
      get() 
        return this.text;
      ,
      set: _.debounce(function(newValue) 
        this.text = newValue;
      , 500)
    
  
)
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<div id="app">
  <div>
    Debounced input:
    <input v-model="textComputed">
  </div>
  <div>
    Immediate input:
    <input v-model="text">
  </div>
  <div>computed:  textComputed  </div>
  <div>debounced:  text  </div>
</div>

【讨论】:

我主要想知道为什么它不起作用,谢谢。我没有对输入进行去抖动,这只是我的示例,我只是想以某种方式延迟计算的属性值。 你有推荐的 Vuex 方法吗? (例如,在存储值上使用双向绑定,设置调用提交?设置调用动作并让动作去抖动提交?) @SumNeuron 这取决于您要实现的目标。使用 Vuex,动作可以是异步的,所以你可以在那里去抖动。突变必须是同步的,所以不存在。 @RoyJ 我有一个文本字段,更改后会切换需要一段时间的计算...在玩具示例中,这不是问题,但不能很好地适应正常的人类打字速度...所以最好对商店的状态进行去抖动,这是绑定到文本输入的当前 2-way 形式... 您可以改用.lazy,但是可以,您可以取消设置操作。【参考方案3】:
    简单 没有外部依赖(如_.debounce) 为 Vue 量身定制
import Vue from 'vue'

// Thanks to https://github.com/vuejs-tips/v-debounce/blob/master/debounce.js
function debounce(fn, delay) 
  var timeoutID = null
  return function () 
    clearTimeout(timeoutID)
    var args = arguments
    var that = this
    timeoutID = setTimeout(function () 
      fn.apply(that, args)
    , delay)
  


function debouncedProperty(delay) 
  let observable = Vue.observable( value: undefined );
  return 
    get()  return observable.value; ,
    set: debounce(function (newValue)  observable.value = newValue; , delay)
  


// component
export default 
  computed: 
    myProperty: debouncedProperty(300),
  ,

【讨论】:

以上是关于在 Vue 中反跳计算属性/getter的主要内容,如果未能解决你的问题,请参考以下文章

使用 Getter 和 Setter 计算的 Vue 属性不会在 Webpack 中编译

Vue 计算属性

vue的计算和监视属性,附一小实例

vue计算属性的getter和setter以及set方法的使用

vue_计算属性getter和setter方法

vue 计算属性的setter getter