Расширенный Vue3.0, построение среды, использование связанных API

Vue.js

оригинал:Моя статья о саде в блоге

Обратите внимание на публичный номер: поиск WeChatweb全栈进阶; получить больше галантерейных товаров

1. Официальная ссылка на китайский документ

https://vue3js.cn/docs/zh/

Во-вторых, начало

  • Vue3.0 был официально выпущен с разминки прошлого года до вечера 18 сентября.vue3.0 betaВерсия;
  • betaверсия означаетvue3.0Открытие официально занесено в проект, все могут учиться с удовольствием (вы продолжаете разрабатывать новые front-end технологии, а я еще могу учиться...потому что я должен есть, чтобы жить!!!);
  • Экосистема передовых технологий постоянно обновляется, и многие думают, что Александр больше не может учиться, но если ты не можешь учиться, ты можешь перестать учиться. . .0.0; Вы должны учиться, если вы не можете учиться, иначе вы будете устранены только в том случае, если вы адаптируетесь к себе.

3. Предложения по проекту vue2.0

Процитирую автора официальной документации:

намекать:

我们仍在开发 Vue 3 的专用迁移版本,该版本的行为与 Vue 2 兼容,运行时警告不兼容。如果你计划迁移一个非常重要的 Vue 2 应用程序,我们强烈建议你等待迁移版本完成以获得更流畅的体验.

В настоящее время автор имеет в виду: для vue2.0проект强烈不建议подняться наvue3.0; потому что текущийbetaВерсии и существующие фреймворки и плагины не очень поддерживаются и совместимыvue3.0синтаксис; так что должно быть много непредвиденных проблем; для стремительных обновленийvue3.0Друзья, нам остается только дождаться разработки официальной совместимой версии и сделать миграцию, ведь онлайн-проект — это не шутки, естьbugможет быть большой потерей. Этот горшок в принципе неподвижен без мин дома...

4. Введение

Что дает Vue3?Общедоступный номер: фронтальные статьи для утреннего чтения

Для получения подробной документации см.:Официальная ссылка на китайский документ

  • Быстрее
    • рефакторингVirtual DOM
      • Пометка статического контента и выделение динамического контента
      • только обновлениеdiffдинамическая часть
    • рефакторинг双向数据绑定
      • Object.defineProperty() --> Proxy API
      • ProxyДля сложных структур данных мониторинг рекурсии цикла уменьшен, рекурсия цикла начального рендеринга очень требовательна к производительности;
      • ProxyДля метода мутации массива (который изменит исходный массив) больше не нужно отдельно переписывать и обрабатывать нативный метод массива.
      • Грамматика такжеdefinePropertyГораздо проще, просто контролируйте свойство напрямую;
    • кэш событий
      • vue2, для события привязки каждый раз, когда оно запускается, создается новыйfunctionобновить;
      • Vue3, предоставляется объект кэша событийcacheHandlers,когдаcacheHandlersЕсли этот параметр включен, компиляция автоматически сгенерирует встроенную функцию и превратит ее в статический узел, поэтому при повторном запуске события нет необходимости воссоздавать функцию для прямого вызова метода обратного вызова кэшированного события.
  • меньше (Tree shakingслужба поддержки)
    • Короче говоря: не упаковывайте все, только то, что вы используетеapi; Для больших проектов вы обнаружите, что горячая загрузка и первоначальный рендеринг значительно улучшились.
    • Значительно сокращает избыточный код при разработке и повышает скорость компиляции.
  • легче поддерживать
    • Vue3отFlowпереехал вTypeScript
      • В случае совместной разработки с несколькими людьми используйтеTypeScriptВы после этого будете жаловаться на кислинку, почему не появились раньше?TypeScript
    • Структура каталогов кода соответствует монорепозиторию.
      • Основная точка зрения: код разделен на небольшие модули, большинство разработчиков работают только с несколькими папками и будут компилировать только те модули, за которые они несут ответственность, вместо того, чтобы компилировать весь проект.
  • Новые функции и возможностиComposition API
    • Не заботьтесь о том, чтобы становиться все более и более похожим на react-hook, в конце концов, чужие преимущества стоит изучить самому;
    • Composition APIФункциональная разработка значительно повышает возможность повторного использования компонентов и бизнес-логики; сильно развязана; улучшает качество кода и эффективность разработки; уменьшает размер кода.
  • Повышение эффективности разработкиviteподдержку (конечно покаviteФункция недостаточно мощная и стабильная, но Youda воспринимает ее какvue3Официальный инструмент сборки, который определенно улучшит его; свободный выборwebpackещеvite)
    • viteНативный браузер в среде разработкиES importsразработки, в производстве на основеRollupПакет
      • быстрый холодный пуск
      • Мгновенное горячее обновление модуля
      • Настоящая компиляция по запросу
    • vue2.0Я считаю, что многие мелкие партнеры объединеныwebpackРазработка; Но заметили ли вы, что первоначальный проект был очень крутым, когда он был маленьким. Запуск, компиляция и горячая загрузка были быстрыми; когда проект был большим... При упаковке, запуске и изменении функции на горячую загрузку ... Давай сначала в туалет/ Набери воды, это раздражает, когда ты занят
    • vue3.0комбинироватьviteНа авторское вступление не влияет огромный размер проекта, и то, что было в начале, есть и сейчас, конечно преувеличение немного преувеличено, но разница не должна быть большой;

5. Строительство окружающей среды

// 对于 Vue 3,应该 npm 上可用的 Vue CLI v4.5 作为 @vue/cli@next
yarn global add @vue/cli@next
# OR
npm install -g @vue/cli@next

// 创建项目
npm init vite-app <project-name>
# OR
yarn create vite-app <project-name>

// 下载依赖及运行项目, 已 npm 方式为例; 详细步骤官方文档的安装页都有
cd <project-name>
npm install
npm run dev // 项目就能跑起来并且访问了

Расширение: проект представляет другие плагины, такие как vue-router4.0, vuex4.0, typescript и т. д. Пожалуйста, обратитесь кСоздание среды Vue3.0

6. Введение в грамматику

Прежде чем начать, вы должны прочитать некоторые изменения vue3 в vue2; нажмите, чтобы узнать подробностиОсновные изменения в документах официального сайта

vue2используется вOptions API; vue3в томComposition APIЧисто функциональный API для краткости

6.1 настройка

vue3Запись компонентаsetup(){}Функция используется как запись и по умолчанию выполняется только один раз, порядок выполнения указан вbeforeCreateПозжеcreatedДо;

...
// 使用props和this
setup (props, ctx) {
  // props 组件间传递的参数; 
  // ctx 组件的实例的执行上下文(可以理解为 vue2 this) 
     /* 可执行 下面等操作:例 ctx.$emit() 
     attrs: Object
     emit: ƒ ()
     listeners: Object
     parent: VueComponent
     refs: Object
     root: Vue 
     */
  // 注意 steup 中没有this了, 拿不到this
}

6.2, жизненный цикл

Я помню, как рано сказалvue3устраненbeforeCreate,createdДва жизненных цикла, но на практике я обнаружил, что писать все же можно, потому чтоvue2,vue3Написание в настоящее время совместимо;

created () { console.log('created') }
setup (props, ctx) {
  console.log('setup')
  // mounted 新写法 记住一句话 所有的方式都是以函数的形式呈现
  onMounted(() => {})
}
mounted () { console.log('mounted') }
// 执行顺序 setup created mounted

Хоть и совместимо, но старайтесь не писать так, ждите, настоятельно рекомендуется поставить все это вsteupв функции

6.3, реактивный, ссылка, toRefs, isRef

Создание реактивных объектовreactive、ref、toRefsиспользование, корреспонденцияvue2серединаdata Рекомендуемое письмо 3

// 写法一:响应式数据一多, return 要很多次; 使用数据的时候要通过state拿到
<template>
  <div>
    <p>{{state.count}}</p>
  </div>
</template>
import {reactive} from 'vue'
...
setup(props, ctx) {
  const state = reactive({ 
    count: 0
  })
  return { state }
}
// 写法二
<template>
  <div>
    <p>{{count}}</p>
  </div>
</template>
import {reactive} from 'vue'
...
setup(props, ctx) {
  const state = reactive({ 
    count: 0
  })
  return {
    count: state.count
  }
}
// 写法三:推荐 通过 toRefs 代理对象, 再通过解构的方式取值
<template>
  <div>
    <p>{{count}}</p>
  </div>
</template>
import {reactive, toRefs} from 'vue'
...
setup(props, ctx) {
  const state = reactive({ 
    count: 0
  })
  return {
    ...toRefs(state)
  }
}
// 写法四:通过 ref() 函数包装, 返回值是一个对象,对象上只包含一个 value 属性, 就是要的属性值
<template>
  <div>
    <p>{{count}}</p>
    <p>{{count1}}</p>
  </div>
</template>
import {reactive, toRefs, ref} from 'vue'
...
setup(props, ctx) {
  // 父组件传递count属性
  // 写法1
  const count = ref(props.count)
  console.log(count.value) // 对应props.count的值
  // 写法2 
  const state = reactive({ 
    count1: ref(props.count)
  })
  return {
    count,
    ...toRefs(state)
  }
}
// isRef 来判断某个值是否为 ref() 创建出来的对象
import { ref, isRef } from 'vue';
export default {
  setup(props, ctx) {
    const refCount = ref(0)
    const count = isRef(refCount) ? refCount : 1
  }
};

6.4, рассчитано

Пример сценария: объединениеvue-routerПо текущей прочности дорогиcountназначить, а также расширитьvue-routerПрименение

<template>
  <div>
    <p>{{count}}</p>
    <p>{{count1}}</p>
  </div>
</template>
import {reactive, toRefs, computed} from 'vue'
import {useRoute} from 'vue-router'
...
setup(props, ctx) {
  const route = useRoute()
  const state = reactive({ 
    // 计算属性 写法1
    count: computed(() => {
      return route.path
    })
  })
  // 计算属性 写法2
  const count1 = computed(() => {
    return route.path
  })
  return {
    ...toRefs(state),
    // 计算属性不需要通过 toRefs 结构, 因为他就是一个具体的值就是响应式的
    count1
  }
}

6.5, часы, часы

Пример сценария: такой же, как вычислено

watchEffectа такжеwatchв чем разница:

  1. watchEffectНет необходимости указывать отслеживаемые свойства, он будет автоматически собирать зависимости, пока мы обращаемся к отзывчивым свойствам в обратном вызове, тогда при изменении этих свойств будет выполняться обратный вызов
  2. watchСлушайте только указанные свойства
  3. watchможет получить новое значение и старое значение, иwatchEffectнет
  4. watchEffectОн выполняется один раз, когда компонент инициализируется для сбора зависимостей (сcomputedТочно так же обратный вызов будет выполняться снова, когда впоследствии изменятся собранные зависимости.
// watch 用法 监听单个属性
<template>
  <div>
    <p>{{count}}</p>
  </div>
</template>
import {reactive, toRefs, watch} from 'vue'
import {useRoute} from 'vue-router'
...
setup(props, ctx) {
  const route = useRoute()
  const state = reactive({ 
    count: 0,
  })
  // 监听路由路劲, immediate 是否立即执行一次
  watch(() => route.path, (newValue) => {
    state.count = newValue
  }, { immediate: true })
  
  return {
    ...toRefs(state),
  }
}
// watch 用法 监听ref数据源
<template>
  <div>
    <p>{{count}}</p>
  </div>
</template>
import {reactive, toRefs, ref, watch} from 'vue'
...
setup(props, ctx) {
  // 定义数据源
  let count = ref(0);
  // 指定要监视的数据源
  watch(count, (count, prevCount) => {
    console.log(count, prevCount)
  })
  setInterval(() => {
    count.value += 2
  }, 2000)
  console.log(count.value)
  return {
    count
  }
}
// watch 用法 监听多个属性
<template>
  <div>
    <p>{{count}}</p>
  </div>
</template>
import {reactive, toRefs, watch} from 'vue'
...
setup(props, ctx) {
  const state = reactive({ 
    name: 'vue',
    age: 3
  })
  watch(
    // 监听name、 age
    [() => state.name, () => state.age],
    // 如果属性改变、则执行以下回调
    ([newName, newAge], [oldname, oldAge]) => {
      console.log(oldname, oldname)
      console.log(oldAge, oldAge)
    },
    { lazy: true} // 在 watch 被创建的时候,不执行回调函数中的代码
  )
  setTimeout(() => {
    state.name = 'react'
    state.age += 1
  }, 3000)
  return {
    ...toRefs(state),
  }
}
// watchEffect 用法
<template>
  <div>
    <p>{{count}}</p>
  </div>
</template>
import {reactive, toRefs, ref, watchEffect} from 'vue'
import {useRoute} from 'vue-router'
...
setup(props, ctx) {
  const route = useRoute()
  const state = reactive({ 
    count: 0,
  })
  // 当 route.path 变化时就会执行打印, 有点类似 react-hook 的 useEffect 第二个参数效果
  watchEffect(() => {
    count = route.path
    console.log(route.path)
  })
  // watchEffect、 watch 都可以主动停止监听
  const stop = watchEffect(() => { 
    count = route.path
    console.log(route.path)
  })
  // 在某个时机下 执行 stop() 停止watchEffect监听
  if (...) { stop() }
  return {
    ...toRefs(state),
  }
}

Семь, некоторые API и методы удалены из Vue3.

7.1 Отмена KeyboardEvent.keyCode

существуетVue2.x, для привязки событий клавиатуры используется следующий код:

<!-- keyCode version -->
<input v-on:keyup.13="submit" />

<!-- alias version -->
<input v-on:keyup.enter="submit" />

или:

Vue.config.keyCodes = {
  f1: 112
}
<!-- keyCode version -->
<input v-on:keyup.112="showHelpText" />

<!-- custom alias version -->
<input v-on:keyup.f1="showHelpText" />

В случае чего датьkeyupНастроить конкретную кнопкуkeyCode(число) вVue3не вступит в силу, но псевдонимы по-прежнему можно будет использовать, например:

<input v-on:keyup.delete="confirmDelete" />

7.2 Удалитьon,on,методы off и $once

существуетVue2.xсквозьEventBusметод для реализации связи компонентов:

var EventBus = new Vue()
Vue.prototype.$EventBus = EventBus
...
this.$EventBus.$on()  this.$EventBus.$emit()

Это использование находится вVue3Это не будет работать вVue3удалено в $on,$offи другие методы (см. rfc), но рекомендуется использоватьmittпрограмма вместо:

import mitt from 'mitt'
const emitter = mitt()
// listen to an event
emitter.on('foo', e => console.log('foo', e) )
// fire an event
emitter.emit('foo', { a: 'b' })

7.3 Удаление фильтров

существуетVue3, компонентаfiltersпункт, вы можете использоватьmethodsилиcomputedзаменить:

<template>
  <p>{{ accountBalance | currencyUSD }}</p>
</template>
<script>
  export default {
    filters: {
      currencyUSD(value) {
        return '$' + value
      }
    }
  }
</script>

Заменить:

<template>
  <p>{{ accountInUSD }}</p>
</template>
<script>
  export default {
    props: {
      accountBalance: {
        type: Number,
        required: true
      }
    },
    computed: {
      accountInUSD() {
        return '$' + this.accountBalance
      }
    }
  }
</script>

Восемь, API и метод записи изменились в Vue3

8.1 Инициализация экземпляра

существуетvue2.xпрошедшийnew Vue()метод инициализации:

import App from './App.vue'
new Vue({
  store,
  render: h => h(App)
}).$mount('#app')

существуетvue3серединаVueбольше не является конструктором, черезcreateAppИнициализация метода:

import App from './App.vue'
createApp(App).use(store).mount('#app')

8.2 Изменения в способе вызова глобального API

существуетVue2.x, большая часть мировогоAPIна всем протяженииVue.xxxилиVue.abc()вызов метода, например:

  import Vue from 'vue'
  Vue.mixin()
  Vue.use()

пока вVue3, эти способы будут изменены и заменены следующими:

  import { createApp } from 'vue'
  const app = createApp({})
  app.mixin()
  app.use()

При этом можно лишь ввести некоторые необходимыеAPI, вводить не нужно, это тоже соответствует Тhree Shakingтребования, такие как:

  import { nextTick,reactive,onMounted } from 'vue'
  nextTick(() => {
  })
  onMounted(() => {
  })

из-заVue3Средний и глобальныйAPIпройдешьapp.xxxвызов метода, поэтому перед передачейVue.prototype.xxxПривязка глобальных методов и переменных будет недоступна и может быть заменена на:

  //在main.js中:
  app.config.globalProperties.http = function(){}

  //在vue组件中:
  this.http()

8.3 Модификация метода рендеринга

существуетVue2.x, иногда по индивидуальному заказуrenderметод для возврата содержимого шаблона следующим образом:

export default {
  render(h) {
    return h('div')
  }
}

существуетVue3середина,hпройти черезvueимпортировать следующим образом:

import { h } from 'vue'
export default {
  render() {
    return h('div')
  }
}

8.4 Новый метод создания асинхронного компонента

существуетVue2.xв, особенно вVue Router, часто используются асинхронные компоненты, с помощьюwebpackМетод упаковки может асинхронно получить код компонента, например:

const asyncPage = () => import('./NextPage.vue')
const asyncPage = {
  component: () => import('./NextPage.vue'),
  delay: 200,
  timeout: 3000,
  error: ErrorComponent,
  loading: LoadingComponent
}

существуетVue3, обеспечиваетdefineAsyncComponent()Метод создает асинхронный компонент и может возвращатьPromiseОбъект сам контролирует время завершения загрузки следующим образом:

import { defineAsyncComponent } from 'vue'
const asyncPageWithOptions = defineAsyncComponent({
  loader: () => import('./NextPage.vue'),
  delay: 200,
  timeout: 3000,
  error: ErrorComponent,
  loading: LoadingComponent
})
const asyncComponent = defineAsyncComponent(
  () =>
    new Promise((resolve, reject) => {
      /* ... */
    })
)

IX. ВРЕМЕННОЕ КОНЕЦ:

  1. Я пишу давно, и это немного многословно.Новый API в основном пишет несколько методов кодирования, и выбирает в соответствии с моими собственными предпочтениями.
  2. В будущем я буду постепенно добавлять собственное понимание и использование некоторых новых API.
  3. Ссылки на эту статью в заголовке: