ฉันสามารถส่งผ่านพารามิเตอร์ในคุณสมบัติที่คำนวณได้ใน Vue.Js


199

เป็นไปได้ที่จะผ่านพารามิเตอร์ในคุณสมบัติที่คำนวณได้ใน 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    
  }
}
// ...

ที่ซึ่งคุณสมบัติที่คำนวณได้รับการโต้แย้งและส่งกลับผลลัพธ์ที่ต้องการ อย่างไรก็ตามเมื่อฉันลองทำสิ่งนี้ฉันได้รับข้อผิดพลาดนี้:

vue.common.js: 2250 TypeError Uncaught: fullName ไม่ใช่ฟังก์ชัน (…)

ฉันควรใช้วิธีการสำหรับกรณีเช่นนี้หรือไม่?


5
ไม่คุณไม่สามารถส่งพารามิเตอร์ไปยังคุณสมบัติที่คำนวณได้ ใช่การใช้วิธีการเป็นวิธีที่ง่ายที่สุดในการทำ
nils

คำตอบ:


270

ส่วนใหญ่คุณอาจต้องการใช้วิธีการ

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

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

คำอธิบายอีกต่อไป

ในทางเทคนิคคุณสามารถใช้คุณสมบัติที่คำนวณได้ด้วยพารามิเตอร์ดังนี้:

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

(ขอบคุณUnirgyสำหรับรหัสฐานสำหรับสิ่งนี้)

ความแตกต่างระหว่างคุณสมบัติที่คำนวณได้และวิธีการคือคุณสมบัติที่คำนวณได้ถูกแคชและเปลี่ยนเฉพาะเมื่อการอ้างอิงของพวกเขาเปลี่ยนไป วิธีการจะประเมินทุกครั้งก็เรียกว่า

หากคุณต้องการพารามิเตอร์มักจะไม่มีประโยชน์ในการใช้ฟังก์ชั่นคุณสมบัติที่คำนวณได้เหนือวิธีการในกรณีเช่นนี้ แม้ว่ามันจะช่วยให้คุณมีฟังก์ชั่นทะลุทะลวง parametrized ผูกพันกับอินสแตนซ์ Vue คุณสูญเสียแคชดังนั้นไม่ได้รับจริง ๆ ที่นั่นในความเป็นจริงคุณอาจทำลายปฏิกิริยา (AFAIU) คุณสามารถอ่านเพิ่มเติมเกี่ยวกับสิ่งนี้ได้ในเอกสาร Vue https://vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods

สถานการณ์ที่มีประโยชน์เพียงอย่างเดียวคือเมื่อคุณต้องใช้ผู้ทะเยอทะยานและจำเป็นต้องทำให้เป็นอันตราย ตัวอย่างเช่นสถานการณ์นี้เกิดขึ้นในVuex ใน Vuex เป็นวิธีเดียวที่จะได้รับผลลัพธ์แบบขนานจากร้านค้า ดังนั้นวิธีการนี้จะแสดงรายการโดยเอกสารทางการของ Vuex สำหรับ getters 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>ดังที่แสดงใน codepen นี้: codepen.io/Ismael-VC/pen/dzGzJa
SalchiPapa

1
คุณถูก. ฉันไม่ได้สังเกตว่ามันถูกเปลี่ยนแปลงใน 2.0 ขอบคุณสำหรับการแก้ไข!
damienix

4
คุณสมบัติที่คำนวณได้ใช้ไวยากรณ์ ES5 getter ซึ่งไม่สนับสนุนการเรียกมันด้วยพารามิเตอร์ใด ๆ (ไม่มีวงเล็บ) ดังนั้นจึงเป็นข้อ จำกัด ในระดับภาษาและเป็นวิธีที่รวมเข้ากับ Vue.js
damienix

1
ขออภัยสำหรับการตอบกลับช้ามาก @PedroMoreira ฉันเพิ่งพบเวลาวิเคราะห์ แน่นอนคุณถูกต้องว่าสิ่งที่ฉันเขียนไม่ชัดเจนและสับสน :) ฉันแก้ไขคำตอบและพยายามอย่างดีที่สุดที่จะใช้ถ้อยคำใหม่เพื่อให้ชัดเจนและแม่นยำยิ่งขึ้น คุณสามารถแจ้งให้เราทราบหากมันชัดเจนในขณะนี้ ขอบคุณ
damienix

27

คุณสามารถใช้วิธีการได้ แต่ฉันยังต้องการใช้คุณสมบัติที่คำนวณได้แทนวิธีการหากพวกเขาไม่ได้กลายพันธุ์ข้อมูลหรือไม่มีผลกระทบภายนอก

คุณสามารถส่งข้อโต้แย้งไปยังคุณสมบัติที่คำนวณได้ด้วยวิธีนี้ (ไม่ใช่เอกสาร แต่แนะนำโดยผู้ดูแลอย่าจำที่):

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

แก้ไข: โปรดอย่าใช้วิธีนี้มันซับซ้อนเพียงรหัสโดยไม่มีผลประโยชน์ใด ๆ


มันจะมีประโยชน์จริง ๆ ถ้าคุณสามารถให้การอ้างอิง สิ่งนี้น่าจะใช้ได้
Saurabh

@saurabh ขอโทษมันเป็นทางออกสำหรับปัญหาที่ไม่สามารถอธิบายจริงๆใน GitHub และฉันไม่สามารถหาได้ในขณะนี้ ...
Unirgy

สิ่งนี้ใช้ได้ผลสำหรับฉัน แต่สิ่งเดียวที่ฉันไม่ใช่แฟนของคือความจริงที่ว่ามันส่งคืนฟังก์ชั่นมากกว่าคุณสมบัติจริงดังนั้น VueJS devtools จึงไม่แสดงผลลัพธ์ใด ๆ ฉันไม่แน่ใจว่าเป็นเรื่องปกติของคุณสมบัติที่คำนวณหรือไม่ แต่มันทำให้การแก้ไขปัญหายากขึ้นเล็กน้อย
Nate Ritter

4
มันจัดการกับแคชอย่างไร มันจะทำงานอย่างถูกต้องเมื่อพารามิเตอร์เปลี่ยนไปหรือไม่
damienix

ฉันไม่เชื่อว่ามันจะแคชอะไรในฟังก์ชันส่งคืน ความแตกต่างจากวิธีการจะเป็นของการประชุมอย่างหมดจด (วิธีการที่มีผลกระทบคำนวณได้เฉพาะสำหรับการดึง)
Unirgy

8

ในทางเทคนิคแล้วเราสามารถส่งพารามิเตอร์ไปยังฟังก์ชันที่คำนวณได้เช่นเดียวกับที่เราสามารถส่งพารามิเตอร์ไปยังฟังก์ชัน getter ใน vuex ฟังก์ชั่นดังกล่าวเป็นฟังก์ชั่นที่ส่งกลับฟังก์ชั่น

ตัวอย่างเช่นใน getters ของร้านค้า:

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

ทะเยอทะยานนี้สามารถแมปกับฟังก์ชั่นการคำนวณขององค์ประกอบ:

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 ที่ระบุถูกเปลี่ยนแปลงในร้านค้ามุมมองจะรีเฟรชเนื้อหาโดยอัตโนมัติด้วยคุณสมบัติใหม่ของรายการนี้ (การเชื่อมโยงดูเหมือนว่าจะทำงานได้ดี)


woah ดังนั้นสิ่งนี้ได้ผลสำหรับฉันไม่ใช่การใช้ vuex ยังต้องการที่จะรู้ว่านี่เป็นวิธีที่ถูกต้องในการทำคุณสมบัติคำนวณ
yeahdixon

1
ในขณะที่มันใช้งานได้จริง ๆ แล้วมันก็จะปฏิบัติต่อคุณสมบัติที่คำนวณเช่นเดียวกับวิธีการ เช่นสูญเสียผลประโยชน์การแคชของคุณสมบัติที่คำนวณ ดังนั้นจึงไม่มีผลประโยชน์ที่แท้จริงจากการใช้วิธีนี้ "โปรดทราบว่าผู้เข้าถึงที่เข้าถึงด้วยวิธีจะทำงานทุกครั้งที่คุณโทรหาและผลลัพธ์จะไม่ถูกแคช" ดูvuex.vuejs.org/en/getters.html
James

@ james.brndwgn แต่ฉันค่อนข้างมั่นใจว่าวิธีการจะไม่ถูกเรียกใช้อีกครั้งเมื่อมีการเปลี่ยนแปลงข้อมูลพื้นฐาน นั่นคือทั้งหมดที่ฉันกำลังมองหา
Alex

@ Alex แล้วคุณควรใช้ watcher vuejs.org/v2/guide/computed.html#Watchers
James

@ james.brndwgn ฉันอยากจะใช้คุณสมบัติที่คำนวณได้มากกว่าผู้เฝ้าดูถ้าเป็นไปได้ ฉันเพิ่งจะมีปัญหากับคำสั่งของคุณ: "ดังนั้นไม่มีการใช้วิธีนี้ผ่านวิธีการ" เนื่องจากมีความแตกต่างที่สำคัญแม้ไม่มีแคช
อเล็กซ์

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

คุณสามารถส่งผ่านอาร์กิวเมนต์ไปยังผู้ได้รับโดยส่งคืนฟังก์ชัน สิ่งนี้มีประโยชน์อย่างยิ่งเมื่อคุณต้องการสอบถามอาเรย์ในร้านค้า:

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

โปรดทราบว่า getters เข้าถึงได้ด้วยวิธีการจะทำงานทุกครั้งที่คุณเรียกพวกเขาและผลลัพธ์จะไม่แคช

ที่เรียกว่าวิธีการสไตล์การเข้าถึงและได้รับการบันทึกในเอกสาร Vue.js


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 สมมติว่าคุณมีร้านค้า 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 store

<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

ฉันไม่แน่ใจว่าสิ่งที่คุณพยายามที่จะบรรลุ แต่ดูเหมือนว่าคุณจะดีอย่างสมบูรณ์โดยใช้วิธีการแทนการคำนวณ!



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];
    }
}

หมายเหตุ: เมื่อใช้สิ่งนี้ระวังหน่วยความจำหากจัดการกับหลักพัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.