Skip to content

ویژگی های کامپیوتد

مثال پایه

عباراتی که در تمپلیت استفاده می شوند بسیار راحت هستند، اما برای عملیات‌های ساده طراحی شده‌اند. قرار دادن منطق بیش از حد در قالب‌های شما ممکن است باعث ناخوانی و دشواری در نگهداری کد ها شود. به عنوان مثال، اگر یک شیء با یک آرایه تو در تو داشته باشیم:

js
export default {
  data() {
    return {
      author: {
        name: 'John Doe',
        books: [
          'Vue 2 - Advanced Guide',
          'Vue 3 - Basic Guide',
          'Vue 4 - The Mystery'
        ]
      }
    }
  }
}
js
const author = reactive({
  name: 'John Doe',
  books: [
    'Vue 2 - Advanced Guide',
    'Vue 3 - Basic Guide',
    'Vue 4 - The Mystery'
  ]
})

و میخواهیم پیام‌های مختلفی را بر اساس اینکه آیا author قبلاً کتابی داشته یا نه نمایش دهیم:

template
<p>Has published books:</p>
<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>

در این نقطه، قالب کمی پیچیده شده است.باید وقت بیشتری برای درک کد صرف کنیم که متوجه شویم شرط بر اساس author.books یک محاسبه انجام می‌دهد. مهمتر از این، اگر نیاز باشد که این محاسبه را بیش از یک بار در قالب استفاده کنیم، احتمالاً نمی خواهیم یک کد را چندین بار بنویسیم.

به همین دلیل است که وقتی منطق پیچیده و داده‌های داینامیک داریم ، استفاده از ویژگی کامپیوتد توصیه می‌شود. در اینجا همان مثال، بازسازی شده است:

js
export default {
  data() {
    return {
      author: {
        name: 'John Doe',
        books: [
          'Vue 2 - Advanced Guide',
          'Vue 3 - Basic Guide',
          'Vue 4 - The Mystery'
        ]
      }
    }
  },
  computed: {
    // a computed getter
    publishedBooksMessage() {
      // `this` points to the component instance
      return this.author.books.length > 0 ? 'Yes' : 'No'
    }
  }
}
template
<p>Has published books:</p>
<span>{{ publishedBooksMessage }}</span>

امتحان کنید

در اینجا ما یک ویژگی محاسبه‌شده به نام publishedBooksMessage داریم. سعی کنید مقدار آرایه books را تغییر دهید و خواهید دید که publishedBooksMessage متناسب با آن تغییر می‌کند.

ویژگی‌های کامپیوتد را می‌توان در قالب‌ها همانند یک ویژگی عادی استفاده کرد. Vue به طور خودکار متوجه می‌شود که ویژگی کامپیوتد وابسته به یک یا چند ویژگی دیگر است. بنابراین، هرگاه ویژگی‌های وابسته تغییر کنند، ویژگی کامپیوتد نیز به‌روز می‌شود.

همچنین ببینید: Typing Computed

vue
<script setup>
import { reactive, computed } from 'vue'

const author = reactive({
  name: 'John Doe',
  books: [
    'Vue 2 - Advanced Guide',
    'Vue 3 - Basic Guide',
    'Vue 4 - The Mystery'
  ]
})

// a computed ref
const publishedBooksMessage = computed(() => {
  return author.books.length > 0 ? 'Yes' : 'No'
})
</script>

<template>
  <p>Has published books:</p>
  <span>{{ publishedBooksMessage }}</span>
</template>

امتحان کنید

در اینجا یک ویژگی کامپیوتد به نام publishedBooksMessage تعریف کرده‌ایم. تابع computed() انتظار دارد که یک تابع گرفته که مقدار بازگشتی آن از نوع computed ref باشد. مشابه ref های عادی، شما می‌توانید به نتیجه محاسبه شده با عنوان publishedBooksMessage.value دسترسی پیدا کنید. Computed ref ها همچنین در قالب‌ها به صورت خودکار از حالت بسته خارج می‌شوند، بنابراین می‌توانید بدون نیاز به .valueبه آنها دسترسی پیدا کنید.

یک ویژگی کامپیوتد به طور خودکار وابستگی‌های متغیر خود را دنبال می‌کند. Vue میداند که محاسبه publishedBooksMessage به author.books وابستگی دارد، بنابراین هنگامی که author.books تغییر می‌کند، هر اتصالی که به publishedBooksMessage وابسته باشد، به‌روزرسانی می‌شود.

همچنین ببینید: Typing Computed

تفاوت کشینگ در کامپیوتد ها و متد ها

ممکن است متوجه شده باشید که می‌توانیم با فراخوانی یک متد هم به همان نتیجه برسیم.

template
<p>{{ calculateBooksMessage() }}</p>
js
// in component
methods: {
  calculateBooksMessage() {
    return this.author.books.length > 0 ? 'Yes' : 'No'
  }
}
js
// in component
function calculateBooksMessage() {
  return author.books.length > 0 ? 'Yes' : 'No'
}

به جای یک ویژگی کامپیوتد، می توانیم همان تابع را به عنوان یک متد تعریف کنیم. نتیجه نهایی این دو رویکرد دقیقاً یکسان است. با این حال، تفاوت این است که ویژگی های کامپیوتد بر اساس وابستگی های متغیر، کش می شوند. یک ویژگی کامپیوتد تنها زمانی دوباره ارزیابی می شود که برخی از وابستگی های متغیر آن تغییر کرده باشند. این بدان معناست که تا زمانی که author.books تغییر نکرده باشد، دسترسی به publishedBooksMessage نتیجه کامپیوتد قبلی را برمی گرداند ، بدون نیاز به اجرای مجدد تابع getter .

این به این معناهم هست که ویژگی محاسبه‌شده زیر هیچ وقت به‌روز نمی‌شود، زیرا Date.now() یک وابستگی متغیر نمی‌باشد.

js
computed: {
  now() {
    return Date.now()
  }
}
js
const now = computed(() => Date.now())

در مقایسه با ویژگی‌های کامپیوتد، فراخوانی متدها همیشه باعث اجرای تابع مربوطه می‌شود، حتی اگر هیچ یک از ویژگی‌های وابسته تغییر نکرده باشند.

چرا به کش نیاز داریم؟ تصور کنید ما یک لیست داریم که یک ویژگی کامپیوتد دارد که نیاز به انجام محاسبات زیادی دارد. سپس ممکن است ویژگی‌های کامپیوتد دیگری داشته باشیم که به نوبه خود به این لیست وابسته باشند. بدون کش، ما تابع دریافت کننده لیست را بیشتر از تعداد مورد نیاز اجرا می‌کنیم! در مواردی که نیاز به کش ندارید، به جای آن از فراخوانی متد استفاده کنید.

کامپیوتد قابل تغییر

ویژگی‌های کامپیوتد به طور پیش‌فرض فقط امکان دریافت مقدار را دارند. اگر سعی کنید مقدار جدیدی به یک ویژگی کامپیوتد اختصاص دهید، یک هشدار در زمان اجرا دریافت خواهید کرد. در موارد نادری که نیاز به "ویژگی کامپیوتد قابل تغییر" دارید، می‌توانید با ارائه همزمان یک تابع getter و یک تابع setter برای آن ، یکی ایجاد کنید.

js
export default {
  data() {
    return {
      firstName: 'John',
      lastName: 'Doe'
    }
  },
  computed: {
    fullName: {
      // getter
      get() {
        return this.firstName + ' ' + this.lastName
      },
      // setter
      set(newValue) {
        // Note: we are using destructuring assignment syntax here.
        [this.firstName, this.lastName] = newValue.split(' ')
      }
    }
  }
}

اکنون هنگام اجرای this.fullName = 'John Doe'، تابع setter فراخوانی خواهد شد و به تبع آن this.firstName و this.lastName به‌روزرسانی می شوند.

vue
<script setup>
import { ref, computed } from 'vue'

const firstName = ref('John')
const lastName = ref('Doe')

const fullName = computed({
  // getter
  get() {
    return firstName.value + ' ' + lastName.value
  },
  // setter
  set(newValue) {
    // Note: we are using destructuring assignment syntax here.
    [firstName.value, lastName.value] = newValue.split(' ')
  }
})
</script>

وقتی شما دستور fullName.value = 'John Doe' را اجرا کنید، تابع setter فراخوانی خواهد شد و firstName و lastName به‌طور متناسب به‌روزرسانی می شوند.

بهترین روش ها

توابع getter باید فقط مقدار مورد نظر را برگردانند و تغییر دیگری در برنامه ایجاد نکنند.

مهم است به یاد داشته باشید که توابع getter کامپیوتد فقط باید محاسبات خالص را انجام دهند . به عبارت دیگر، درون تابع getter ، از درخواست‌های async یا تغییر DOM استفاده نکنید! به ویژگی کامپیوتد به عنوان یک راه ساده برای محاسبه یک مقدار بر اساس مقادیر دیگر نگاه کنید - مسئولیت اصلی آن تنها محاسبه و بازگرداندن آن مقدار می‌باشد. در ادامه این بخش، به بحث در مورد انجام عملیات هایی در پاسخ به تغییرات state با ناظر ها خواهیم پرداخت.

مقادیر کامپیوتد را تغییر ندهید

مقدار بازگشتی از ویژگی کامپیوتد بر اساس مقادیر دیگر محاسبه می‌شود. این مقدار مانند یک عکس است که هر بار که وابستگی‌های آن تغییر کنند، به‌روز می‌شود. از آنجا که تغییر دادن عکس‌ها منطقی نیست، مقدار بازگشتی باید فقط خوانده شود و روی آن عملیاتی انجام نشود. برای تغییر مقدار بازگشتی، باید متغیری که ویژگی کامپیوتد به آن وابسته است را به‌روز کنید.

ویژگی های کامپیوتد has loaded