September 16, 2024

Vue js da JSX va Render Functions

Vue js bizga odatda template lar dan foydalanishni maslahat beradi, lekin ayrim holatlarda bizga JavaScript ni to'liq kuchini qo'llash uchun Vue bizga render funksiyalarni ishlatish imkonini beradi

Agar siz Virtual DOM ishlash konseptsiyasiga yangi bo'lsez, Rendering Mechanism
ni o'qib chiqishni maslahat beraman

Vue js bizga h() funksiya yordamida element larni yaratishni imkonini beradi.

import { h } from 'vue'

const vnode = h(
  'div', // type
  { id: 'foo', class: 'bar' }, // props
  [
    /* children */
  ]
)

h() - bu hyperscript so'zining qisqartmasi - bu "HTML (gipermatn belgilash tili) yaratadigan JavaScript" degani. Bu nom ko'plab virtual DOM implementatsiyalari tomonidan baham ko'rilgan an'analardan kelib chiqqan. Yanada tavsiflovchi nom createVnode() bo'lishi mumkin edi, lekin qisqaroq nom bu funksiyani ko'p marta chaqirishingiz kerak bo'lganda foydali bo'ladi.

// type dan boshqa har qanday argument lar ixtiyoriy
h('div')
h('div', { id: 'foo' })

// attribute lar va property lar props da ishlatilinsa bo'ladi
// Vue avtomatik tarzda o'zi moslab ketadi ketma ketlikni
h('div', { class: 'bar', innerHTML: 'hello' })

// prop lardagi o'zgaruvchilar yani `.prop` and `.attr`
// `.` and `^` prefix lari bilan birga yoziladi
h('div', { '.name': 'some-name', '^width': '100' })

// class va style larda object / array
// tarzda yozilishni ham qabul qiladi
h('div', { class: [foo, { bar }], style: { color: 'red' } })

// event listener lar onXxx kabi berilishi kerak
h('div', { onClick: () => {} })

// children lar string bo'lishi ham mumkun
h('div', { id: 'foo' }, 'hello')

// children array da birgalikda vnode va string lar bo'lishi mumkun
h('div', ['hello', h('span', 'hello')])

Render function larni e'lon qilish.

Composition Api bilan birgalikda ishlaganimizda setup() funksiyasidan qaytgan qiymat template da ko'rsatish uchun kerak bo'ladi, lekin biz shu qaytgan qiymatlar o'rniga h() ni o'zini ham qaytarib yuborsak bo'ladi.

import { ref, h } from 'vue'

export default {
  props: {
    /* ... */
  },
  setup(props) {
    const count = ref(1)    // return the render function
    return () => h('div', props.msg + count.value)
  }
}

E'lon qilingan render funksiyamiz setup() ichida bo'lgani uchun har qanday reactive o'zgaruvchidan foydalana oladi, va string yoki array ham qaytara oladi.

export default {
  setup() {
    return () => 'hello world!'
  }
}
import { h } from 'vue'

export default {
  setup() {
    // use an array to return multiple root nodes
    return () => [
      h('div'),
      h('div'),
      h('div')
    ]
  }
}

JSX va TSX

JSX bu JavaScript-ning XML-ga o'xshash kengaytmasi bo'lib, bizga quyidagi kodlarni yozish imkonini beradi.

const vnode = <div>hello</div>

// JSX da dinamik holatda qiymatlarni berish uchun 
// curly bracket dan foydalanaimiz
const vnode = <div id={dynamicId}>hello, {userName}</div>
v-for
// template da
<ul>
  <li v-for="{ id, text } in items" :key="id">
    {{ text }}
  </li>
</ul>

// render function da
h(
  'ul',
  // assuming `items` is a ref with array value
  items.value.map(({ id, text }) => {
    return h('li', { key: id }, text)
  })
)

// JSX da ko'rinishi
<ul>
  {items.value.map(({ id, text }) => {
    return <li key={id}>{text}</li>
  })}
</ul>
v-on
// onClick bu vue template dagi @click bilan bir-xil
// render function da
h(
  'button',
  {
    onClick(event) {
      /* ... */
    }
  },
  'Click Me'
)

// JSX da ko'rinishi
<button
  onClick={(event) => {
    /* ... */
  }}
>
  Click Me
</button>

Component lar.

Component lar yaratganimizda, ularni qo'llanilishi bu holatda bo'lishi kerak.

// template ko'rinishi
import Foo from './Foo.vue'
import Bar from './Bar.jsx'

function render() {
  return h('div', [h(Foo), h(Bar)])
}

// JSX da ko'rinishi
function render() {
  return (
    <div>
      <Foo />
      <Bar />
    </div>
  )
}

Functional component lar.

Functional komponentlar - bu o'zining holati bo'lmagan komponentlarning muqobil shakli. Ular sof funksiyalar kabi ishlaydi: props kiradi, vnodelar chiqadi. Ular komponent namunasini yaratmasdan (ya'ni, this ishlatilmaydi) va odatdagi komponent hayot sikli hooklarisiz renderlanadi.

Functional komponent yaratish uchun biz otpions obyekti o'rniga oddiy funksiyadan foydalanamiz. Bu funksiya aslida komponent uchun render funksiyasi vazifasini bajaradi. Ko'p holatda functional component lar yaratganimzda unda options config lari bo'lmasligi mumkun, lekin proplar va emit lar yarata olamiz

function MyComponent(props, { slots, emit, attrs }) {
  // ...
}

MyComponent.props = ['value']
MyComponent.emits = ['click']
import type { SetupContext } from 'vue'

type FComponentProps = {
  message: string
}

type Events = {
  sendMessage(message: string): void
}

function FComponent(
  props: FComponentProps,
  context: SetupContext<Events>
) {
  return (
    <button onClick={() => context.emit('sendMessage', props.message)}>
        {props.message} {' '}
    </button>
  )
}

FComponent.props = {
  message: {
    type: String,
    required: true
  }
}

FComponent.emits = {
  sendMessage: (value: unknown) => typeof value === 'string'
}

Umuman aytganda Vue js da ham bemalol React js kabi JSX/TSX dan foydanalansak bo'ladi, va bu React js dan Vue ga ko'chib o'tmoxchi bo'lganlar yoki qo'shimcha sifatida o'rganmoxchi bo'lganlar uchun juda qulay, lekin bu kabi component larni yozish production da kamdan kam uchratiladi, h() function esa juda ko'p holatlarda kerakli vazifalarni bajarishi mumkun.

Naive UI - JSX da yozilgan (h function lar bilan birgalikda qo'llaniladi)
Uzum UI - Naive UI dan fork qilingan bo'lib unda ham JSX dan foydalanilgan.

Vue.js docs - da batafsil yana JSX va render funksiyalar haqida ma'lumot lar olishingiz mumkun


https://t.me/shahzodcodes