Reactivity Fundamentals
API Preference
এই পৃষ্ঠাটি এবং পরবর্তীতে গাইডের অন্যান্য অনেক অধ্যায়ে অপশন এপিআই এবং কম্পোজিশন এপিআই-এর জন্য বিভিন্ন বিষয়অবজেক্ট রয়েছে। আপনার বর্তমান পছন্দ হল কম্পোজিশন API। আপনি বাম সাইডবারের শীর্ষে "API পছন্দ" সুইচগুলি ব্যবহার করে API স্টাইলগুলির মধ্যে টগল করতে পারেন।
Declaring Reactive State
ref()
Composition API-এ, প্রতিক্রিয়াশীল অবস্থা ঘোষণা করার প্রস্তাবিত উপায় হল ref()
ফাংশন ব্যবহার করা:
js
import { ref } from 'vue'
const count = ref(0)
ref()
আর্গুমেন্ট নেয় এবং একটি .value
বৈশিষ্ট্য সহ একটি রেফ অবজেক্টের মধ্যে মোড়ানো রিটার্ন করে:
js
const count = ref(0)
console.log(count) // { value: 0 }
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
আরো দেখুন: Refs টাইপ করা
একটি কম্পোনেন্টের টেমপ্লেটে রেফ অ্যাক্সেস করতে, একটি কম্পোনেন্টের setup()
ফাংশন থেকে ঘোষণা করুন এবং ফেরত দিন:
js
import { ref } from 'vue'
export default {
// `setup` is a special hook dedicated for the Composition API.
setup() {
const count = ref(0)
// expose the ref to the template
return {
count
}
}
}
template
<div>{{ count }}</div>
লক্ষ্য করুন যে টেমপ্লেটে রেফ ব্যবহার করার সময় আমাদের .value
যোগ করার প্রয়োজন নেই। সুবিধার জন্য, টেমপ্লেটের ভিতরে ব্যবহার করা হলে রেফগুলি স্বয়ংক্রিয়ভাবে খুলে ফেলা হয় (কিছু সতর্কতার সাথে)।
You can also mutate a ref directly in event handlers:
template
<button @click="count++">
{{ count }}
</button>
আরও জটিল যুক্তির জন্য, আমরা এমন ফাংশন ঘোষণা করতে পারি যেগুলি একই সুযোগে রেফগুলিকে রূপান্তরিত করে এবং সেগুলিকে state পাশাপাশি পদ্ধতি হিসাবে প্রকাশ করে:
js
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
function increment() {
// .value is needed in JavaScript
count.value++
}
// don't forget to expose the function as well.
return {
count,
increment
}
}
}
উন্মুক্ত পদ্ধতিগুলি তখন ইভেন্ট হ্যান্ডলার হিসাবে ব্যবহার করা যেতে পারে:
template
<button @click="increment">
{{ count }}
</button>
Here's the example live on Codepen, without using any build tools.
<script setup>
setup()
এর মাধ্যমে ম্যানুয়ালি স্টেট এবং পদ্ধতি প্রকাশ করা ভার্বোস হতে পারে। সৌভাগ্যবশত, Single-File Components (SFCs) ব্যবহার করার সময় এটি এড়ানো যেতে পারে। আমরা <script setup>
দিয়ে ব্যবহার সহজ করতে পারি:
vue
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
</script>
<template>
<button @click="increment">
{{ count }}
</button>
</template>
<script setup>
-এ ঘোষিত শীর্ষ-স্তরের আমদানি, ভেরিয়েবল এবং ফাংশন একই কম্পোনেন্টের টেমপ্লেটে স্বয়ংক্রিয়ভাবে ব্যবহারযোগ্য। টেমপ্লেটটিকে একই সুযোগে ঘোষিত একটি জাভাস্ক্রিপ্ট ফাংশন হিসাবে ভাবুন - এটির পাশাপাশি ঘোষিত সমস্ত কিছুতে স্বাভাবিকভাবেই অ্যাক্সেস রয়েছে।
TIP
গাইডের বাকি অংশের জন্য, আমরা প্রাথমিকভাবে কম্পোজিশন API কোড উদাহরণগুলির জন্য SFC + <script setup>
সিনট্যাক্স ব্যবহার করব, কারণ এটি Vue বিকাশকারীদের জন্য সবচেয়ে সাধারণ ব্যবহার।
If you are not using SFC, you can still use Composition API with the setup()
option.
Why Refs?
আপনি হয়তো ভাবছেন কেন আমাদের প্লেইন ভেরিয়েবলের পরিবর্তে .value
এর সাথে refs দরকার। এটি ব্যাখ্যা করার জন্য, আমাদের সংক্ষিপ্তভাবে আলোচনা করতে হবে কিভাবে Vue এর প্রতিক্রিয়াশীলতা সিস্টেম কাজ করে।
আপনি যখন একটি টেমপ্লেটে একটি রেফ ব্যবহার করেন এবং পরে রেফের মান পরিবর্তন করেন, Vue স্বয়ংক্রিয়ভাবে পরিবর্তনটি সনাক্ত করে এবং সেই অনুযায়ী DOM আপডেট করে। এটি একটি নির্ভরতা-ট্র্যাকিং ভিত্তিক প্রতিক্রিয়া সিস্টেমের মাধ্যমে সম্ভব হয়েছে। যখন একটি কম্পোনেন্ট প্রথমবারের জন্য রেন্ডার করা হয়, Vue tracks প্রতিটি রেফারেন্স যা রেন্ডারের সময় ব্যবহৃত হয়েছিল। পরবর্তীতে, যখন একটি রেফ মিউটেট করা হয়, তখন এটি ট্র্যাক করা কম্পোনেন্টগুলির জন্য এটি trigger করবে।
স্ট্যান্ডার্ড জাভাস্ক্রিপ্টে, প্লেইন ভেরিয়েবলের অ্যাক্সেস বা মিউটেশন সনাক্ত করার কোন উপায় নেই। যাইহোক, আমরা getter and setter পদ্ধতি ব্যবহার করে একটি অবজেক্টর বৈশিষ্ট্যগুলির get and set অপারেশনগুলিকে আটকাতে পারি।
.value
প্রপার্টি Vue কে শনাক্ত করার সুযোগ দেয় যখন কোনো রেফ অ্যাক্সেস করা হয়েছে বা মিউটেট করা হয়েছে। হুডের নিচে, Vue তার গেটারে ট্র্যাকিং সঞ্চালন করে এবং তার সেটারের মধ্যে ট্রিগারিং সঞ্চালন করে। ধারণাগতভাবে, আপনি একটি রেফকে এমন একটি অবজেক্ট হিসাবে ভাবতে পারেন যা দেখতে এইরকম:
js
// pseudo code, not actual implementation
const myRef = {
_value: 0,
get value() {
track()
return this._value
},
set value(newValue) {
this._value = newValue
trigger()
}
}
রেফের আরেকটি চমৎকার বৈশিষ্ট্য হল যে প্লেইন ভেরিয়েবলের বিপরীতে, আপনি সর্বশেষ মান এবং রিঅ্যাকটিভিটি সংযোগে অ্যাক্সেস বজায় রেখে রেফগুলিকে ফাংশনে পাস করতে পারেন। পুনর্ব্যবহারযোগ্য কোডে জটিল লজিক রিফ্যাক্টর করার সময় এটি বিশেষভাবে কার্যকর।
রিঅ্যাকটিভিটি সিস্টেমটি গভীরতার মধ্যে প্রতিক্রিয়া বিভাগে আরও বিশদে আলোচনা করা হয়েছে।
Deep Reactivity
Refs গভীরভাবে নেস্টেড অবজেক্ট, অ্যারে, বা জাভাস্ক্রিপ্ট বিল্ট-ইন ডেটা স্ট্রাকচার যেমন Map
সহ যেকোনো মান ধরতে পারে।
একটি ref এর মানকে গভীরভাবে প্রতিক্রিয়াশীল করে তুলবে। এর মানে আপনি nested objects or arrays পরিবর্তন করলেও আপনি পরিবর্তনগুলি সনাক্ত করা আশা করতে পারেন:
js
import { ref } from 'vue'
const obj = ref({
nested: { count: 0 },
arr: ['foo', 'bar']
})
function mutateDeeply() {
// these will work as expected.
obj.value.nested.count++
obj.value.arr.push('baz')
}
Non-primitive values are turned into reactive proxies via reactive()
, which is discussed below.
It is also possible to opt-out of deep reactivity with shallow refs. For shallow refs, only .value
access is tracked for reactivity. Shallow refs can be used for optimizing performance by avoiding the observation cost of large objects, or in cases where the inner state is managed by an external library.
Further reading:
DOM Update Timing
যখন আপনি প্রতিক্রিয়াশীল অবস্থা পরিবর্তন করেন, DOM স্বয়ংক্রিয়ভাবে আপডেট হয়। যাইহোক, এটি লক্ষ করা উচিত যে DOM আপডেটগুলি সিঙ্ক্রোনাসভাবে প্রয়োগ করা হয় না। পরিবর্তে, Vue আপডেট চক্রে "পরবর্তী টিক" না হওয়া পর্যন্ত সেগুলিকে বাফার করে যাতে আপনি যতগুলি রাজ্য পরিবর্তন করেছেন না কেন প্রতিটি কম্পোনেন্ট শুধুমাত্র একবার আপডেট হয়।
একটি রাষ্ট্র পরিবর্তনের পরে DOM আপডেট সম্পূর্ণ হওয়ার জন্য অপেক্ষা করতে, আপনি nextTick() গ্লোবাল API ব্যবহার করতে পারেন:
js
import { nextTick } from 'vue'
async function increment() {
count.value++
await nextTick()
// Now the DOM is updated
}
reactive()
প্রতিক্রিয়াশীল অবস্থা ঘোষণা করার আরেকটি উপায় আছে, reactive()
API সহ। একটি রেফের বিপরীতে যা অভ্যন্তরীণ মানকে একটি বিশেষ অবজেক্টতে মোড়ানো, reactive()
একটি অবজেক্টকে নিজেই প্রতিক্রিয়াশীল করে তোলে:
js
import { reactive } from 'vue'
const state = reactive({ count: 0 })
আরও দেখুন: প্রতিক্রিয়াশীল টাইপিং
টেমপ্লেটে ব্যবহার:
template
<button @click="state.count++">
{{ state.count }}
</button>
প্রতিক্রিয়াশীল অবজেক্ট হল JavaScript Proxies এবং সাধারণ অবজেক্টর মতোই আচরণ করে। পার্থক্য হল যে Vue প্রতিক্রিয়াশীল অবজেক্টর সমস্ত বৈশিষ্ট্যের অ্যাক্সেস এবং মিউটেশনকে রিঅ্যাকটিভিটি ট্র্যাকিং এবং ট্রিগার করার জন্য বাধা দিতে সক্ষম।
reactive()
অবজেক্টকে গভীরভাবে রূপান্তর করে: নেস্টেড অবজেক্টগুলিকেও reactive()
দিয়ে মোড়ানো হয় যখন অ্যাক্সেস করা হয়। এটিকে অভ্যন্তরীণভাবে রেফ()
দ্বারাও বলা হয় যখন রেফ মান একটি অবজেক্ট হয়। অগভীর রেফের মতো, গভীর প্রতিক্রিয়া থেকে অপ্ট-আউট করার জন্য shallowReactive()
APIও রয়েছে।
Reactive Proxy vs. Original
এটা মনে রাখা গুরুত্বপূর্ণ যে reactive()
থেকে প্রত্যাবর্তিত মান হল একটি Proxy অবজেক্ট, যা মূল অবজেক্টর সমান নয়:
js
const raw = {}
const proxy = reactive(raw)
// proxy is NOT equal to the original.
console.log(proxy === raw) // false
শুধুমাত্র প্রক্সিই প্রতিক্রিয়াশীল - আসল অবজেক্টকে পরিবর্তন করলে আপডেট ট্রিগার হবে না। অতএব, Vue এর প্রতিক্রিয়াশীলতা সিস্টেমের সাথে কাজ করার সময় সর্বোত্তম অনুশীলন হল একচেটিয়াভাবে আপনার রাজ্যের প্রক্সি সংস্করণগুলি ব্যবহার করা।
প্রক্সিতে সামঞ্জস্যপূর্ণ অ্যাক্সেস নিশ্চিত করতে, একই অবজেক্টতে reactive()
কল করা সর্বদা একই প্রক্সি ফেরত দেয় এবং একটি বিদ্যমান প্রক্সিতে reactive()
কল করাও একই প্রক্সি ফেরত দেয়:
js
// calling reactive() on the same object returns the same proxy
console.log(reactive(raw) === proxy) // true
// calling reactive() on a proxy returns itself
console.log(reactive(proxy) === proxy) // true
এই নিয়ম নেস্টেড অবজেক্টের ক্ষেত্রেও প্রযোজ্য। গভীর প্রতিক্রিয়াশীলতার কারণে, প্রতিক্রিয়াশীল অবজেক্টর ভিতরে নেস্টেড অবজেক্টগুলিও প্রক্সি:
js
const proxy = reactive({})
const raw = {}
proxy.nested = raw
console.log(proxy.nested === raw) // false
Limitations of reactive()
reactive()
API-এর কয়েকটি সীমাবদ্ধতা রয়েছে:
সীমিত মান প্রকার: এটি শুধুমাত্র অবজেক্টর প্রকারের জন্য কাজ করে (অবজেক্ট, অ্যারে, এবং সংগ্রহের ধরন ) যেমন
Map
এবংSet
)। এটি প্রিমিটিভ ধরনের যেমনstring
,number
বাboolean
ধরে রাখতে পারে না।সম্পূর্ণ অবজেক্ট প্রতিস্থাপন করা যাবে না: যেহেতু Vue এর রিঅ্যাকটিভিটি ট্র্যাকিং প্রোপার্টি অ্যাক্সেসের উপর কাজ করে, তাই আমাদের অবশ্যই সবসময় রিঅ্যাকটিভ অবজেক্টের একই রেফারেন্স রাখতে হবে। এর মানে হল যে আমরা একটি প্রতিক্রিয়াশীল অবজেক্টকে সহজে "প্রতিস্থাপন" করতে পারি না কারণ প্রথম রেফারেন্সের প্রতিক্রিয়াশীলতার সংযোগ হারিয়ে গেছে:
jslet state = reactive({ count: 0 }) // the above reference ({ count: 0 }) is no longer being tracked // (reactivity connection is lost!) state = reactive({ count: 1 })
Not destructure-friendly: যখন আমরা একটি প্রতিক্রিয়াশীল অবজেক্টর আদিম প্রকারের কম্পিউটেড প্রপার্টিকে স্থানীয় ভেরিয়েবলে ধ্বংস করি, অথবা যখন আমরা সেই কম্পিউটেড প্রপার্টিটিকে একটি ফাংশনে পাস করি, তখন আমরা প্রতিক্রিয়াশীলতার সংযোগ হারাবো:
jsconst state = reactive({ count: 0 }) // count is disconnected from state.count when destructured. let { count } = state // does not affect original state count++ // the function receives a plain number and // won't be able to track changes to state.count // we have to pass the entire object in to retain reactivity callSomeFunction(state.count)
এই সীমাবদ্ধতার কারণে, আমরা প্রতিক্রিয়াশীল অবস্থা ঘোষণা করার জন্য প্রাথমিক API হিসেবে ref()
ব্যবহার করার পরামর্শ দিই।
Additional Ref Unwrapping Details
As Reactive Object Property
একটি ref স্বয়ংক্রিয়ভাবে unwrapped যখন একটি প্রতিক্রিয়াশীল অবজেক্টর একটি কম্পিউটেড প্রপার্টি হিসাবে অ্যাক্সেস বা পরিবর্তন করা হয়. অন্য কথায়, এটি একটি স্বাভাবিক কম্পিউটেড প্রপার্টির মতো আচরণ করে:
js
const count = ref(0)
const state = reactive({
count
})
console.log(state.count) // 0
state.count = 1
console.log(count.value) // 1
যদি একটি নতুন রেফ একটি বিদ্যমান রেফের সাথে লিঙ্কযুক্ত একটি কম্পিউটেড প্রপার্টিতে বরাদ্দ করা হয় তবে এটি পুরানো রেফের প্রতিস্থাপন করবে:
js
const otherCount = ref(2)
state.count = otherCount
console.log(state.count) // 2
// original ref is now disconnected from state.count
console.log(count.value) // 1
Ref unwrapping শুধুমাত্র তখনই ঘটে যখন একটি গভীর প্রতিক্রিয়াশীল অবজেক্টর ভিতরে নেস্ট করা হয়। এটি প্রযোজ্য হয় না যখন এটি একটি অগভীর প্রতিক্রিয়াশীল অবজেক্ট এর কম্পিউটেড প্রপার্টি হিসাবে অ্যাক্সেস করা হয়।
Caveat in Arrays and Collections
প্রতিক্রিয়াশীল অবজেক্টর বিপরীতে, যখন রেফটিকে একটি প্রতিক্রিয়াশীল অ্যারের একটি কম্পোনেন্ট হিসাবে বা Map
-এর মতো একটি নেটিভ সংগ্রহের ধরণ হিসাবে অ্যাক্সেস করা হয় তখন না খুলে ফেলা হয়:
js
const books = reactive([ref('Vue 3 Guide')])
// need .value here
console.log(books[0].value)
const map = reactive(new Map([['count', ref(0)]]))
// need .value here
console.log(map.get('count').value)
Caveat when Unwrapping in Templates
টেমপ্লেটে রেফ আনর্যাপিং শুধুমাত্র তখনই প্রযোজ্য যদি রেফটি টেমপ্লেট রেন্ডার প্রসঙ্গে একটি শীর্ষ-স্তরের কম্পিউটেড প্রপার্টি হয়।
নীচের উদাহরণে, count
এবং object
শীর্ষ-স্তরের বৈশিষ্ট্য, কিন্তু object.id
নয়:
js
const count = ref(0)
const object = { id: ref(1) }
অতএব, এই অভিব্যক্তিটি প্রত্যাশিত হিসাবে কাজ করে:
template
{{ count + 1 }}
...যখন এটি না করে:
template
{{ object.id + 1 }}
রেন্ডার করা ফলাফল হবে [object object]1
কারণ অভিব্যক্তিটির মূল্যায়ন করার সময় object.id
খুলে রাখা হয় না এবং একটি রেফ অবজেক্ট থাকে। এটি ঠিক করার জন্য, আমরা একটি শীর্ষ-স্তরের কম্পিউটেড প্রপার্টিতে `id' ধ্বংস করতে পারি:
js
const { id } = object
template
{{ id + 1 }}
এখন রেন্ডার ফলাফল হবে 2
।
আরেকটি বিষয় লক্ষণীয় যে একটি রেফ যদি টেক্সট ইন্টারপোলেশনের চূড়ান্ত মূল্যায়ন করা মান হয় (যেমন একটি {{ }}
ট্যাগ) তাহলে রেফটি খুলে যায়, তাই নিম্নলিখিতটি 1
রেন্ডার করবে :
template
{{ object.id }}
এটি টেক্সট ইন্টারপোলেশনের একটি সুবিধাজনক বৈশিষ্ট্য এবং এটি {{ object.id.value }}
এর সমতুল্য।