Tôi có thể truyền tham số trong thuộc tính được tính trong Vue.Js


199

điều này có thể truyền tham số trong các thuộc tính được tính trong Vue.Js. Tôi có thể thấy khi có getters / setter sử dụng tính toán, họ có thể lấy một tham số và gán nó cho một biến. như ở đây từ tài liệu :

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

Điều này cũng có thể:

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

Trong đó thuộc tính được tính có một đối số và trả về đầu ra mong muốn. Tuy nhiên, khi tôi thử điều này, tôi nhận được lỗi này:

vue.common.js: 2250 Uncaught TypeError: fullName không phải là một hàm

Tôi có nên sử dụng phương pháp cho những trường hợp như vậy?


5
Không, bạn không thể truyền tham số cho các thuộc tính được tính toán. Có, sử dụng các phương pháp là cách dễ nhất để làm điều đó.
nils

Câu trả lời:


266

Hầu hết có lẽ bạn muốn sử dụng một phương pháp

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

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

Giải thích dài hơn

Về mặt kỹ thuật, bạn có thể sử dụng một thuộc tính được tính toán với một tham số như thế này:

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

(Cảm ơn Unirgymã cơ sở cho việc này.)

Sự khác biệt giữa một thuộc tính được tính toán và một phương thức là các thuộc tính được tính toán được lưu trữ và chỉ thay đổi khi các phụ thuộc của chúng thay đổi. Một phương thức sẽ đánh giá mỗi lần nó được gọi .

Nếu bạn cần tham số, thường không có lợi ích của việc sử dụng hàm thuộc tính được tính trên một phương thức trong trường hợp đó. Mặc dù nó cho phép bạn có chức năng getter tham số được liên kết với thể hiện Vue, nhưng bạn mất bộ nhớ đệm nên thực sự không có bất kỳ lợi ích nào ở đó, trên thực tế, bạn có thể phá vỡ phản ứng (AFAIU). Bạn có thể đọc thêm về điều này trong tài liệu Vue https://vuejs.org/v2/guide/computing.html#Computing-Caching-vs-Methods

Tình huống hữu ích duy nhất là khi bạn phải sử dụng một getter và cần phải có nó. Tình huống này xảy ra trong ví dụ ở Vuex . trong Vuex, đó là cách duy nhất để nhận được kết quả tham số đồng bộ từ cửa hàng (các hành động không đồng bộ). Do đó, cách tiếp cận này được liệt kê bởi tài liệu chính thức của Vuex cho getters https://vuex.vuejs.org/guide/getters.html#method-style-access


1
Sử dụng <span v-text="fullName('Hi')"></span>thay thế, cũng hoạt động.
SalchiPapa

2
Vấn đề là <span :text="message"></span>, không còn hoạt động cho Vue 2.0, người ta phải sử dụng thay thế: <span v-text="message"></span>hoặc <span>{{ message }}</span>như được hiển thị trong codepen này: codepen.io/Ismael-VC/pen/dzGzJa
SalchiPapa

1
Bạn đúng. Tôi không nhận thấy điều này đã được thay đổi trong 2.0. Cảm ơn vì sự đúng đắn của bạn!
damienix

4
Các thuộc tính được sử dụng cú pháp getter ES5 không hỗ trợ gọi nó với bất kỳ tham số nào (không có dấu ngoặc đơn). Vì vậy, đó là giới hạn cấp độ ngôn ngữ và đó là cách nó được tích hợp vào Vue.js.
damienix

1
Xin lỗi vì phản hồi rất muộn @PedroMoreira, tôi chỉ tìm thấy một chút thời gian để phân tích điều này. Quả thực bạn đúng rằng những gì tôi viết không rõ ràng và lẫn lộn :) Tôi đã sửa câu trả lời và cố hết sức để viết lại nó để làm cho rõ ràng và chính xác hơn. Bạn có thể cho tôi biết nếu bây giờ rõ ràng. Cảm ơn.
damienix

27

Bạn có thể sử dụng các phương thức, nhưng tôi vẫn thích sử dụng các thuộc tính được tính thay vì các phương thức, nếu chúng không làm thay đổi dữ liệu hoặc không có tác động bên ngoài.

Bạn có thể chuyển các đối số cho các thuộc tính được tính theo cách này (không được ghi lại, nhưng được đề xuất bởi các nhà bảo trì, đừng nhớ ở đâu):

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

EDIT: Xin vui lòng không sử dụng giải pháp này, nó chỉ làm phức tạp mã mà không có bất kỳ lợi ích.


Nó sẽ thực sự hữu ích nếu bạn có thể cung cấp một tài liệu tham khảo. Điều này nên làm việc.
Saurabh

@saurabh xin lỗi, đó là một giải pháp cho một vấn đề không thực sự mô tả trong github và tôi không thể tìm thấy nó ngay bây giờ ...
Unirgy

Điều này hiệu quả với tôi, nhưng điều duy nhất tôi không phải là người hâm mộ là thực tế là nó trả về một hàm chứ không phải là tài sản thực tế, vì vậy các devtools của VueJS không hiển thị kết quả ở bất cứ đâu. Tôi không chắc đó là điển hình cho các thuộc tính được tính toán, nhưng nó làm cho việc khắc phục sự cố khó khăn hơn một chút.
Nate Ritter

4
Làm thế nào để nó xử lý bộ nhớ đệm? Nó sẽ hoạt động đúng khi tham số thay đổi?
damienix

Tôi không tin rằng nó sẽ lưu trữ bất cứ thứ gì bên trong hàm return. Sự khác biệt so với các phương thức sẽ hoàn toàn là quy ước (các phương thức có hiệu lực, được tính toán chỉ để truy xuất)
Unirgy

8

Vâng, về mặt kỹ thuật, chúng ta có thể truyền tham số cho hàm được tính toán, giống như cách chúng ta có thể truyền tham số cho hàm getter trong vuex. Hàm như vậy là hàm trả về hàm.

Chẳng hạn, trong các bản thu của một cửa hàng:

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

Getter này có thể được ánh xạ tới các chức năng được tính toán của một thành phần:

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

Và chúng ta có thể sử dụng hàm tính toán này trong mẫu của mình như sau:

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

Chúng ta có thể áp dụng cách tiếp cận tương tự để tạo ra một phương thức tính toán có tham số.

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

Và sử dụng nó trong mẫu của chúng tôi:

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

Điều này đang được nói, tôi không nói ở đây rằng đó là cách làm việc đúng đắn với Vue.

Tuy nhiên, tôi có thể quan sát thấy rằng khi mục có ID được chỉ định bị đột biến trong cửa hàng, chế độ xem sẽ tự động làm mới nội dung của nó với các thuộc tính mới của mục này (ràng buộc có vẻ hoạt động tốt).


Vì vậy, điều này làm việc cho tôi, không sử dụng vuex. cũng muốn biết nếu đây là một cách hợp pháp để làm các thuộc tính được tính toán.
yeahdixon

1
Trong khi điều này không hoạt động, về cơ bản, nó xử lý thuộc tính được tính giống như một phương thức. tức là nó mất các lợi ích lưu trữ của một thuộc tính được tính toán. Vì vậy, không có lợi ích thực tế bằng cách sử dụng phương pháp này. "Lưu ý rằng các getters được truy cập thông qua các phương thức sẽ chạy mỗi khi bạn gọi chúng và kết quả không được lưu trong bộ nhớ cache." Xem vuex.vuejs.org/en/getters.html
James

@ james.brndwgn nhưng tôi khá chắc chắn rằng các phương thức sẽ không được chạy lại khi dữ liệu cơ bản được thay đổi. Đó là tất cả những gì tôi thực sự tìm kiếm.
Alex

@Alex thì bạn nên sử dụng một người theo dõi. vuejs.org/v2/guide/computing.html#Watchers
James

@ james.brndwgn Tôi muốn sử dụng một tài sản được tính toán hơn là một người theo dõi nếu có thể. Tôi chỉ đưa ra vấn đề với tuyên bố của bạn: "Vì vậy, không có lợi ích thực sự bằng cách sử dụng điều này qua một phương pháp." vì có một sự khác biệt đáng kể ngay cả khi không lưu trữ.
Alex

4

Bộ lọc là một chức năng được cung cấp bởi các thành phần Vue cho phép bạn áp dụng định dạng và biến đổi cho bất kỳ phần nào của dữ liệu động mẫu của bạn.

Họ không thay đổi dữ liệu của một thành phần hoặc bất cứ điều gì, nhưng chúng chỉ ảnh hưởng đến đầu ra.

Giả sử bạn đang in tên:

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>

Lưu ý cú pháp để áp dụng bộ lọc, đó là | tên lọc. Nếu bạn quen thuộc với Unix, đó là toán tử ống Unix, được sử dụng để chuyển đầu ra của một thao tác làm đầu vào cho thao tác tiếp theo.

Thuộc tính bộ lọc của thành phần là một đối tượng. Một bộ lọc duy nhất là một hàm chấp nhận một giá trị và trả về một giá trị khác.

Giá trị được trả về là giá trị thực sự được in trong mẫu Vue.js.


3

Bạn cũng có thể truyền đối số cho getters bằng cách trả về một hàm. Điều này đặc biệt hữu ích khi bạn muốn truy vấn một mảng trong cửa hàng:

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

Lưu ý rằng getters được truy cập thông qua các phương thức sẽ chạy mỗi khi bạn gọi chúng và kết quả không được lưu trong bộ nhớ cache.

Đó được gọi là Phương pháp-Style Access và nó là tài liệu trên các tài liệu Vue.js .


2

Bạn có thể truyền tham số nhưng đó không phải là cách vue.js hoặc cách bạn đang làm là sai.

Tuy nhiên, có những trường hợp khi bạn cần làm như vậy. Tôi sẽ chỉ cho bạn một ví dụ đơn giản chuyển giá trị cho thuộc tính được sử dụng getter và setter.

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

Và kịch bản

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

Khi nhấp vào nút, chúng tôi sẽ chuyển sang thuộc tính được tính tên 'Roland' và trong đó set()chúng tôi sẽ đổi tên từ 'John Doe' thành 'Roland'.

Dưới đây có một trường hợp sử dụng phổ biến khi tính toán được sử dụng với getter và setter. Nói rằng bạn có cửa hàng vuex sau:

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

Và trong thành phần của bạn, bạn muốn thêm v-modelvào một đầu vào nhưng sử dụng cửa hàng 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

Tôi không hoàn toàn chắc chắn những gì bạn đang cố gắng để đạt được nhưng có vẻ như bạn sẽ hoàn toàn ổn khi sử dụng phương pháp thay vì tính toán!


1
computed: {
  fullName: (app)=> (salut)=> {
      return salut + ' ' + this.firstName + ' ' + this.lastName    
  }
}

khi bạn muốn sử dụng

<p>{{fullName('your salut')}}</p>

1

Tính toán có thể được xem xét có một chức năng. Vì vậy, đối với một ví dụ về định giá, bạn rõ ràng có thể làm một cái gì đó như:

    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
            }
        },
        ...
    }

Mà bạn sẽ sử dụng như:

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

Chỉ cần lưu ý rằng bạn vẫn sẽ bỏ lỡ bộ nhớ đệm cụ thể để tính toán.


0

Có phương pháp có sẵn để sử dụng params. Giống như các câu trả lời đã nêu ở trên, trong ví dụ của bạn, tốt nhất nên sử dụng các phương thức vì việc thực thi rất nhẹ.

Chỉ để tham khảo, trong trường hợp phương thức phức tạp và chi phí cao, bạn có thể lưu trữ kết quả như vậy:

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

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

lưu ý: Khi sử dụng, hãy coi chừng bộ nhớ nếu xử lý hàng ngàn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.