১. ভূমিকা
সর্বশেষ হালনাগাদ: ২০২১-০৮-১০
ওয়েব উপাদান
ওয়েব কম্পোনেন্ট হলো ওয়েব প্ল্যাটফর্ম এপিআই-এর একটি সেট, যা আপনাকে ওয়েব পেজ এবং ওয়েব অ্যাপে ব্যবহারের জন্য নতুন কাস্টম, পুনঃব্যবহারযোগ্য ও এনক্যাপসুলেটেড এইচটিএমএল ট্যাগ তৈরি করতে দেয়। ওয়েব কম্পোনেন্ট স্ট্যান্ডার্ডের উপর ভিত্তি করে তৈরি কাস্টম কম্পোনেন্ট এবং উইজেটগুলো আধুনিক ব্রাউজারগুলোতে কাজ করে এবং এইচটিএমএল-এর সাথে কাজ করে এমন যেকোনো জাভাস্ক্রিপ্ট লাইব্রেরি বা ফ্রেমওয়ার্কের সাথে ব্যবহার করা যায়।
লিট কী
Lit হলো দ্রুত ও হালকা ওয়েব কম্পোনেন্ট তৈরির একটি সহজ লাইব্রেরি, যা যেকোনো ফ্রেমওয়ার্কে, এমনকি কোনো ফ্রেমওয়ার্ক ছাড়াই কাজ করে। Lit ব্যবহার করে আপনি শেয়ারযোগ্য কম্পোনেন্ট, অ্যাপ্লিকেশন, ডিজাইন সিস্টেম এবং আরও অনেক কিছু তৈরি করতে পারেন।
Lit, প্রোপার্টি, অ্যাট্রিবিউট ও রেন্ডারিং ব্যবস্থাপনার মতো সাধারণ ওয়েব কম্পোনেন্টের কাজগুলোকে সহজ করার জন্য এপিআই (API) প্রদান করে।
আপনি যা শিখবেন
- ওয়েব কম্পোনেন্ট কী?
- ওয়েব কম্পোনেন্টের ধারণাগুলি
- কীভাবে একটি ওয়েব কম্পোনেন্ট তৈরি করবেন
- lit-html এবং LitElement কী?
- একটি ওয়েব কম্পোনেন্টের উপরে Lit যা করে
আপনি যা তৈরি করবেন
- একটি সাধারণ থাম্বস আপ / ডাউন ওয়েব কম্পোনেন্ট
- একটি ইতিবাচক/নেতিবাচক সাহিত্য-ভিত্তিক ওয়েব উপাদান
আপনার যা যা লাগবে
- যেকোনো হালনাগাদকৃত আধুনিক ব্রাউজার (ক্রোম, সাফারি, ফায়ারফক্স, ক্রোমিয়াম এজ)। ওয়েব কম্পোনেন্টস সকল আধুনিক ব্রাউজারে কাজ করে এবং মাইক্রোসফট ইন্টারনেট এক্সপ্লোরার ১১ ও নন-ক্রোমিয়াম মাইক্রোসফট এজ-এর জন্য পলিফিল উপলব্ধ আছে।
- এইচটিএমএল, সিএসএস, জাভাস্ক্রিপ্ট এবং ক্রোম ডেভটুলস সম্পর্কে জ্ঞান।
২. প্রস্তুতি গ্রহণ এবং খেলার মাঠটি ঘুরে দেখা
কোড অ্যাক্সেস করা
পুরো কোডল্যাব জুড়ে লিট প্লেগ্রাউন্ডের লিঙ্কগুলো এইভাবে থাকবে:
প্লেগ্রাউন্ড হলো একটি কোড স্যান্ডবক্স যা সম্পূর্ণভাবে আপনার ব্রাউজারে চলে। এটি টাইপস্ক্রিপ্ট এবং জাভাস্ক্রিপ্ট ফাইল কম্পাইল ও রান করতে পারে এবং নোড মডিউলের ইম্পোর্টগুলোও স্বয়ংক্রিয়ভাবে সমাধান করতে পারে। যেমন:
// before
import './my-file.js';
import 'lit';
// after
import './my-file.js';
import 'https://unpkg.com/lit?module';
আপনি এই চেকপয়েন্টগুলোকে প্রারম্ভিক বিন্দু হিসেবে ব্যবহার করে লিট প্লেগ্রাউন্ডে সম্পূর্ণ টিউটোরিয়ালটি করতে পারেন। আপনি যদি ভিএস কোড ব্যবহার করেন, তবে এই চেকপয়েন্টগুলো ব্যবহার করে যেকোনো ধাপের প্রারম্ভিক কোড ডাউনলোড করতে পারবেন, এবং নিজের কাজ যাচাই করার জন্যও এগুলো ব্যবহার করতে পারবেন।
আলোকিত খেলার মাঠের UI অন্বেষণ করা

লিট প্লেগ্রাউন্ড UI স্ক্রিনশটটি সেই বিভাগগুলিকে হাইলাইট করে যা আপনি এই কোডল্যাবে ব্যবহার করবেন।
- ফাইল নির্বাচক। প্লাস বাটনটি লক্ষ্য করুন...
- ফাইল সম্পাদক।
- কোড প্রিভিউ।
- রিলোড বাটন।
- ডাউনলোড বাটন।
ভিএস কোড সেটআপ (উন্নত)
এই ভিএস কোড সেটআপটি ব্যবহারের সুবিধাগুলো নিচে দেওয়া হলো:
- টেমপ্লেট প্রকার যাচাইকরণ
- টেমপ্লেট ইন্টেলিসেন্স এবং অটোকমপ্লিশন
যদি আপনার NPM, VS Code ( lit-plugin প্লাগইন সহ) আগে থেকেই ইনস্টল করা থাকে এবং আপনি সেই পরিবেশটি ব্যবহার করতে জানেন, তাহলে আপনি নিম্নলিখিত পদক্ষেপগুলো অনুসরণ করে সহজেই এই প্রজেক্টগুলো ডাউনলোড ও চালু করতে পারেন:
- ডাউনলোড বোতাম টিপুন
- tar ফাইলের বিষয়বস্তু একটি ডিরেক্টরিতে এক্সট্র্যাক্ট করুন।
- এমন একটি ডেভ সার্ভার ইনস্টল করুন যা বেয়ার মডিউল স্পেসিফায়ার রিজলভ করতে পারে (লিট টিম @web/dev-server ব্যবহারের পরামর্শ দেয়)।
- এখানে
package.jsonএকটি উদাহরণ দেওয়া হলো।
- এখানে
- ডেভ সার্ভারটি চালু করুন এবং আপনার ব্রাউজারটি খুলুন (যদি আপনি
@web/dev-serverব্যবহার করেন তবেnpx web-dev-server --node-resolve --watch --openব্যবহার করতে পারেন)।- আপনি যদি উদাহরণ
package.jsonব্যবহার করেন, তাহলেnpm run serveব্যবহার করুন।
- আপনি যদি উদাহরণ
৩. একটি কাস্টম এলিমেন্ট সংজ্ঞায়িত করুন
কাস্টম উপাদান
ওয়েব কম্পোনেন্ট হলো ৪টি নেটিভ ওয়েব এপিআই-এর একটি সংগ্রহ। সেগুলো হলো:
- ES মডিউল
- কাস্টম উপাদান
- ছায়া ডোম
- এইচটিএমএল টেমপ্লেট
আপনি ইতিমধ্যেই ES মডিউল স্পেসিফিকেশন ব্যবহার করেছেন, যা আপনাকে ইম্পোর্ট ও এক্সপোর্ট সহ জাভাস্ক্রিপ্ট মডিউল তৈরি করার সুযোগ দেয়, যেগুলো <script type="module"> ব্যবহার করে পেজে লোড করা হয়।
একটি কাস্টম উপাদান সংজ্ঞায়িত করা
কাস্টম এলিমেন্টস স্পেসিফিকেশন ব্যবহারকারীদের জাভাস্ক্রিপ্ট ব্যবহার করে নিজস্ব এইচটিএমএল এলিমেন্ট সংজ্ঞায়িত করার সুযোগ দেয়। নেটিভ ব্রাউজার এলিমেন্ট থেকে আলাদা করার জন্য নামগুলিতে অবশ্যই একটি হাইফেন ( - ) থাকতে হবে। index.js ফাইলটি খালি করুন এবং একটি কাস্টম এলিমেন্ট ক্লাস সংজ্ঞায়িত করুন:
index.js
class RatingElement extends HTMLElement {}
customElements.define('rating-element', RatingElement);
একটি কাস্টম এলিমেন্ট সংজ্ঞায়িত করা হয় HTMLElement এক্সটেন্ড করে এমন একটি ক্লাসকে একটি হাইফেনযুক্ত ট্যাগ নামের সাথে যুক্ত করার মাধ্যমে। customElements.define কলটি ব্রাউজারকে 'rating-element' ট্যাগনেমটির সাথে RatingElement ক্লাসটি যুক্ত করতে বলে। এর মানে হলো, আপনার ডকুমেন্টের <rating-element> নামের প্রতিটি এলিমেন্ট এই ক্লাসের সাথে যুক্ত হবে।
ডকুমেন্টের মূল অংশে একটি <rating-element> রাখুন এবং দেখুন কী রেন্ডার হয়।
index.html
<body>
<rating-element></rating-element>
</body>
এখন, আউটপুটের দিকে তাকালে আপনি দেখতে পাবেন যে কিছুই রেন্ডার হয়নি। এটাই স্বাভাবিক, কারণ আপনি ব্রাউজারকে বলেননি যে <rating-element> কীভাবে রেন্ডার করতে হবে। কাস্টম এলিমেন্ট ডেফিনিশনটি সফল হয়েছে কিনা তা আপনি Chrome Dev Tools-এর এলিমেন্ট সিলেক্টরে <rating-element> সিলেক্ট করে এবং কনসোলে নিম্নলিখিত কমান্ডটি কল করে নিশ্চিত হতে পারেন:
$0.constructor
যার আউটপুট হওয়া উচিত:
class RatingElement extends HTMLElement {}
কাস্টম এলিমেন্ট লাইফসাইকেল
কাস্টম এলিমেন্টগুলোর সাথে এক সেট লাইফসাইকেল হুক থাকে। সেগুলো হলো:
-
constructor -
connectedCallback -
disconnectedCallback -
attributeChangedCallback -
adoptedCallback
এলিমেন্টটি প্রথমবার তৈরি করার সময় constructor কল করা হয়: উদাহরণস্বরূপ, document.createElement('rating-element') বা new RatingElement() কল করার মাধ্যমে। আপনার এলিমেন্ট সেট আপ করার জন্য কনস্ট্রাক্টর একটি ভালো জায়গা, কিন্তু এলিমেন্টের "বুট-আপ" পারফরম্যান্সের কারণে কনস্ট্রাক্টরের মধ্যে DOM ম্যানিপুলেশন করাকে সাধারণত একটি খারাপ অভ্যাস হিসেবে বিবেচনা করা হয়।
কাস্টম এলিমেন্টটি DOM-এর সাথে সংযুক্ত হলে connectedCallback টি কল করা হয়। সাধারণত এখানেই প্রাথমিক DOM পরিবর্তনগুলো ঘটে থাকে।
কাস্টম এলিমেন্টটি DOM থেকে সরিয়ে ফেলার পর disconnectedCallback টি কল করা হয়।
ব্যবহারকারী-নির্দিষ্ট কোনো অ্যাট্রিবিউট পরিবর্তিত হলে attributeChangedCallback(attrName, oldValue, newValue) ফাংশনটি কল করা হয়।
যখন কোনো কাস্টম এলিমেন্টকে অন্য কোনো documentFragment থেকে adoptNode মাধ্যমে (যেমন HTMLTemplateElement এ) মূল ডকুমেন্টে গ্রহণ করা হয়, তখন adoptedCallback টি কল করা হয়।
DOM রেন্ডার করুন
এখন, কাস্টম এলিমেন্টটিতে ফিরে যান এবং এর সাথে কিছু DOM যুক্ত করুন। এলিমেন্টটি DOM-এর সাথে সংযুক্ত হওয়ার পর এর কন্টেন্ট সেট করুন:
index.js
class RatingElement extends HTMLElement {
constructor() {
super();
this.rating = 0;
}
connectedCallback() {
this.innerHTML = `
<style>
rating-element {
display: inline-flex;
align-items: center;
}
rating-element button {
background: transparent;
border: none;
cursor: pointer;
}
</style>
<button class="thumb_down" >
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating">${this.rating}</span>
<button class="thumb_up">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>
`;
}
}
customElements.define('rating-element', RatingElement);
constructor , আপনি এলিমেন্টটিতে rating নামের একটি ইনস্ট্যান্স প্রপার্টি সংরক্ষণ করেন। connectedCallback , আপনি <rating-element> এ DOM চাইল্ড যোগ করেন বর্তমান রেটিং এবং তার সাথে থাম্বস আপ ও থাম্বস ডাউন বাটনগুলো প্রদর্শন করার জন্য।
৪. ছায়া ডোম
শ্যাডো ডোম কেন?
পূর্ববর্তী ধাপে, আপনি লক্ষ্য করবেন যে আপনার যোগ করা স্টাইল ট্যাগের সিলেক্টরগুলো পেজের যেকোনো রেটিং এলিমেন্ট এবং যেকোনো বাটনকেও সিলেক্ট করে। এর ফলে স্টাইলগুলো এলিমেন্টের বাইরে ছড়িয়ে গিয়ে এমন অন্যান্য নোড সিলেক্ট করতে পারে, যেগুলোকে আপনি স্টাইল করতে চান না। এছাড়াও, এই কাস্টম এলিমেন্টের বাইরের অন্যান্য স্টাইলগুলো অনিচ্ছাকৃতভাবে আপনার কাস্টম এলিমেন্টের ভেতরের নোডগুলোকে স্টাইল করে ফেলতে পারে। উদাহরণস্বরূপ, মূল ডকুমেন্টের হেডে একটি স্টাইল ট্যাগ রেখে দেখুন:
index.html
<!DOCTYPE html>
<html>
<head>
<script src="./index.js" type="module"></script>
<style>
span {
border: 1px solid red;
}
</style>
</head>
<body>
<rating-element></rating-element>
</body>
</html>
আপনার আউটপুটে রেটিং-এর স্প্যানটির চারপাশে একটি লাল বর্ডার বক্স থাকা উচিত। এটি একটি সাধারণ বিষয়, কিন্তু DOM এনক্যাপসুলেশনের অভাব আরও জটিল অ্যাপ্লিকেশনগুলির ক্ষেত্রে বড় ধরনের সমস্যা তৈরি করতে পারে। এখানেই শ্যাডো ডোম (Shadow DOM) কাজে আসে।
একটি শ্যাডো রুট সংযুক্ত করা
এলিমেন্টটিতে একটি শ্যাডো রুট সংযুক্ত করুন এবং সেই রুটের ভিতরে DOM রেন্ডার করুন:
index.js
class RatingElement extends HTMLElement {
constructor() {
super();
this.rating = 0;
}
connectedCallback() {
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.innerHTML = `
<style>
:host {
display: inline-flex;
align-items: center;
}
button {
background: transparent;
border: none;
cursor: pointer;
}
</style>
<button class="thumb_down" >
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating">${this.rating}</span>
<button class="thumb_up">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>
`;
}
}
customElements.define('rating-element', RatingElement);
যখন আপনি পৃষ্ঠাটি রিফ্রেশ করবেন, তখন আপনি লক্ষ্য করবেন যে মূল ডকুমেন্টের স্টাইলগুলো আর শ্যাডো রুটের ভেতরের নোডগুলোকে নির্বাচন করতে পারবে না।
আপনি এটা কীভাবে করলেন? connectedCallback এ আপনি this.attachShadow কল করেছেন, যা একটি এলিমেন্টের সাথে শ্যাডো রুট যুক্ত করে। open মোডের অর্থ হলো শ্যাডো কন্টেন্টটি ইন্সপেক্টেবল এবং this.shadowRoot এর মাধ্যমে শ্যাডো রুটটিকেও অ্যাক্সেসযোগ্য করে তোলে। ক্রোম ইন্সপেক্টরে ওয়েব কম্পোনেন্টটিও একবার দেখুন:

এখন আপনি একটি প্রসারণযোগ্য শ্যাডো রুট দেখতে পাবেন যা এর ভেতরের বিষয়বস্তু ধারণ করে। সেই শ্যাডো রুটের ভেতরের সবকিছুকে শ্যাডো ডোম (Shadow DOM) বলা হয়। আপনি যদি ক্রোম ডেভ টুলস (Chrome Dev Tools)-এ রেটিং এলিমেন্টটি সিলেক্ট করে $0.children কল করেন, তাহলে আপনি লক্ষ্য করবেন যে এটি কোনো চাইল্ড রিটার্ন করে না। এর কারণ হলো, শ্যাডো ডোমকে সরাসরি চাইল্ডদের মতো একই ডোম ট্রি-র অংশ হিসেবে বিবেচনা করা হয় না, বরং এটি শ্যাডো ট্রি (Shadow Tree)- র অংশ।
আলো ডোম
একটি পরীক্ষা: <rating-element> -এর সরাসরি চাইল্ড হিসেবে একটি নোড যোগ করুন:
index.html
<rating-element>
<div>
This is the light DOM!
</div>
</rating-element>
পৃষ্ঠাটি রিফ্রেশ করুন, এবং আপনি দেখতে পাবেন যে এই কাস্টম এলিমেন্টের লাইট ডোমে থাকা নতুন ডোম নোডটি পৃষ্ঠায় দেখা যাচ্ছে না। এর কারণ হলো, শ্যাডো ডোমে <slot> এলিমেন্টের মাধ্যমে লাইট ডোম নোডগুলো কীভাবে শ্যাডো ডোমে প্রজেক্টেড হবে তা নিয়ন্ত্রণ করার বৈশিষ্ট্য রয়েছে।
৫. এইচটিএমএল টেমপ্লেট
টেমপ্লেট কেন
কোনো স্যানিটাইজেশন ছাড়া innerHTML এবং টেমপ্লেট লিটারেল স্ট্রিং ব্যবহার করলে স্ক্রিপ্ট ইনজেকশনের কারণে নিরাপত্তাজনিত সমস্যা দেখা দিতে পারে। অতীতে DocumentFragment ব্যবহার করা হতো, কিন্তু এগুলোর সাথেও অন্যান্য সমস্যা রয়েছে, যেমন টেমপ্লেট সংজ্ঞায়িত করার সময় ইমেজ লোড হওয়া ও স্ক্রিপ্ট চালু হওয়া এবং সেইসাথে পুনঃব্যবহারযোগ্যতার ক্ষেত্রেও বাধা সৃষ্টি হওয়া। এখানেই <template> এলিমেন্টের ভূমিকা আসে; টেমপ্লেটগুলো নিষ্ক্রিয় DOM, নোড ক্লোন করার একটি অত্যন্ত কার্যকর পদ্ধতি এবং পুনঃব্যবহারযোগ্য টেমপ্লেটিং প্রদান করে।
টেমপ্লেট ব্যবহার করা
এরপরে, কম্পোনেন্টটিকে এইচটিএমএল টেমপ্লেট ব্যবহার করার জন্য পরিবর্তন করুন:
index.html
<body>
<template id="rating-element-template">
<style>
:host {
display: inline-flex;
align-items: center;
}
button {
background: transparent;
border: none;
cursor: pointer;
}
</style>
<button class="thumb_down" >
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating"></span>
<button class="thumb_up">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>
</template>
<rating-element>
<div>
This is the light DOM!
</div>
</rating-element>
</body>
এখানে আপনি DOM কন্টেন্টটি মূল ডকুমেন্টের DOM-এর একটি টেমপ্লেট ট্যাগের মধ্যে সরিয়ে নিয়েছেন। এখন কাস্টম এলিমেন্টের সংজ্ঞাটি রিফ্যাক্টর করুন:
index.js
class RatingElement extends HTMLElement {
constructor() {
super();
this.rating = 0;
}
connectedCallback() {
const shadowRoot = this.attachShadow({mode: 'open'});
const templateContent = document.getElementById('rating-element-template').content;
const clonedContent = templateContent.cloneNode(true);
shadowRoot.appendChild(clonedContent);
this.shadowRoot.querySelector('.rating').innerText = this.rating;
}
}
customElements.define('rating-element', RatingElement);
এই টেমপ্লেট এলিমেন্টটি ব্যবহার করতে, আপনাকে টেমপ্লেটটি কোয়েরি করে এর বিষয়বস্তু সংগ্রহ করতে হবে এবং templateContent.cloneNode ব্যবহার করে সেই নোডগুলো ক্লোন করতে হবে, যেখানে true আর্গুমেন্টটি একটি ডিপ ক্লোন সম্পন্ন করে। এরপর আপনি সেই ডেটা দিয়ে ডম (dom) ইনিশিয়ালাইজ করবেন।
অভিনন্দন, আপনার এখন একটি ওয়েব কম্পোনেন্ট তৈরি হয়ে গেছে! দুর্ভাগ্যবশত, এটি এখনও কোনো কাজ করে না, তাই এরপরে এতে কিছু কার্যকারিতা যোগ করুন।
৬. কার্যকারিতা যোগ করা
সম্পত্তির বাধ্যবাধকতা
বর্তমানে, রেটিং-এলিমেন্টে রেটিং সেট করার একমাত্র উপায় হলো এলিমেন্টটি তৈরি করা, অবজেক্টটিতে rating প্রপার্টি সেট করা এবং তারপর সেটিকে পেজে রাখা। দুর্ভাগ্যবশত, নেটিভ এইচটিএমএল এলিমেন্টগুলো সাধারণত এভাবে কাজ করে না। নেটিভ এইচটিএমএল এলিমেন্টগুলো প্রপার্টি এবং অ্যাট্রিবিউট উভয়ের পরিবর্তনেই আপডেট হয়ে থাকে।
rating প্রপার্টি পরিবর্তিত হলে কাস্টম এলিমেন্টের ভিউ আপডেট করার জন্য নিম্নলিখিত লাইনগুলো যোগ করুন:
index.js
constructor() {
super();
this._rating = 0;
}
set rating(value) {
this._rating = value;
if (!this.shadowRoot) {
return;
}
const ratingEl = this.shadowRoot.querySelector('.rating');
if (ratingEl) {
ratingEl.innerText = this._rating;
}
}
get rating() {
return this._rating;
}
আপনি রেটিং প্রপার্টির জন্য একটি সেটার এবং গেটার যোগ করুন, এবং তারপর রেটিং এলিমেন্টের টেক্সটটি উপলব্ধ থাকলে তা আপডেট করুন। এর মানে হলো, আপনি যদি এলিমেন্টটিতে রেটিং প্রপার্টি সেট করেন, তাহলে ভিউটি আপডেট হয়ে যাবে; আপনার ডেভ টুলস কনসোলে এটি দ্রুত পরীক্ষা করে দেখুন!
অ্যাট্রিবিউট বাইন্ডিং
এখন, অ্যাট্রিবিউট পরিবর্তিত হলে ভিউটি আপডেট করুন; এটি অনেকটা <input value="newValue"> সেট করলে একটি ইনপুটের ভিউ আপডেট হওয়ার মতো। সৌভাগ্যবশত, ওয়েব কম্পোনেন্ট লাইফসাইকেলে attributeChangedCallback অন্তর্ভুক্ত রয়েছে। নিম্নলিখিত লাইনগুলো যোগ করে রেটিংটি আপডেট করুন:
index.js
static get observedAttributes() {
return ['rating'];
}
attributeChangedCallback(attributeName, oldValue, newValue) {
if (attributeName === 'rating') {
const newRating = Number(newValue);
this.rating = newRating;
}
}
attributeChangedCallback ট্রিগার করার জন্য, আপনাকে অবশ্যই RatingElement.observedAttributes which defines the attributes to be observed for changes । এরপর আপনি DOM-এ ডিক্লারেটিভভাবে রেটিংটি সেট করবেন। চেষ্টা করে দেখুন:
index.html
<rating-element rating="5"></rating-element>
রেটিংটি এখন ঘোষণামূলকভাবে আপডেট হওয়া উচিত!
বোতামের কার্যকারিতা
এখন শুধু বাটনের কার্যকারিতাটিই বাকি আছে। এই কম্পোনেন্টটির আচরণ এমন হওয়া উচিত যাতে ব্যবহারকারী একটিমাত্র আপ বা ডাউন ভোট রেটিং দিতে পারেন এবং ভিজ্যুয়াল ফিডব্যাক পান। আপনি কিছু ইভেন্ট লিসেনার এবং একটি রিফ্লেক্টিং প্রপার্টি ব্যবহার করে এটি বাস্তবায়ন করতে পারেন, কিন্তু প্রথমে ভিজ্যুয়াল ফিডব্যাক দেওয়ার জন্য নিম্নলিখিত লাইনগুলো যোগ করে স্টাইলগুলো আপডেট করুন:
index.html
<style>
...
:host([vote=up]) .thumb_up {
fill: green;
}
:host([vote=down]) .thumb_down {
fill: red;
}
</style>
শ্যাডো ডোমে :host সিলেক্টরটি সেই নোড বা কাস্টম এলিমেন্টকে নির্দেশ করে যার সাথে শ্যাডো রুট সংযুক্ত থাকে। এক্ষেত্রে, যদি vote অ্যাট্রিবিউটটি "up" হয়, তাহলে থাম্ব-আপ বাটনটি সবুজ হয়ে যাবে, কিন্তু যদি vote "down", then it will turn the thumb-down button red । এখন, আপনি যেভাবে rating ইমপ্লিমেন্ট করেছেন, ঠিক সেভাবেই vote জন্য একটি রিফ্লেক্টিং প্রপার্টি/অ্যাট্রিবিউট তৈরি করে এর লজিকটি প্রয়োগ করুন। প্রপার্টি সেটার এবং গেটার দিয়ে শুরু করুন:
index.js
constructor() {
super();
this._rating = 0;
this._vote = null;
}
set vote(newValue) {
const oldValue = this._vote;
if (newValue === oldValue) {
return;
}
if (newValue === 'up') {
if (oldValue === 'down') {
this.rating += 2;
} else {
this.rating += 1;
}
} else if (newValue === 'down') {
if (oldValue === 'up') {
this.rating -= 2;
} else {
this.rating -= 1;
}
}
this._vote = newValue;
this.setAttribute('vote', newValue);
}
get vote() {
return this._vote;
}
আপনি constructor _vote ইনস্ট্যান্স প্রপার্টিটিকে null দিয়ে ইনিশিয়ালাইজ করেন এবং সেটারে নতুন মানটি ভিন্ন কিনা তা পরীক্ষা করেন। যদি ভিন্ন হয়, তবে আপনি সেই অনুযায়ী রেটিংটি সমন্বয় করেন এবং, গুরুত্বপূর্ণভাবে, this.setAttribute ব্যবহার করে vote অ্যাট্রিবিউটটি হোস্টে প্রতিফলিত করেন।
এরপরে, অ্যাট্রিবিউট বাইন্ডিং সেট আপ করুন:
index.js
static get observedAttributes() {
return ['rating', 'vote'];
}
attributeChangedCallback(attributeName, oldValue, newValue) {
if (attributeName === 'rating') {
const newRating = Number(newValue);
this.rating = newRating;
} else if (attributeName === 'vote') {
this.vote = newValue;
}
}
আবারও, এটি সেই একই প্রক্রিয়া যা আপনি rating অ্যাট্রিবিউট বাইন্ডিংয়ের ক্ষেত্রে অনুসরণ করেছিলেন; আপনি observedAttributes এ vote যোগ করুন, এবং attributeChangedCallback এ vote প্রপার্টিটি সেট করুন। এবং এখন সবশেষে, বাটনগুলোকে কার্যকারিতা দেওয়ার জন্য কিছু ক্লিক ইভেন্ট লিসেনার যোগ করুন!
index.js
constructor() {
super();
this._rating = 0;
this._vote = null;
this._boundOnUpClick = this._onUpClick.bind(this);
this._boundOnDownClick = this._onDownClick.bind(this);
}
connectedCallback() {
...
this.shadowRoot.querySelector('.thumb_up')
.addEventListener('click', this._boundOnUpClick);
this.shadowRoot.querySelector('.thumb_down')
.addEventListener('click', this._boundOnDownClick);
}
disconnectedCallback() {
this.shadowRoot.querySelector('.thumb_up')
.removeEventListener('click', this._boundOnUpClick);
this.shadowRoot.querySelector('.thumb_down')
.removeEventListener('click', this._boundOnDownClick);
}
_onUpClick() {
this.vote = 'up';
}
_onDownClick() {
this.vote = 'down';
}
constructor আপনি এলিমেন্টের সাথে কিছু ক্লিক লিসেনার যুক্ত করেন এবং রেফারেন্সগুলো রেখে দেন। connectedCallback আপনি বাটনগুলোর ক্লিক ইভেন্ট শোনেন। disconnectedCallback আপনি এই লিসেনারগুলো পরিষ্কার করেন এবং ক্লিক লিসেনারগুলোতে যথাযথভাবে vote সেট করেন।
অভিনন্দন, আপনার কাছে এখন একটি সম্পূর্ণ বৈশিষ্ট্যযুক্ত ওয়েব কম্পোনেন্ট আছে; কয়েকটি বাটনে ক্লিক করে দেখুন! এখন সমস্যা হলো, আমার JS ফাইলটি ৯৬ লাইনের, HTML ফাইলটি ৪৩ লাইনের হয়ে গেছে, এবং এত সাধারণ একটি কম্পোনেন্টের জন্য কোডটি বেশ বিশদ ও নির্দেশমূলক। এখানেই গুগলের লিট প্রজেক্টটি কাজে আসে!
৭. লিট-এইচটিএমএল
কোড চেকপয়েন্ট
কেন lit-html
প্রথমত এবং সর্বাগ্রে, <template> ট্যাগটি কার্যকরী এবং কর্মদক্ষ, কিন্তু এটি কম্পোনেন্টের লজিকের সাথে প্যাকেজ করা থাকে না, ফলে বাকি লজিকের সাথে টেমপ্লেটটি বিতরণ করা কঠিন হয়ে পড়ে। এছাড়াও, টেমপ্লেট এলিমেন্টগুলো যেভাবে ব্যবহৃত হয়, তা স্বভাবতই ইম্পারেটিভ কোডের দিকে ঝুঁকে পড়ে, যা অনেক ক্ষেত্রে ডিক্লারেটিভ কোডিং প্যাটার্নের তুলনায় কম পাঠযোগ্য কোডের জন্ম দেয়।
এইখানেই লিট-এইচটিএমএল (lit-html) কাজে আসে! লিট-এইচটিএমএল হলো লিট (Lit)-এর রেন্ডারিং সিস্টেম, যা আপনাকে জাভাস্ক্রিপ্টে এইচটিএমএল (HTML) টেমপ্লেট লিখতে এবং তারপর সেই টেমপ্লেটগুলোকে ডেটার সাথে দক্ষতার সাথে রেন্ডার ও রি-রেন্ডার করে ডিওএম (DOM) তৈরি ও আপডেট করতে দেয়। এটি জনপ্রিয় জেএসএক্স (JSX) এবং ভিডোম (VDOM) লাইব্রেরিগুলোর মতোই, কিন্তু এটি ব্রাউজারে নেটিভভাবে চলে এবং অনেক ক্ষেত্রে আরও বেশি দক্ষতার সাথে কাজ করে।
লিট এইচটিএমএল ব্যবহার করে
এরপরে, নেটিভ ওয়েব কম্পোনেন্ট rating-element লিট টেমপ্লেট ব্যবহার করার জন্য মাইগ্রেট করুন। লিট টেমপ্লেট ট্যাগড টেমপ্লেট লিটারেল ব্যবহার করে, যা হলো এমন ফাংশন যা একটি বিশেষ সিনট্যাক্স সহ টেমপ্লেট স্ট্রিংগুলোকে আর্গুমেন্ট হিসেবে গ্রহণ করে। লিট তখন দ্রুত রেন্ডারিং প্রদানের জন্য এবং নিরাপত্তার জন্য কিছু স্যানিটাইজেশন বৈশিষ্ট্য যোগ করতে অভ্যন্তরীণভাবে টেমপ্লেট এলিমেন্ট ব্যবহার করে। ওয়েবকম্পোনেন্টে একটি render() মেথড যোগ করে index.html এর <template> কে একটি লিট টেমপ্লেটে মাইগ্রেট করার মাধ্যমে শুরু করুন:
index.js
// Dont forget to import from Lit!
import {render, html} from 'lit';
class RatingElement extends HTMLElement {
...
render() {
if (!this.shadowRoot) {
return;
}
const template = html`
<style>
:host {
display: inline-flex;
align-items: center;
}
button {
background: transparent;
border: none;
cursor: pointer;
}
:host([vote=up]) .thumb_up {
fill: green;
}
:host([vote=down]) .thumb_down {
fill: red;
}
</style>
<button class="thumb_down">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating">${this.rating}</span>
<button class="thumb_up">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>`;
render(template, this.shadowRoot);
}
}
আপনি index.html থেকেও আপনার টেমপ্লেটটি মুছে ফেলতে পারেন। এই রেন্ডার মেথডে আপনি ` template নামে একটি ভ্যারিয়েবল সংজ্ঞায়িত করেন এবং html ট্যাগযুক্ত টেমপ্লেট লিটারেল ফাংশনটি কল করেন। আপনি আরও লক্ষ্য করবেন যে, আপনি ` span.rating এলিমেন্টের ভিতরে ${...} টেমপ্লেট লিটারেল ইন্টারপোলেশন সিনট্যাক্স ব্যবহার করে একটি সাধারণ ডেটা বাইন্ডিং করেছেন। এর মানে হলো, ভবিষ্যতে আপনার আর ওই নোডটিকে ইম্পারেটিভলি আপডেট করার প্রয়োজন হবে না। এছাড়াও, আপনি `lit` render মেথডটি কল করেন, যা টেমপ্লেটটিকে শ্যাডো রুটে সিনক্রোনাসলি রেন্ডার করে।
ডিক্লারেটিভ সিনট্যাক্সে স্থানান্তরিত হওয়া
এখন যেহেতু আপনি <template> এলিমেন্টটি সরিয়ে দিয়েছেন, কোডটি রিফ্যাক্টর করে এর পরিবর্তে নতুনভাবে সংজ্ঞায়িত render মেথডটি কল করুন। লিসেনার কোডটি গুছিয়ে নিতে আপনি lit-এর ইভেন্ট লিসেনার বাইন্ডিং ব্যবহার করে শুরু করতে পারেন:
index.js
<button
class="thumb_down"
@click=${() => {this.vote = 'down'}}>
...
<button
class="thumb_up"
@click=${() => {this.vote = 'up'}}>
লিট টেমপ্লেটগুলো @EVENT_NAME বাইন্ডিং সিনট্যাক্স ব্যবহার করে কোনো নোডে ইভেন্ট লিসেনার যোগ করতে পারে, যার ফলে এই বাটনগুলো প্রতিবার ক্লিক করার সাথে সাথে vote প্রপার্টিটি আপডেট হয়।
এরপরে, constructor এবং connectedCallback ও disconnectedCallback মধ্যে ইভেন্ট লিসেনার ইনিশিয়ালাইজেশন কোডটি পরিপাটি করুন:
index.js
constructor() {
super();
this._rating = 0;
this._vote = null;
}
connectedCallback() {
this.attachShadow({mode: 'open'});
this.render();
}
// remove disonnectedCallback and _onUpClick and _onDownClick
আপনি তিনটি কলব্যাক থেকেই ক্লিক লিসেনার লজিক সরিয়ে ফেলতে পেরেছেন এবং এমনকি disconnectedCallback পুরোপুরি বাদ দিতে পেরেছেন! আপনি connectedCallback থেকে সমস্ত DOM ইনিশিয়ালাইজেশন কোডও সরিয়ে ফেলতে পেরেছেন, যা এটিকে আরও অনেক বেশি মার্জিত করে তুলেছে। এর মানে হলো, আপনি _onUpClick এবং _onDownClick লিসেনার মেথডগুলোও বাদ দিতে পারবেন!
অবশেষে, প্রপার্টি সেটারগুলোকে render মেথড ব্যবহার করার জন্য আপডেট করুন, যাতে প্রপার্টি বা অ্যাট্রিবিউট পরিবর্তিত হলে ডম আপডেট হতে পারে:
index.js
set rating(value) {
this._rating = value;
this.render();
}
...
set vote(newValue) {
const oldValue = this._vote;
if (newValue === oldValue) {
return;
}
if (newValue === 'up') {
if (oldValue === 'down') {
this.rating += 2;
} else {
this.rating += 1;
}
} else if (newValue === 'down') {
if (oldValue === 'up') {
this.rating -= 2;
} else {
this.rating -= 1;
}
}
this._vote = newValue;
this.setAttribute('vote', newValue);
// add render method
this.render();
}
এখানে, আপনি rating সেটার থেকে ডম আপডেট লজিকটি সরিয়ে দিয়েছেন এবং vote সেটার থেকে render জন্য একটি কল যুক্ত করেছেন। এখন টেমপ্লেটটি অনেক বেশি পাঠযোগ্য, কারণ আপনি এখন দেখতে পাচ্ছেন বাইন্ডিং এবং ইভেন্ট লিসেনারগুলো কোথায় প্রয়োগ করা হয়েছে।
পেজটি রিফ্রেশ করুন, এবং আপভোট চাপলে আপনি একটি কার্যকরী রেটিং বাটন দেখতে পাবেন যা এইরকম দেখাবে!

৮. লিটএলিমেন্ট
কেন লিটএলিমেন্ট
কোডটিতে এখনও কিছু সমস্যা রয়ে গেছে। প্রথমত, আপনি যদি ' vote প্রপার্টি বা অ্যাট্রিবিউট পরিবর্তন করেন, তাহলে তা rating প্রপার্টিও পরিবর্তন করে দিতে পারে, যার ফলে render দুইবার কল হবে। বারবার 'render' কল করা মূলত একটি নো-অপ (no-op) এবং কার্যকর প্রক্রিয়া হওয়া সত্ত্বেও, জাভাস্ক্রিপ্ট ভিএম (VM) সিনক্রোনাসভাবে ফাংশনটিকে দুইবার কল করতে গিয়ে সময় ব্যয় করছে। দ্বিতীয়ত, নতুন প্রপার্টি এবং অ্যাট্রিবিউট যোগ করা বেশ কষ্টসাধ্য, কারণ এর জন্য প্রচুর বয়লারপ্লেট কোডের প্রয়োজন হয়। আর এখানেই LitElement ভূমিকা!
LitElement হলো Lit-এর বেস ক্লাস, যা দিয়ে দ্রুত ও হালকা ওয়েব কম্পোনেন্ট তৈরি করা যায় এবং যা বিভিন্ন ফ্রেমওয়ার্ক ও পরিবেশে ব্যবহার করা সম্ভব। এরপর, rating-element ইমপ্লিমেন্টেশন পরিবর্তন করে দেখুন LitElement আমাদের জন্য কী করতে পারে!
লিটএলিমেন্ট ব্যবহার করে
প্রথমে lit প্যাকেজ থেকে LitElement বেস ক্লাসটি ইম্পোর্ট এবং সাবক্লাস করুন:
index.js
import {LitElement, html, css} from 'lit';
class RatingElement extends LitElement {
// remove connectedCallback()
...
আপনি LitElement ইম্পোর্ট করবেন, যা rating-element নতুন বেস ক্লাস। এরপর আপনি আপনার html ইম্পোর্টটি রাখবেন এবং সবশেষে css ইম্পোর্ট করবেন, যা আমাদেরকে সিএসএস ম্যাথ, টেমপ্লেটিং এবং অন্যান্য অভ্যন্তরীণ ফিচারের জন্য সিএসএস ট্যাগযুক্ত টেমপ্লেট লিটারেল সংজ্ঞায়িত করার সুযোগ দেয়।
এরপরে, রেন্ডার মেথড থেকে স্টাইলগুলো Lit-এর স্ট্যাটিক স্টাইলশীটে সরিয়ে নিন:
index.js
class RatingElement extends LitElement {
static get styles() {
return css`
:host {
display: inline-flex;
align-items: center;
}
button {
background: transparent;
border: none;
cursor: pointer;
}
:host([vote=up]) .thumb_up {
fill: green;
}
:host([vote=down]) .thumb_down {
fill: red;
}
`;
}
...
Lit-এর বেশিরভাগ স্টাইল এখানেই থাকে। Lit এই স্টাইলগুলো গ্রহণ করে এবং দ্রুততর রেন্ডারিং নিশ্চিত করতে কনস্ট্রাক্টেবল স্টাইলশীটের মতো ব্রাউজার ফিচার ব্যবহার করে, সেইসাথে প্রয়োজনে পুরোনো ব্রাউজারগুলোতে ওয়েব কম্পোনেন্টস পলিফিলের মাধ্যমেও তা পাস করে দেয়।
জীবনচক্র
Lit, নেটিভ ওয়েব কম্পোনেন্ট কলব্যাকগুলোর পাশাপাশি এক সেট রেন্ডার লাইফসাইকেল কলব্যাক মেথড চালু করেছে। ঘোষিত Lit প্রোপার্টিগুলো পরিবর্তিত হলে এই কলব্যাকগুলো ট্রিগার হয়।
এই বৈশিষ্ট্যটি ব্যবহার করতে হলে, আপনাকে স্থিরভাবে ঘোষণা করতে হবে কোন প্রোপার্টিগুলো রেন্ডার লাইফসাইকেল চালু করবে।
index.js
static get properties() {
return {
rating: {
type: Number,
},
vote: {
type: String,
reflect: true,
}
};
}
// remove observedAttributes() and attributeChangedCallback()
// remove set rating() get rating()
এখানে, আপনি নির্ধারণ করেন যে rating এবং vote LitElement রেন্ডারিং লাইফসাইকেলকে সক্রিয় করবে, সেইসাথে স্ট্রিং অ্যাট্রিবিউটগুলোকে প্রপার্টিতে রূপান্তর করতে কোন টাইপগুলো ব্যবহৃত হবে তাও নির্ধারণ করেন।
<user-profile .name=${this.user.name} .age=${this.user.age}>
${this.user.family.map(member => html`
<family-member
.name=${member.name}
.relation=${member.relation}>
</family-member>`)}
</user-profile>
এছাড়াও, vote প্রপার্টির reflect ফ্ল্যাগটি host এলিমেন্টের vote অ্যাট্রিবিউটকে স্বয়ংক্রিয়ভাবে আপডেট করবে, যা আপনি vote সেটারে ম্যানুয়ালি ট্রিগার করেছিলেন।
এখন যেহেতু আপনার কাছে স্ট্যাটিক প্রোপার্টি ব্লকটি আছে, আপনি অ্যাট্রিবিউট এবং প্রোপার্টি রেন্ডার আপডেট করার সমস্ত লজিক সরিয়ে ফেলতে পারেন। এর মানে হলো, আপনি নিম্নলিখিত মেথডগুলো সরিয়ে ফেলতে পারেন:
-
connectedCallback -
observedAttributes -
attributeChangedCallback -
rating(সেটার এবং গেটার) -
vote(সেটার এবং গেটার উভয়ই ব্যবহার করুন, কিন্তু পরিবর্তনের লজিকটি সেটার থেকেই নিন)
আপনাকে যা রাখতে হবে তা হলো constructor এবং সেই সাথে একটি নতুন willUpdate লাইফসাইকেল মেথড যোগ করা:
index.js
constructor() {
super();
this.rating = 0;
this.vote = null;
}
willUpdate(changedProps) {
if (changedProps.has('vote')) {
const newValue = this.vote;
const oldValue = changedProps.get('vote');
if (newValue === 'up') {
if (oldValue === 'down') {
this.rating += 2;
} else {
this.rating += 1;
}
} else if (newValue === 'down') {
if (oldValue === 'up') {
this.rating -= 2;
} else {
this.rating -= 1;
}
}
}
}
// remove set vote() and get vote()
এখানে, আপনি কেবল rating এবং vote ইনিশিয়ালাইজ করবেন এবং vote সেটার লজিকটি willUpdate লাইফসাইকেল মেথডে সরিয়ে নেবেন। যখনই কোনো আপডেটিং প্রপার্টি পরিবর্তিত হয়, render আগে willUpdate মেথডটি কল করা হয়, কারণ LitElement প্রপার্টির পরিবর্তনগুলোকে ব্যাচ করে এবং রেন্ডারিংকে অ্যাসিঙ্ক্রোনাস করে তোলে। willUpdate এ রিঅ্যাক্টিভ প্রপার্টিতে (যেমন this.rating ) করা পরিবর্তনগুলো অপ্রয়োজনীয় render লাইফসাইকেল কল ট্রিগার করবে না।
অবশেষে, render হলো একটি LitElement লাইফসাইকেল মেথড, যার জন্য আমাদের একটি Lit টেমপ্লেট রিটার্ন করতে হয়:
index.js
render() {
return html`
<button
class="thumb_down"
@click=${() => {this.vote = 'down'}}>
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v2c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></svg>
</button>
<span class="rating">${this.rating}</span>
<button
class="thumb_up"
@click=${() => {this.vote = 'up'}}>
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewbox="0 0 24 24" width="24"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-2z"/></svg>
</button>`;
}
আপনাকে আর শ্যাডো রুট চেক করতে হবে না এবং পূর্বে 'lit' প্যাকেজ থেকে ইম্পোর্ট করা render ফাংশনটিও কল করতে হবে না।
আপনার এলিমেন্টটি এখন প্রিভিউতে রেন্ডার হওয়ার কথা; এটিতে ক্লিক করুন!
৯. অভিনন্দন
অভিনন্দন, আপনি সফলভাবে একেবারে শুরু থেকে একটি ওয়েব কম্পোনেন্ট তৈরি করে সেটিকে একটি লিটএলিমেন্টে রূপান্তরিত করেছেন!
Lit খুবই ছোট (মিনিফাইড ও জিপড অবস্থায় < ৫কেবি), অত্যন্ত দ্রুত এবং এটি দিয়ে কোড করা সত্যিই মজাদার! আপনি এটি দিয়ে অন্যান্য ফ্রেমওয়ার্কের ব্যবহারের জন্য কম্পোনেন্ট তৈরি করতে পারেন, অথবা এটি দিয়ে পূর্ণাঙ্গ অ্যাপও তৈরি করতে পারেন!
আপনি এখন জানেন ওয়েব কম্পোনেন্ট কী, কীভাবে একটি তৈরি করতে হয়, এবং কীভাবে Lit এগুলো তৈরি করা আরও সহজ করে তোলে!
কোড চেকপয়েন্ট
আপনি কি আপনার চূড়ান্ত কোডটি আমাদের কোডের সাথে মিলিয়ে দেখতে চান? এখানে তুলনা করুন।
এরপর কী?
অন্যান্য কোডল্যাবগুলোও দেখে নিন!
- রিঅ্যাক্ট ডেভেলপারদের জন্য সাহিত্য
- লিট-এলিমেন্ট দিয়ে একটি ব্রিক ভিউয়ার তৈরি করুন
- lit-element ব্যবহার করে একটি Stories কম্পোনেন্ট তৈরি করুন
আরও পড়ুন
- সাহিত্য বিষয়ক ইন্টারেক্টিভ টিউটোরিয়াল
- লিট ডকস
- ওপেন ওয়েব কম্পোনেন্টস - একটি কমিউনিটি পরিচালিত নির্দেশিকা ও টুলিং কমিউনিটি
- WebComponents.dev - সকল পরিচিত ফ্রেমওয়ার্কে একটি ওয়েব কম্পোনেন্ট তৈরি করুন
সম্প্রদায়
- লিট অ্যান্ড ফ্রেন্ডস স্ল্যাক - বৃহত্তম ওয়েব কম্পোনেন্টস কমিউনিটি
- টুইটারে @buildWithLit — Lit তৈরি করা দলের টুইটার অ্যাকাউন্ট।
- ওয়েব কম্পোনেন্টস এসএফ - সান ফ্রান্সিসকোর জন্য একটি ওয়েব কম্পোনেন্টস মিটআপ