Can I pass parameters in computed properties in Vu

2019-01-07 06:05发布

is this possible to pass parameter in computed properties in Vue.Js. I can see when having getters/setter using computed, they can take a parameter and assign it to a variable. like here from documentation:

// ...
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]
    }
  }
}
// ...

Is this also possible:

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

Where computed property takes a argument and returns desired output. However when I try this, I am getting this error:

vue.common.js:2250 Uncaught TypeError: fullName is not a function(…)

Should I be using methods for such cases?

7条回答
ゆ 、 Hurt°
2楼-- · 2019-01-07 06:40

You can use methods, but I prefer still to use computed properties instead of methods, if they're not mutating data or do not have external effects.

You can pass arguments to computed properties this way (not documented, but suggested by maintainers, don't remember where):

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

EDIT: Please do not use this solution, it only complicates code without any benefits.

查看更多
做自己的国王
3楼-- · 2019-01-07 06:54

Most probably you want to use a method:

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

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

Longer explanation

Technically you can use a computed property with a parameter like this:

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

(Thanks Unirgy for the base code for this.)

The difference between computed property and method is that computed properties are cached and change only when their dependencies change. A method will evaluate every time its called. There no benefits of using this approach over a computed property such a case. You can read more about this in Vue documentation https://vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods

This situation is slightly different when use Vuex. AFAIK in Vuex it's the only way to synchronously get parametrized result from the store (actions are async). Thus this approach is listed by official Vuex documentation for its getters https://vuex.vuejs.org/guide/getters.html#method-style-access

查看更多
女痞
4楼-- · 2019-01-07 06:56

Well, technically speaking we can pass a parameter to a computed function, the same way we can pass a parameter to a getter function in vuex. Such a function is a function that returns a function.

For instance, in the getters of a store:

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

This getter can be mapped to the computed functions of a component:

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

And we can use this computed function in our template as follows:

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

We can apply the same approach to create a computed method that takes a parameter.

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

And use it in our template:

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

This being said, I'm not saying here that it's the right way of doing things with Vue.

However, I could observe that when the item with the specified ID is mutated in the store, the view does refresh its contents automatically with the new properties of this item (the binding seems to be working just fine).

查看更多
太酷不给撩
5楼-- · 2019-01-07 07:01

I am not fully sure what you are trying to achieve but looks like you will be perfectly fine using method instead of computed!

查看更多
The star\"
6楼-- · 2019-01-07 07:03

Yes methods are there for using params. Like answers stated above, in your example it's best to use methods since execution is very light.

Only for reference, in a situation where the method is complex and cost is high, you can cache the results like so:

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

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

note: When using this, watchout for memory if dealing with thousands

查看更多
小情绪 Triste *
7楼-- · 2019-01-07 07:03

You can also pass arguments to getters by returning a function. This is particularly useful when you want to query an array in the store:

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

Note that getters accessed via methods will run each time you call them, and the result is not cached.

That is called Method-Style Access and it is documented on the Vue.js docs.

查看更多
登录 后发表回答