Mundarijaga o‘tish

<script setup>

<script setup> - bu Single-File Komponentlar (SFC) ichida Composition API'ni ishlatish uchun kompilyatsiya vaqtidagi sintaksis shakaridir. Agar siz ham SFC, ham Composition API'ni ishlatayotgan bo'lsangiz, bu tavsiya etilgan sintaksis. Bu oddiy <script> sintaksisiga nisbatan bir qator afzalliklarga ega:

  • Kam boilerplate bilan yanada ixcham kod
  • Toza TypeScript yordamida prop'lar va chiqarilgan hodisalarni e'lon qilish imkoniyati
  • Yaxshiroq runtime ishlash (shablon xuddi shu scope'da render funksiyasiga kompilyatsiya qilinadi, oraliq proxy'siz)
  • Yaxshiroq IDE tur aniqlash ishlashi (til serveri uchun kodlardan turlarni ajratib olish kamroq ish)

Asosiy Sintaksis

Sintaksisni ishlatish uchun <script> blokiga setup atributini qo'shing:

vue
<script setup>
console.log('hello script setup')
</script>

Ichidagi kod komponentning setup() funksiyasi kontenti sifatida kompilyatsiya qilinadi. Bu oddiy <script> dan farqli ravishda, u faqat komponent birinchi marta import qilinganda bir marta ishga tushiriladi, <script setup> ichidagi kod komponentning har bir instansi yaratilganda ishga tushiriladi.

Yuqori darajadagi bog'lanishlar shablonga ochiq

<script setup> ishlatganda, <script setup> ichida e'lon qilingan har qanday yuqori darajadagi bog'lanishlar (o'zgaruvchilar, funksiya e'lonlari va importlar) shablonda to'g'ridan-to'g'ri ishlatilishi mumkin:

vue
<script setup>
// o'zgaruvchi
const msg = 'Hello!'

// funksiyalar
function log() {
  console.log(msg)
}
</script>

<template>
  <button @click="log">{{ msg }}</button>
</template>

Importlar ham xuddi shu tarzda ochiq. Bu shablon ifodalarida import qilingan yordamchi funksiyani methods opsiyasi orqali ochishga hojat yo'q, to'g'ridan-to'g'ri ishlatish mumkinligini anglatadi:

vue
<script setup>
import { capitalize } from './helpers'
</script>

<template>
  <div>{{ capitalize('hello') }}</div>
</template>

Reaktivlik

Reaktiv holat Reaktivlik API'lari yordamida aniq yaratilishi kerak. setup() funksiyasidan qaytarilgan qiymatlarga o'xshab, ref'lar shablonda ishlatilganda avtomatik ravishda ochiladi:

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

const count = ref(0)
</script>

<template>
  <button @click="count++">{{ count }}</button>
</template>

Komponentlarni Ishlatish

<script setup> scope'idagi qiymatlar ham maxsus komponent teglari nomlari sifatida to'g'ridan-to'g'ri ishlatilishi mumkin:

vue
<script setup>
import MyComponent from './MyComponent.vue'
</script>

<template>
  <MyComponent />
</template>

MyComponent o'zgaruvchi sifatida ishlatilgan deb o'ylang. Agar siz JSX ishlatgan bo'lsangiz, bu yerda mental model o'xshash. Kebab-case ekvivalenti <my-component> ham shablonda ishlaydi - biroq izchillik uchun PascalCase komponent teglari kuchli tavsiya etiladi. Bu shuningdek mahalliy maxsus elementlardan farqlashga yordam beradi.

Dinamik Komponentlar

Komponentlar string kalitlari ostida ro'yxatdan o'tkazilgan o'rniga o'zgaruvchilar sifatida ishlatilgani uchun, <script setup> ichida dinamik komponentlarni ishlatganda dinamik :is bog'lashidan foydalanishimiz kerak:

vue
<script setup>
import Foo from './Foo.vue'
import Bar from './Bar.vue'
</script>

<template>
  <component :is="Foo" />
  <component :is="someCondition ? Foo : Bar" />
</template>

Komponentlar ternary ifodada o'zgaruvchilar sifatida qanday ishlatilishi mumkinligiga e'tibor bering.

Rekursiv Komponentlar

SFC o'z fayl nomi orqali o'ziga o'zini murojaat qilishi mumkin. Masalan, FooBar.vue nomli fayl o'z shablonida <FooBar/> sifatida o'ziga murojaat qilishi mumkin.

Eslatma, bu import qilingan komponentlardan pastroq ustuvorlikka ega. Agar sizda komponentning aniqlangan nomi bilan to'qnashuvchi nomli import bo'lsa, importni alias qilishingiz mumkin:

js
import { FooBar as FooBarChild } from './components'

Namespace Komponentlar

Ob'ekt xususiyatlari ostida joylashgan komponentlarga murojaat qilish uchun <Foo.Bar> kabi nuqtali komponent teglaridan foydalanishingiz mumkin. Bu bitta fayldan bir nechta komponentlarni import qilganda foydali:

vue
<script setup>
import * as Form from './form-components'
</script>

<template>
  <Form.Input>
    <Form.Label>label</Form.Label>
  </Form.Input>
</template>

Maxsus Direktivalarni Ishlatish

Global ro'yxatdan o'tkazilgan maxsus direktivalar oddiygina ishlaydi. Mahalliy maxsus direktivalar <script setup> bilan aniq ro'yxatdan o'tkazilishi shart emas, lekin ular vNameOfDirective nomlash sxemasiga rioya qilishi kerak:

vue
<script setup>
const vMyDirective = {
  beforeMount: (el) => {
    // element bilan biror narsa qilish
  }
}
</script>
<template>
  <h1 v-my-directive>This is a Heading</h1>
</template>

Agar siz direktivani boshqa joydan import qilayotgan bo'lsangiz, uni kerakli nomlash sxemasiga moslashtirish uchun qayta nomlash mumkin:

vue
<script setup>
import { myDirective as vMyDirective } from './MyDirective.js'
</script>

defineProps() & defineEmits()

To'liq tur aniqlash qo'llab-quvvatlashiga ega props va emits kabi opsiyalarni e'lon qilish uchun, <script setup> ichida avtomatik ravishda mavjud bo'lgan defineProps va defineEmits API'laridan foydalanishimiz mumkin:

vue
<script setup>
const props = defineProps({
  foo: String
})

const emit = defineEmits(['change', 'delete'])
// setup kodi
</script>
  • defineProps va defineEmits faqat <script setup> ichida ishlatilishi mumkin bo'lgan kompilyator makrolari. Ular import qilishni talab qilmaydi va <script setup> qayta ishlanganda kompilyatsiya qilinadi.

  • defineProps props opsiyasi bilan bir xil qiymatni qabul qiladi, defineEmits esa emits opsiyasi bilan bir xil qiymatni qabul qiladi.

  • defineProps va defineEmits uzatilgan opsiyalarga asoslangan to'g'ri tur aniqlashini ta'minlaydi.

  • defineProps va defineEmits ga uzatilgan opsiyalar setup'dan modul scope'iga ko'tariladi. Shuning uchun, opsiyalar setup scope'ida e'lon qilingan mahalliy o'zgaruvchilarga murojaat qila olmaydi. Buning natijasida kompilyatsiya xatosi yuzaga keladi. Biroq, u modul scope'ida ham bo'lgani uchun import qilingan bog'lanishlarga murojaat qilishi mumkin.

Faqat tur uchun prop/emit e'lonlari

Prop'lar va emit'lar ham defineProps yoki defineEmits ga literal tur argumentini uzatish orqali toza tur sintaksisi yordamida e'lon qilinishi mumkin:

ts
const props = defineProps<{
  foo: string
  bar?: number
}>()

const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}>()

// 3.3+: alternativa, yanada ixcham sintaksis
const emit = defineEmits<{
  change: [id: number] // nomlangan tuple sintaksisi
  update: [value: string]
}>()
  • defineProps yoki defineEmits faqat runtime e'lon YOKI tur e'lonidan foydalanishi mumkin. Ikkalasini bir vaqtda ishlatish kompilyatsiya xatosini keltirib chiqaradi.

  • Tur e'lonini ishlatganda, ekvivalent runtime e'lon statik tahlil orqali avtomatik ravishda yaratiladi, bu ikki marta e'lon qilish zaruratini olib tashlaydi va baribir to'g'ri runtime xatti-harakatini ta'minlaydi.

    • Dev rejimida, kompilyator turlardan tegishli runtime tekshiruvini aniqlashga harakat qiladi. Masalan, bu yerda foo: String foo: string turidan aniqlanadi. Agar tur import qilingan turga havola bo'lsa, kompilyator tashqi fayllar haqida ma'lumotga ega bo'lmagani uchun aniqlangan natija foo: null (ya'ni any turi bilan teng) bo'ladi.

    • Prod rejimida, kompilyator paket hajmini kamaytirish uchun massiv formatidagi e'lonni yaratadi (bu yerda prop'lar ['foo', 'bar'] ga kompilyatsiya qilinadi)

  • 3.2 va undan past versiyalarda, defineProps() uchun generic tur parametri faqat literal tur yoki mahalliy interfeysga havola bilan cheklangan edi.

    Bu cheklov 3.3 da hal qilindi. Vue'ning so'nggi versiyasi tur parametri o'rnida import qilingan va cheklangan murakkab turlar to'plamiga havolalarni qo'llab-quvvatlaydi. Biroq, turdan runtime konvertatsiyasi hali ham AST-ga asoslangan bo'lgani uchun, ba'zi murakkab turlar, masalan shartli turlar, qo'llab-quvvatlanmaydi. Siz bitta prop uchun shartli turlardan foydalanishingiz mumkin, lekin butun prop'lar ob'ekti uchun emas.

Reaktiv Prop'lar Destrukturalizatsiyasi

Vue 3.5 va undan yuqori versiyalarda, defineProps qaytarilgan qiymatidan destrukturalizatsiya qilingan o'zgaruvchilar reaktiv. Vue kompilyatori bir xil <script setup> blokidagi kod defineProps dan destrukturalizatsiya qilingan o'zgaruvchilarga kirganda avtomatik ravishda props. ni oldiga qo'shadi:

ts
const { foo } = defineProps(['foo'])

watchEffect(() => {
  // 3.5 dan oldin faqat bir marta ishga tushadi
  // 3.5+ da "foo" prop'i o'zgarganda qayta ishga tushadi
  console.log(foo)
})

Yuqoridagi kod quyidagi ekvivalentga kompilyatsiya qilinadi:

js
const props = defineProps(['foo'])

watchEffect(() => {
  // `foo` kompilyator tomonidan `props.foo` ga o'zgartiriladi
  console.log(props.foo)
})

Bundan tashqari, prop'lar uchun default qiymatlarni e'lon qilish uchun JavaScript'ning native default qiymat sintaksisidan foydalanishingiz mumkin. Bu ayniqsa turga asoslangan prop'lar e'lonini ishlatganda foydali:

ts
interface Props {
  msg?: string
  labels?: string[]
}

const { msg = 'hello', labels = ['one', 'two'] } = defineProps<Props>()

Tur e'lonini ishlatganda default prop qiymatlari

3.5 va undan yuqori versiyalarda, default qiymatlar Reaktiv Prop'lar Destrukturalizatsiyasini ishlatganda tabiiy ravishda e'lon qilinishi mumkin. Lekin 3.4 va undan past versiyalarda, Reaktiv Prop'lar Destrukturalizatsiyasi default bo'yicha yoqilmagan. Turga asoslangan e'lon bilan prop'lar default qiymatlarini e'lon qilish uchun withDefaults kompilyator makrosi kerak:

ts
interface Props {
  msg?: string
  labels?: string[]
}

const props = withDefaults(defineProps<Props>(), {
  msg: 'hello',
  labels: () => ['one', 'two']
})

Bu ekvivalent runtime prop'lar default opsiyalariga kompilyatsiya qilinadi. Bundan tashqari, withDefaults yordamchisi default qiymatlar uchun tur tekshiruvini ta'minlaydi va default qiymatlar e'lon qilingan xususiyatlar uchun ixtiyoriy bayroqlar olib tashlangan props turini ta'minlaydi.

INFO

Eslatma, withDefaults ishlatganda o'zgartirilishi mumkin bo'lgan havola turlari (masalan massivlar yoki ob'ektlar) uchun default qiymatlar tasodifiy o'zgartirish va tashqi yon effektlardan saqlash uchun funksiyalar ichiga o'ralishi kerak. Bu har bir komponent instansi o'zining default qiymat nusxasini olishini ta'minlaydi. Bu destrukturalizatsiya bilan default qiymatlarni ishlatganda kerak emas.

defineModel()

  • Faqat 3.4+ da mavjud

Bu makro ota-ona komponentidan v-model orqali ishlatilishi mumkin bo'lgan ikki tomonlama bog'lanish prop'ini e'lon qilish uchun ishlatilishi mumkin. Misol ishlatish Komponent v-model qo'llanmasida ham muhokama qilinadi.

Qulaylik uchun, bu makro model prop'ini va tegishli qiymat yangilash hodisasini e'lon qiladi. Agar birinchi argument literal string bo'lsa, u prop nomi sifatida ishlatiladi; Aks holda prop nomi default bo'yicha "modelValue" bo'ladi. Ikkala holatda ham, siz prop'ning opsiyalarini va model ref'ining qiymat transformatsiya opsiyalarini o'z ichiga olgan qo'shimcha ob'ektni uzatishingiz mumkin.

js
// ota-ona tomonidan v-model orqali ishlatiladigan "modelValue" prop'ini e'lon qiladi
const model = defineModel()
// YOKI: opsiyalar bilan "modelValue" prop'ini e'lon qiladi
const model = defineModel({ type: String })

// o'zgartirilganda "update:modelValue" ni chiqaradi
model.value = 'hello'

// ota-ona tomonidan v-model:count orqali ishlatiladigan "count" prop'ini e'lon qiladi
const count = defineModel('count')
// YOKI: opsiyalar bilan "count" prop'ini e'lon qiladi
const count = defineModel('count', { type: Number, default: 0 })

function inc() {
  // o'zgartirilganda "update:count" ni chiqaradi
  count.value++
}

WARNING

Agar defineModel prop'i uchun default qiymati bo'lsa va siz bu prop uchun ota-ona komponentidan hech qanday qiymat bermasangiz, bu ota-ona va farzand komponentlari o'rtasida sinxronizatsiyani yo'qotishga olib kelishi mumkin. Quyidagi misolda, ota-onaning myRef i aniqlanmagan, lekin farzandning model i 1:

js
// farzand komponenti:
const model = defineModel({ default: 1 })

// ota-ona komponenti:
const myRef = ref()
html
<Child v-model="myRef"></Child>

Modifikatorlar va Transformatorlar

v-model direktivasi bilan ishlatilgan modifikatorlarga kirish uchun, defineModel() qaytarilgan qiymatini quyidagicha destrukturalizatsiya qilishimiz mumkin:

js
const [modelValue, modelModifiers] = defineModel()

// v-model.trim bilan mos keladi
if (modelModifiers.trim) {
  // ...
}

Modifikator mavjud bo'lganda, biz uni o'qiganda yoki ota-onaga qayta sinxronlashtirganda qiymatni transformatsiya qilishimiz kerak bo'lishi mumkin. Buni get va set transformator opsiyalarini ishlatish orqali amalga oshirishimiz mumkin:

js
const [modelValue, modelModifiers] = defineModel({
  // get() bu yerda kerak bo'lmagani uchun tashlab ketilgan
  set(value) {
    // agar .trim modifikatori ishlatilgan bo'lsa, qirqilgan qiymatni qaytaradi
    if (modelModifiers.trim) {
      return value.trim()
    }
    // aks holda, qiymatni o'z holatida qaytaradi
    return value
  }
})

TypeScript bilan Ishlatish

defineProps va defineEmits kabi, defineModel ham model qiymati va modifikatorlar turlarini belgilash uchun tur argumentlarini qabul qilishi mumkin:

ts
const modelValue = defineModel<string>()
//    ^? Ref<string | undefined>

// opsiyalar bilan default model, required mumkin bo'lgan undefined qiymatlarni olib tashlaydi
const modelValue = defineModel<string>({ required: true })
//    ^? Ref<string>

const [modelValue, modifiers] = defineModel<string, 'trim' | 'uppercase'>()
//                 ^? Record<'trim' | 'uppercase', true | undefined>

defineExpose()

<script setup> ishlatadigan komponentlar default bo'yicha yopiq - ya'ni shablon ref'lari yoki $parent zanjirlari orqali olingan komponentning ommaviy instansi <script setup> ichida e'lon qilingan bog'lanishlardan hech birini ochmaydi.

<script setup> komponentida xususiyatlarni aniq ochish uchun defineExpose kompilyator makrosidan foydalaning:

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

const a = 1
const b = ref(2)

defineExpose({
  a,
  b
})
</script>

Ota-ona bu komponentning instansini shablon ref'lari orqali olganda, olingan instans { a: number, b: number } ko'rinishida bo'ladi (ref'lar oddiy instanslardagi kabi avtomatik ravishda ochiladi).

defineOptions()

  • Faqat 3.3+ da qo'llab-quvvatlanadi

Bu makro alohida <script> blokidan foydalanishga hojat yo'q, to'g'ridan-to'g'ri <script setup> ichida komponent opsiyalarini e'lon qilish uchun ishlatilishi mumkin:

vue
<script setup>
defineOptions({
  inheritAttrs: false,
  customOptions: {
    /* ... */
  }
})
</script>
  • Bu makro. Opsiyalar modul scope'iga ko'tariladi va <script setup> ichidagi literal konstantalar bo'lmagan mahalliy o'zgaruvchilarga kirish imkoni yo'q.

defineSlots()

  • Faqat 3.3+ da qo'llab-quvvatlanadi

Bu makro IDE'larga slot nomi va prop'lar turini tekshirish uchun tur maslahatlarini ta'minlash uchun ishlatilishi mumkin.

defineSlots() faqat tur parametrini qabul qiladi va runtime argumentlari yo'q. Tur parametri xususiyat kaliti slot nomi va qiymat turi slot funksiyasi bo'lgan tur literal bo'lishi kerak. Funksiyaning birinchi argumenti slot qabul qilishi kutilayotgan prop'lar va uning turi shablondagi slot prop'lari uchun ishlatiladi. Qaytarilgan tur hozirda e'tiborga olinmaydi va any bo'lishi mumkin, lekin biz kelajakda slot kontentini tekshirish uchun undan foydalanishimiz mumkin.

Bu shuningdek slots ob'ektini qaytaradi, u setup kontekstida ochilgan yoki useSlots() tomonidan qaytarilgan slots ob'ekti bilan ekvivalent.

vue
<script setup lang="ts">
const slots = defineSlots<{
  default(props: { msg: string }): any
}>()
</script>

useSlots() & useAttrs()

<script setup> ichida slots va attrs ishlatilishi nisbatan kam uchraydi, chunki ularga shablonda $slots va $attrs orqali to'g'ridan-to'g'ri kirish mumkin. Kam uchraydigan holatlarda, ularga kerak bo'lsa, mos ravishda useSlots va useAttrs yordamchilaridan foydalaning:

vue
<script setup>
import { useSlots, useAttrs } from 'vue'

const slots = useSlots()
const attrs = useAttrs()
</script>

useSlots va useAttrs setupContext.slots va setupContext.attrs bilan ekvivalent bo'lgan haqiqiy runtime funksiyalari. Ular oddiy kompozitsiya API funksiyalarida ham ishlatilishi mumkin.

Oddiy <script> bilan Birga Ishlatish

<script setup> oddiy <script> bilan birga ishlatilishi mumkin. Oddiy <script> quyidagi holatlarda kerak bo'lishi mumkin:

  • <script setup> da ifodalab bo'lmaydigan opsiyalarni e'lon qilish, masalan inheritAttrs yoki plugin'lar orqali yoqilgan maxsus opsiyalar (3.3+ da defineOptions bilan almashtirilishi mumkin).
  • Nomlangan eksportlarni e'lon qilish.
  • Faqat bir marta ishga tushirilishi kerak bo'lgan yon effektlarni ishga tushirish yoki ob'ektlarni yaratish.
vue
<script>
// oddiy <script>, modul scope'ida ishga tushiriladi (faqat bir marta)
runSideEffectOnce()

// qo'shimcha opsiyalarni e'lon qilish
export default {
  inheritAttrs: false,
  customOptions: {}
}
</script>

<script setup>
// setup() scope'ida ishga tushiriladi (har bir instans uchun)
</script>

Bir xil komponentda <script setup> va <script> ni birlashtirish qo'llab-quvvatlanishi yuqorida tavsiflangan holatlarla cheklangan. Xususan:

  • <script setup> da allaqachon e'lon qilish mumkin bo'lgan props va emits kabi opsiyalar uchun alohida <script> bo'limidan foydalanmang.
  • <script setup> ichida yaratilgan o'zgaruvchilar komponent instansiga xususiyatlar sifatida qo'shilmaydi, shuning uchun ular Options API orqali kirish imkoni yo'q. API'larni shu tarzda aralashtirish kuchli tavsiya etilmaydi.

Agar o'zingizni qo'llab-quvvatlanmaydigan holatlardan birida topsangiz, <script setup> ishlatish o'rniga aniq setup() funksiyasiga o'tishni ko'rib chiqishingiz kerak.

Yuqori darajadagi await

Yuqori darajadagi await <script setup> ichida ishlatilishi mumkin. Natijada olingan kod async setup() sifatida kompilyatsiya qilinadi:

vue
<script setup>
const post = await fetch(`/api/post/1`).then((r) => r.json())
</script>

Bundan tashqari, kutayotgan ifoda await dan keyin joriy komponent instans kontekstini saqlaydigan formatda avtomatik ravishda kompilyatsiya qilinadi.

Eslatma

async setup() hozirda hali eksperimental xususiyat bo'lgan Suspense bilan birga ishlatilishi kerak. Biz uni kelajakdagi relizda yakunlash va hujjatlashtirishni rejalashtirmoqdamiz - lekin agar siz hozir qiziqsangiz, u qanday ishlashini ko'rish uchun uning testlariga murojaat qilishingiz mumkin.

Import Bayonotlari

Vue'dagi import bayonotlari ECMAScript modul spetsifikatsiyasiga rioya qiladi. Bundan tashqari, siz build tool konfiguratsiyangizda belgilangan alias'lardan foydalanishingiz mumkin:

vue
<script setup>
import { ref } from 'vue'
import { componentA } from './Components'
import { componentB } from '@/Components'
import { componentC } from '~/Components'
</script>

Generic'lar

Generic tur parametrlari <script> tegi ustidagi generic atributi yordamida e'lon qilinishi mumkin:

vue
<script setup lang="ts" generic="T">
defineProps<{
  items: T[]
  selected: T
}>()
</script>

generic qiymati TypeScript'dagi <...> orasidagi parametrlar ro'yxati bilan bir xil ishlaydi. Masalan, siz bir nechta parametrlardan, extends cheklovlaridan, default turlardan va import qilingan turlarga havolalardan foydalanishingiz mumkin:

vue
<script
  setup
  lang="ts"
  generic="T extends string | number, U extends Item"
>
import type { Item } from './types'
defineProps<{
  id: T
  list: U[]
}>()
</script>

Tur aniqlab bo'lmasa, aniq turlarni uzatish uchun @vue-generic direktivasidan foydalanishingiz mumkin:

vue
<template>
  <!-- @vue-generic {import('@/api').Actor} -->
  <ApiSelect v-model="peopleIds" endpoint="/api/actors" id-prop="actorId" />

  <!-- @vue-generic {import('@/api').Genre} -->
  <ApiSelect v-model="genreIds" endpoint="/api/genres" id-prop="genreId" />
</template>

Generic komponentga havolani ref da ishlatish uchun InstanceType ishlamagani uchun vue-component-type-helpers kutubxonasidan foydalanish kerak.

vue
<script
  setup
  lang="ts"
>
import componentWithoutGenerics from '../component-without-generics.vue';
import genericComponent from '../generic-component.vue';

import type { ComponentExposed } from 'vue-component-type-helpers';

// Generic'siz komponent uchun ishlaydi
ref<InstanceType<typeof componentWithoutGenerics>>();

ref<ComponentExposed<typeof genericComponent>>();

Cheklovlar

  • Modul ishga tushirish semantikasi farqi tufayli, <script setup> ichidagi kod SFC kontekstiga tayanadi. Tashqi .js yoki .ts fayllariga ko'chirilganda, bu ham ishlab chiquvchilar, ham asboblar uchun chalkashlikka olib kelishi mumkin. Shuning uchun, <script setup> src atributi bilan ishlatilishi mumkin emas.
  • <script setup> In-DOM Root Komponent Shablonini qo'llab-quvvatlamaydi.(Muhokama)
<script setup> allaqachon yuklandi