我可以在Vue.Js的计算属性中传递参数吗


198

这有可能在Vue.Js中的计算属性中传递参数。我可以看到在使用getters / setter进行计算时,他们可以采用参数并将其分配给变量。就像这里的文档

// ...
computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}
// ...

这也是可能的:

// ...
computed: {
  fullName: function (salut) {
      return salut + ' ' + this.firstName + ' ' + this.lastName    
  }
}
// ...

其中,calculated属性接受一个参数并返回所需的输出。但是,当我尝试此操作时,出现此错误:

vue.common.js:2250未捕获的TypeError:fullName不是函数(…)

我应该在这种情况下使用方法吗?


4
不,您不能将参数传递给计算的属性。是的,使用方法是最简单的方法。
nils

Answers:


265

您最有可能想要使用一种方法

<span>{{ fullName('Hi') }}</span>

methods: {
  fullName(salut) {
      return `${salut} ${this.firstName} ${this.lastName}`
  }
}

更长的解释

从技术上讲,您可以将计算属性与如下参数一起使用:

computed: {
   fullName() {
      return salut => `${salut} ${this.firstName} ${this.lastName}`
   }
}

Unirgy为此感谢基本代码。)

计算属性和方法之间的区别在于,计算属性将被缓存并仅在其依赖项更改时更改。一个方法将评估每一个,它被称为时间

如果需要参数,在这种情况下,使用计算属性函数比使用方法通常没有任何好处。尽管它使您可以将参数化的getter函数绑定到Vue实例,但是您会丢失缓存,因此实​​际上并没有任何收获,实际上,您可能会破坏反应性(AFAIU)。您可以在Vue文档https://vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods中阅读有关此内容的更多信息。

唯一有用的情况是必须使用吸气剂并对其进行参数设置。这种情况例如发生在Vuex中。在Vuex中,这是从商店同步获取参数化结果的唯一方法(动作是异步的)。因此,Vuex官方文档为其吸气剂列出了这种方法 https://vuex.vuejs.org/guide/getters.html#method-style-access


1
使用<span v-text="fullName('Hi')"></span>替代,也适用。
SalchiPapa

2
问题是<span :text="message"></span>,不再适用于Vue 2.0,必须改为使用:<span v-text="message"></span><span>{{ message }}</span>如本代码
SalchiPapa

1
你是对的。我没注意到这在2.0中已更改。感谢您的指正!
damienix

4
计算属性使用ES5 getter语法,该语法不支持使用任何参数调用它(没有括号)。因此,这是语言级别的限制,这就是将其合并到Vue.js中的方式。
damienix

1
对不起,@ PedroMoreira的回复很晚,我才找到时间来对此进行分析。的确,我写的内容不清楚并不清楚,这是正确的:)我固定了答案,并竭尽全力改写该答案,以使内容更加清楚和准确。您可以让我知道现在是否清楚。谢谢。
damienix '19

27

您可以使用方法,但是如果它们不变异数据或没有外部影响,我还是更喜欢使用计算属性而不是方法。

您可以通过这种方式将参数传递给计算属性(未记录,但由维护人员建议,不记得在哪里):

computed: {
   fullName: function () {
      var vm = this;
      return function (salut) {
          return salut + ' ' + vm.firstName + ' ' + vm.lastName;  
      };
   }
}

编辑:请不要使用此解决方案,它只会使代码复杂,没有任何好处。


如果您可以提供参考,将会非常有帮助。这应该工作。
萨拉巴

@saurabh对不起,这是一个针对github中的描述性问题的解决方案,我现在找不到它……
Unirgy

这对我有用,但是我不喜欢的唯一事实是它返回的是函数而不是实际的属性,因此VueJS devtools不会在任何地方显示结果。我不确定这是否是计算属性的典型值,但这会使疑难解答变得更加困难。
Nate Ritter

4
它如何处理缓存?参数更改后是否可以正常工作?
damienix

我不认为它会在return函数中缓存任何内容。与方法的区别纯属惯例(方法有效,计算仅用于检索)
Unirgy

8

好吧,从技术上讲,我们可以将参数传递给计算函数,就像我们将参数传递给vuex中的getter函数一样。这样的函数是返回函数的函数。

例如,在商店的吸气剂中:

{
  itemById: function(state) {
    return (id) => state.itemPool[id];
  }
}

该getter可以映射到组件的计算函数:

computed: {
  ...mapGetters([
    'ids',
    'itemById'
  ])
}

我们可以在模板中使用此计算函数,如下所示:

<div v-for="id in ids" :key="id">{{itemById(id).description}}</div>

我们可以应用相同的方法来创建带有参数的计算方法。

computed: {
  ...mapGetters([
    'ids',
    'itemById'
  ]),
  descriptionById: function() {
    return (id) => this.itemById(id).description;
  }
}

并在我们的模板中使用它:

<div v-for="id in ids" :key="id">{{descriptionById(id)}}</div>

话虽这么说,但我并不是在这里说这是使用Vue做事的正确方法。

但是,我可以观察到在商店中对具有指定ID的商品进行了更改时,视图会使用该商品的新属性自动刷新其内容(绑定似乎工作得很好)。


哇,这对我有用,不使用vuex。还想知道这是否是进行计算属性的合法方法。
yeahdixon

1
尽管这确实起作用,但它实际上将计算的属性与方法相同。也就是说,它失去了计算属性的缓存优势。因此,使用这种方法无法获得实际收益。“请注意,通过方法访问的getter会在您每次调用它们时运行,并且结果不会被缓存。” 参见vuex.vuejs.org/en/getters.html
James

@ james.brndwgn,但是我很确定在更改基础数据时不会重新运行方法。这就是我真正想要的。
Alex

@Alex,那么您应该使用观察者。vuejs.org/v2/guide/computed.html#Watchers
詹姆斯

@ james.brndwgn如果可能的话,我宁愿使用计算属性,也不愿使用监视程序。我只是对您的陈述表示怀疑:“因此,通过某种方法使用此方法并没有实际收益。” 因为即使没有缓存也存在很大的差异。
Alex

4

过滤器是Vue组件提供的功能,可让您将格式和转换应用于模板动态数据的任何部分。

它们不会更改组件的数据或其他任何内容,而只会影响输出。

假设您正在打印名称:

new Vue({
  el: '#container',
  data() {
    return {
      name: 'Maria',
      lastname: 'Silva'
    }
  },
  filters: {
    prepend: (name, lastname, prefix) => {
      return `${prefix} ${name} ${lastname}`
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="container">
  <p>{{ name, lastname | prepend('Hello') }}!</p>
</div>

请注意应用过滤器的语法,即|。filterName。如果您熟悉Unix,那就是Unix管道运算符,该运算符用于将操作的输出作为输入传递给下一个操作。

组件的滤镜属性是一个对象。单个过滤器是一个接受一个值并返回另一个值的函数。

返回的值是Vue.js模板中实际打印的值。


3

您还可以通过返回函数将参数传递给getter。当您要查询存储中的数组时,这特别有用:

getters: {
  // ...
  getTodoById: (state) => (id) => {
    return state.todos.find(todo => todo.id === id)
  }
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }

请注意,通过方法访问的getter将在每次调用它们时运行,并且结果不会被缓存。

这称为“方法样式访问”,并记录在Vue.js docs中


2

您可以传递参数,但这不是vue.js方式,或者您做的方式是错误的。

但是在某些情况下需要这样做。我将向您展示一个简单的示例,该示例使用getter和setter将值传递给计算属性。

<template>
    <div>
        Your name is {{get_name}} <!-- John Doe at the beginning -->
        <button @click="name = 'Roland'">Change it</button>
    </div>
</template>

和脚本

export default {
    data: () => ({
        name: 'John Doe'
    }),
    computed:{
        get_name: {
            get () {
                return this.name
            },
            set (new_name) {
                this.name = new_name
            }
        },
    }    
}

单击该按钮时,我们将传递给计算属性“ Roland”,然后set()将名称从“ John Doe”更改为“ Roland”。

在下面的示例中,有一种常见的使用情况,即与getter和setter一起使用Calculation时。假设您拥有以下vuex商店:

export default new Vuex.Store({
  state: {
    name: 'John Doe'
  },
  getters: {
    get_name: state => state.name
  },
  mutations: {
    set_name: (state, payload) => state.name = payload
  },
})

在您的组件中,您想v-model使用vuex存储添加到输入中。

<template>
    <div>
        <input type="text" v-model="get_name">
        {{get_name}}
    </div>
</template>
<script>
export default {
    computed:{
        get_name: {
            get () {
                return this.$store.getters.get_name
            },
            set (new_name) {
                this.$store.commit('set_name', new_name)
            }
        },
    }    
}
</script>



1

计算可以考虑具有功能。因此,对于检定的一个例子,您可以明确地执行以下操作:

    methods: {
        validation(attr){
            switch(attr) {
                case 'email':
                    const re = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
                    return re.test(this.form.email);
                case 'password':
                    return this.form.password.length > 4
            }
        },
        ...
    }

您将使用的类似:

  <b-form-input
            id="email"
            v-model="form.email"
            type="email"
            :state="validation('email')"
            required
            placeholder="Enter email"
    ></b-form-input>

请记住,您仍然会错过特定于计算的缓存。


0

是的,那里有使用参数的方法。像上面提到的答案一样,在您的示例中,最好使用方法,因为执行非常轻便。

仅供参考,在方法复杂且成本高的情况下,可以缓存结果,如下所示:

data() {
    return {
        fullNameCache:{}
    };
}

methods: {
    fullName(salut) {
        if (!this.fullNameCache[salut]) {
            this.fullNameCache[salut] = salut + ' ' + this.firstName + ' ' + this.lastName;
        }
        return this.fullNameCache[salut];
    }
}

注意:使用此功能时,如果要处理数千个内存,请注意内存

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.