Vue-next (Vue 3) уже давно отсутствует. Сейчас он находится на стадии релиз-кандидата, что означает, что в открытых API не будет больших изменений. Приятно видеть, что Vue уже стабилизировался и готов вальсировать в наши проекты.

Я должен сказать, что Vue 2 уже достаточно хорош. Но с новыми функциями Vue 3, вероятно, наши проекты будут обновлены до более высокого уровня. Думаю, самая захватывающая функция Vue 3 - это API-интерфейсы композиции. Сам Эван Ю упомянул, что API-интерфейсы композиции основаны на хуках React. Хотя эти два API-перехватчика и композиции во многом похожи, но с точки зрения кода они совершенно разные. Давайте не будем обсуждать, что лучше или многообещающе, потому что я действительно не думаю, что одна из этих рамок превосходит другую.

В целом, я так счастлив видеть, что Vue также может делать то, что делает React. Давайте внимательно посмотрим на новые функции.

TL; DR;

Посетите Pitayan.com, чтобы прочитать оригинал статьи.



1. Вите

Это еще одно произведение искусства Эвана Ю, цель которого заменить Webpack в разработке Vue (в настоящее время работает только для Vue). Он разработан, чтобы быть быстрым, как следует из его французского названия.

Начало работы с Vite

Официальное репо предлагает нам простой способ создать приложение Vue 3 через Vite.

Npm

$ npm init vite-app <project-name>
$ cd <project-name>
$ npm install
$ npm run dev

Пряжа

$ yarn create vite-app <project-name>
$ cd <project-name>
$ yarn
$ yarn dev

Запустить Dev Server

Все произошло в мгновение ока.

❯ yarn dev
yarn run v1.22.4
$ vite
vite v1.0.0-rc.4
  Dev server running at:
  > Local:    http://localhost:3000/
  > Network:  http://192.168.3.2:3000/
  > Network:  http://10.80.67.216:3000/

Откройте http: // localhost: 3000 /

Vue-next-features

Я создал небольшое приложение для демонстрации новых возможностей Vue 3. Если вы посмотрите на проекты »package.json, простота зависимостей vue-next-features сразу заставит вас полюбить Vite . (Я имею в виду, кто не хочет начинать с простого package.json?)

Существует еще одно репозиторий Vue 3 Hello World (vue-next-webpack-preview) в комплекте с Webpack. Это еще и хорошая детская площадка.

Vue-next-features

{
  ...,
  "dependencies": {
    "vite": "^1.0.0-rc.4",
    "vue": "^3.0.0-rc.5"
  },
  "devDependencies": {
    "@vue/compiler-sfc": "^3.0.0-rc.5"
  }
}

Vue-next-webpack-превью

{
  ...,
  "dependencies": {
    "vue": "^3.0.0-beta.2"
  },
  "devDependencies": {
    "@vue/compiler-sfc": "^3.0.0-beta.2",
    "css-loader": "^3.4.2",
    "file-loader": "^6.0.0",
    "mini-css-extract-plugin": "^0.9.0",
    "url-loader": "^4.0.0",
    "vue-loader": "^16.0.0-alpha.3",
    "webpack": "^4.42.1",
    "webpack-cli": "^3.3.11",¥
    "webpack-dev-server": "^3.10.3"
  }
}

2. Composition API

Как самое большое изменение Vue.js, API композиции станет вашей следующей наиболее часто и часто используемой функцией. Как и перехватчики React, API композиции Vue поможет получить больше возможностей настройки.

Вот список API композиции Vue 3. (На самом деле их больше…)

Реактивность

  • computed reactive ref readonly
  • watch watchEffect unref toRefs
  • isRef isProxy isReactive isReadonly
  • customRef markRaw shallowReactive
  • shallowReadonly shallowRef toRaw

Крючки жизненного цикла

  • onBeforeMount onBeforeUnmount onBeforeUpdate
  • onMounted onUpdated onErrorCaptured
  • onRenderTracked onRenderTriggered onUnmounted
  • onActivated onDeactivated

Посетите официальный документ Vue 3, чтобы узнать больше об этих API. Https://v3.vuejs.org/api/composition-api.html

Стили компонентов

В Vue 2

Используйте шаблон конфигурации для определения содержимого компонента. В Vue 3 это устаревшее использование все еще доступно. Если вы предпочитаете этот стиль, можете продолжать его использовать.

<template>
  <button @click="count++">count: {{ count }}</button>
</template>
<script>
const multiplier = 2
export default {
  data () {
    return {
      count: 0
    }
  },
  computed: {
    result () {
      return this.count * multiplier
    }
  },
  mounted () {
    console.log(this.count)
  },
  watch: {
    count (val, oldVal) {
      console.log(val, oldVal)
    }
  }
}
</script>

В Vue 3

Чтобы использовать API композиции, вам нужно добавить свойство setup в экспорт по умолчанию. Приведенный ниже код полностью эквивалентен приведенному выше коду.

<template>
  <button @click="count++">count: {{ count }}</button>
</template>
<script>
import { computed, reactive, toRefs, onMounted, watch } from 'vue'
export default {
  setup () {
    const multiplier = 2
    const state = reactive({
      count: 0
    })
    const result = computed(() => {
      return state.count * multiplier
    })
    onMounted(() => {
      console.log(state.count)
    })
    watch(state.count, (val, oldVal) => {
      console.log(val, oldVal)
    })
    return {
      ...toRefs(state)
    }
  }
}
</script>

Вперед с новым API

Есть 4 причины, по которым вы должны использовать API композиции вместо стандартного шаблона конфигурации Vue 2:

  • Для повышения читабельности исходного кода
  • Чтобы избежать дублирования или дублирования логики
  • Сгруппировать похожие логики
  • Чтобы повторно использовать логику

По сравнению со стилем конфигурации Vue 2, логика точно разбита на более мелкие части, чтобы вы могли легко сгруппировать похожие логики. Таким образом, это также снижает вероятность отклонения от несущественной логики. Это, без сомнения, поможет повысить производительность.

2. Advanced Reactivity API

Лично я думаю, что это ничем не отличается от других API реактивности. Но он действительно предлагает такие возможности обработки крайних случаев, как пользовательские крючки и мелкая модификация слоя. Согласно официальному документу Vue 3, теперь он является частью базового API реактивности.

В документе API композиции Vue (да, есть документ только для API композиции) следующие API перечислены как расширенные API реактивности.

  • customRef: пользовательский хук
  • markRaw: не может быть reactive
  • shallowReactive: первый слой объекта reactive
  • shallowReadonly: первый слой объекта readonly
  • shallowRef: значение объекта не reactive
  • toRaw: восстановить reactive до нормального объекта

Вы знакомы с Debounce? Вот официальная демонстрация customRef:

import { customRef } from 'vue'
const useDebouncedRef = (value, delay = 200) => {
  let timeout
  return customRef((track, trigger) => {
    return {
      get() {
        track()
        return value
      },
      set(newValue) {
        clearTimeout(timeout)
        timeout = setTimeout(() => {
          value = newValue
          trigger()
        }, delay)
      },
    }
  })
}
export default {
  setup () {
    return {
      text: useDebouncedRef('some text')
    }
  }
}

3. v-вход-из / v-выезд-из

В Vue 2 компонент <Transition> помогает обрабатывать компонент animation / transition. Но свойство компонента v-enter-active v-enter v-enter-to было для меня довольно неоднозначным. Иногда я не понимаю, что происходит первым.

Теперь в Vue 3 эти имена свойств перехода стали более унифицированными и интуитивно понятными.

  • v-enter => v-enter-from
  • v-leave => v-leave-from
<template>
  <transition name="fade">
    <div v-show="show">fade transition</div>
  </transition>
</template>
<script>
import { reactive, toRefs } from 'vue'
export default {
  setup () {
    const state = reactive({
      show: true
    })
    setTimeout(() => {
      state.show = false
    }, 1000)
    setTimeout(() => {
      state.show = true
    }, 2000)
    return {
      ...toRefs(state)
    }
  }
}
</script>
<style>
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
.fade-enter-to,
.fade-leave-from {
  opacity: 1;
}
.fade-enter-active,
.fade-leave-active {
  transition: opacity 2000ms;
}
</style>

Порядок перехода:

  1. v-enter-from (v-ввод)
  2. v-enter-active
  3. v-enter-to
  4. v-leave-from (v-отпуск)
  5. v-leave-active
  6. v-leave-to

Я считаю, что это намного легче понять, не так ли?

4. Разрешить использование нескольких корневых элементов

Vue 2 выдает ошибки для нескольких корневых элементов. Все элементы должны быть вложены в один корневой элемент в шаблоне.

<!-- Error -->
<template>
  <div>pitayan</div>
  <div>blog</div>
</template>
<!-- One Root Element only -->
<template>
  <div>
    <div>pitayan</div>
    <div>blog</div>
  </div>
</template>

Vue 3 удалил это надоедливое использование. Я думаю, что это чрезвычайно полезно, когда вы действительно не хотите вкладывать свои элементы в родительский «контейнер». Иногда все, что вам нужно, это просто вставить эти голые элементы в нужное место.

Это работает аналогично Реагировать фрагментам, что помогает смягчить проблемы вложенности.

<!-- Vue 3 Multiple Root Element -->
<!-- Okay -->
<template>
  <div>pitayan</div>
  <div>blog</div>
</template>

5. «Фильтры устарели (удалены) »

Я думаю, что многие люди думают, что filters - это, возможно, замечательная функция Vue.js. Это действительно хорошо работает в движке шаблонов Vue. (Например, форматирование данных / расчет и т. Д.).

Давайте посмотрим, как документ Vue 3 объясняет, почему был удален filters:

Хотя это кажется удобством, для этого требуется специальный синтаксис, который нарушает предположение, что выражения внутри фигурных скобок являются «просто JavaScript», что требует затрат как на обучение, так и на реализацию.

Я считаю, что для разработки без filters нет ничего плохого, хотя это может стоить вам дополнительного времени при переходе на Vue 3. В моих проектах появление filters - довольно редкий случай, поскольку я мог бы легко заменить такую ​​функциональность на method или computed. Потому что, на мой взгляд, method / computed имеет более высокую читаемость, чем filters.

<template>
  <!-- Deprecated (removed) & Error -->
  <span>{{ count | double }}</span>
  <!-- If you have to use fiter, make it a function -->
  <span>{{ double(count) }}</span>
</template>
<script>
import { ref } from 'vue'
export default {
  // Not working
  filters: {
    double (val) {
      return val * 2
    }
  },
  setup () {
    const count = ref(1)
    return {
      count,
      double: val => val * 2
    }
  }
}
</script>

6. Новый асинхронный компонент: приостановка

Это, пожалуй, единственная новая функция Vue 3, которая может быть изменена даже после официального выпуска. Вдохновение также от React Suspense. Так что, на мой взгляд, сценарий использования будет таким же.

Вы помните, как вы раньше отображали асинхронные данные в Vue 2? Я думаю, что v-if / v-else должно быть ответом.

<template>
  <div>
    <div v-for="i in items" :key="i">{{ i }}</div>
    <div v-else>loading...<div>
  </div>
</template>
<script>
export default {
  data () {
    return {
      items: null
    }
  },
  mounted () {
    this.items = await new Promise(resolve => {
      setTimeout(() => {
        return resolve(['one', 'two'])
      }, 3000)
    })
  }
}
</script>

С компонентом Suspense вы можете сделать это, не обрабатывая условия самостоятельно. Установив слот default и fallback, компонент Suspense автоматически обработает асинхронное событие.

<template>
  <suspense>
    <template #default>
      <div v-for="i in items" :key="i">{{ i }}</div>
    </template>
    <template #fallback>
      Loading...
    </template>
  </suspense>
</template>
<script>
export default {
  async setup () {
    const items = await new Promise(resolve => {
      setTimeout(() => {
        return resolve(['one', 'two'])
      }, 3000)
    })
    return {
      items
    }
  }
}
</script>

7. Показать его в другом месте: Телепорт

Еще одна крутая штука на базе React Portals. Он предоставляет возможность вставлять компонент в целевой узел DOM.

Что мы делаем в Vue 2 для вставки пользовательского компонента в <body> (конечно, существует сторонний плагин Vue PortalVue, обеспечивающий такую ​​функциональность):

import Vue from 'vue'
const Ctor = Vue.extends({
  template: `<div>hello world</div>`
})
const vm = new Ctor({ ... }).$mount()
document.body.appendChild(vm.$el)

Чтобы использовать такую ​​функцию в Vue 3, оберните целевой компонент в <Teleport> и определите целевой узел (querySelector) в свойстве to.

<template>
  <Teleport to="body">
    <div>Pitayan</div>
  </Teleport>
</template>

8. Разрешить несколько v-моделей

v-model используется для двусторонней привязки данных в элементах формы или даже в пользовательских компонентах. В Vue 2 пользовательский компонент может иметь только один v-model в теге.

<template>
  <my-input-form v-model="input" />
</template>

Vue 3 снял ограничение и позволяет вам иметь несколько v-model, чтобы вы могли указывать привязки отдельно для большего количества входных элементов.

<template>
  <my-input-form
    v-model:first="inputFirst"
    v-model:second="inputSecond"
    />
</template>

9. Глобальные API

Vue 3 предлагает несколько новых API, которые помогут нам лучше контролировать компоненты и экземпляры.

CreateApp

В Vue 2 Vue можно использовать как конструктор для возврата объекта-экземпляра. В Vue 3 вместо этого вы можете использовать функцию createApp. На самом деле поведение такое же.

// Vue 2
import Vue from 'vue'
import App from '@/src/App'
new Vue({
  el: '#app',
  components: {
    App
  }
})
// Vue 3
import { createApp } from 'vue'
import App from '@/src/App'
const app = createApp(App)

А как насчет таких глобальных методов, как extend component mixin и directive?

То же самое, но вместо этого вам нужно использовать метод экземпляра.

// Global methods
app.extend()
app.component()
app.mixin()
app.directive()

NextTick

Я думаю, что nextTick - это часто используемый API, поскольку многие логики на самом деле асинхронны, и их необходимо согласовать с следующим циклом обновления DOM.

В Vue 2 nextTick - это метод экземпляра.

export default {
  ...,
  mounted () {
    this.$nextTick(() => {
      console.log('pitayan')
    })
  }
}

Vue 3 позволяет использовать nextTick как независимую функцию.

// nextTick function type
export declare function nextTick(fn?: () => void): Promise<void>;
// An official doc Example
import { nextTick } from 'vue'
export default {
  setup () {
    const message = ref('Hello, Pitayan!')
    const changeMessage = async newMessage => {
      message.value = newMessage
      await nextTick()
      console.log('Now DOM is updated')
    }
  }
}

Другие вспомогательные функции

Эти новые API-интерфейсы будут чрезвычайно полезны, когда вам понадобятся дополнительные элементы управления для гораздо более абстрактных сценариев. Я лично считаю, что их можно часто использовать в сторонних библиотеках.

  • h: вернуть виртуальный узел
  • createRenderer: настраиваемое средство визуализации, которое можно использовать для кросс-средовых целей.
  • defineComponent: введите переданный объект
  • defineAsyncComponent: при необходимости загрузить асинхронный компонент.
  • resolveComponent: разрешить компонент в пределах текущей области действия экземпляра.
  • resolveDynamicComponent: разрешить динамический компонент в пределах текущей области действия экземпляра.
  • resolveDirective: получить directive из области текущего экземпляра
  • withDirectives: применяется directive к VNode

Выводы

Я очень счастлив и для меня большая честь наблюдать за развитием Vue.js 2.x = ›3.x. Команда Vue сделала вывод о том, что изначально было невозможно в Vue 2, и сделала это возможным в Vue 3. Как я мог видеть, есть много знакомых вещей из кодовой базы Vue 3.

Нетрудно сказать, что Vue 3 - гораздо более надежный фреймворк. Он обеспечивает новый и более простой способ организации исходного кода, в то же время меньшего размера и более быстрого. А с помощью Typescript и их новых функций, например API композиции, структура проектов может сильно отличаться от прежней. Я считаю, что это положительно повлияет на пользовательское сообщество.

Вот и все, что касается новой функции Vue 3.

Если вы думаете, что эта статья отличная. Поделитесь, пожалуйста, в социальных сетях. Спасибо за прочтение.

"Использованная литература"

Изначально на Pitayan.com