Рука об руку с вами, чтобы открыть магию мира Vue3

Vue.js

предисловие

2020 год суждено стать необычным: будь то появление эпидемии, ожесточенные потрясения в мире или взлеты и падения фондового рынка, я верю, что многие китайцы испытают глубокое чувство радости. что я китаец. Как тек хаус, кроме эпидемии, больше дождевых девчонок без дынь.Vue3.0 BetaПосле запуска все рвутся попробовать, и автор не исключение.После некоторых исследований я чувствую, чтоVue3У него есть свое неповторимое очарование, и вы должны вести блог, чтобы друзья, которые еще не испытали его, могли быстро получить общее представление о нем.

Начинать

По умолчанию вы уже знакомы с этой статьейVue2.xсвязанная информация

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

Соответствующая версия библиотеки

  • Vue-Cli 4.x
  • Vue 3.0.0-beta.1
  • Vue-Router 4.0.0-alpha.7

Конкретные шаги заключаются в следующем:

  1. использоватьVueCliСоздаватьVueБазовый проект:vue create project
  2. В проекте выполните команду обновления:vue add vue-next

Структура каталогов проекта выглядит следующим образом:

После правильного выполнения вышеуказанных операций базовая среда настроена.

Настроить маршрутизацию

  • внедрение в проектnpm install vue-router@4.0.0-alpha.7 -S

По общему правилу вsrcновый каталогrouterпапка и вrouterновый в папкеindex.jsдокумент.

Содержимое index.js:

import { createRouter, createWebHashHistory } from 'vue-router';
import Home from '../components/home'

const routes = [
    {path: '/', redirect: '/home'},
    {path: '/home', component: Home}
]

export default createRouter({
    history: createWebHashHistory(),
    routes
})

Базовая конфигурация маршрутизации не сильно изменилась, большую часть времени нужно просто обращать вниманиеroutesПравила маршрутизации прописаны в . Далее нам нужноmain.jsсредний доступrouter.

main.js:

import { createApp } from 'vue';
import App from './App.vue'
import router from './router';

const app = createApp(App);

app.use(router);
app.mount('#app');

отличается от нашего предыдущегоnew Vue()Создайте экземпляр,Vue3Здесь внесены изменения, мало того, нетрудно обнаружить, что и способ установки роутинга изменен предыдущимVue.use(Router)становится указанным выше образом, аналогично дляVuexДоступ тоже аналогичен, здесь автор не будет вдаваться в подробности.

App.js

<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

Предварительное изучение базовой грамматики

setup

Функция настройки — это новая опция компонента, которая действует как точка входа для использования Composition API (новая функция) внутри компонента; когда создается экземпляр компонента, он вызывается сразу после разрешения начального реквизита. С точки зрения жизненного цикла, он вызывается перед хуком beforeCreate.

Вообще говоря, согласно нашему предыдущему обычному способу написания, когда нам нужно использовать переменные и вычисляемые свойства, мы обычно будем писать:

home/index.vue

<template>
    <div class='home'>
        <div>{{count}}</div>
        <div>{{foo}}</div>
    </div>
</template>

<script>

import { ref } from 'vue'

export default {
    name: 'home',
    data() {
        return {
            count: 0
        }
    },
    computed: {
        foo() {
            return this.count + 1;
        }
    }
};

Два должны быть классифицированы в свои собственные объекты.С точки зрения реализации равной функции,Vue3Реализация выглядит следующим образом:

<template>
    <div class='home'>
        <div>{{count}}</div>
        <div>{{foo}}</div>
    </div>
</template>

<script>

import { ref, computed } from 'vue'

export default {
    name: 'home',
    setup(props, context) {
        const count = ref(0)
        const foo = computed(() => count.value + 1)
        return {
            count,
            foo
        }
    }
};
</script>

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

setupПолучает два важных параметра:

  • реквизит: Это, естественно, не нужно упоминать, это эквивалентноvue2изprops, на что нам нужно обратить внимание в этом месте, так это на то, что мы не можем деконструировать этот параметр, если использование деструктуризации сделает его невосприимчивым. Например, следующий код сделаетpropsПереданное значение перестает отвечать на запросы:
export default {
  props: {
    name: String
  },
  setup({ name }) {
    watchEffect(() => {
      console.log(`name is: ` + name) // 失去响应性!
    })
  }
}

  • context: На самом деле этот параметр нам тоже знаком. Он предоставляет объект контекста, который предоставляет выборочный список свойств, ранее предоставленных this в API 2.x. Он содержит только три свойства (attrs,slots,emit), дать каштан:
setup(props, context) {
    context.attrs // 2.x:this.attrs
    context.slots // 2.x:this.slots
    context.emit // 2.x:this.emit
}

Прочитав код, мы можем в основном понять, какsetupФункция — это логическая связь между всем нашим компонентом и входом операции.Vue3, мы используем разныеapiВсе методы в виде импорта, а это значит, что мы имеем большее рабочее пространство и большую свободу.

хотяVue3обратная совместимостьVue2, но здесь нам нужно обратить внимание на то, что мы должны стараться избегать 2.x иsetupСмешивание функций, это вызовет некоторые проблемы.

reactive

Реактивный прокси, который принимает объект и возвращает исходный объект. Это эквивалентно 2.xVue.observable().

к этомуapiИспользование, автор лучше поймет это с объяснением кода:

<template>
    <div class='home'>
        <div>{{name}}</div>
    </div>
</template>

<script>

import { reactive } from 'vue'

export default {
    name: 'home',
    setup() {
        const obj = reactive({name: '流星啊'})
        obj.name = 'bilibili'; // 修改属性值
        return obj;
    }
};
</script>

Я считаю, что все видели подсказки, да, этоapiЭто просто делает объект отзывчивым.

ref

Принимает внутреннее значение и возвращает реактивный и изменяемый объект ссылки. Объект ref имеет единственное свойство .value, которое указывает на внутреннее значение.

Тут, наверное, некоторые друзья спросят, а это не реф в 2.х, нет-нет, в 3.х он такой же, как тот, что посажен на этикеткеrefне имеет ничего общего с$refsНечего делать, для новой 2.x-подобной выборкиdomСм. раздел «Ссылки на шаблоны».

Аналогично возьмем каштан:

<template>
    <div class='home'>
        <div>{{count}}</div>
    </div>
</template>

<script>

import { ref } from 'vue'

export default {
    name: 'home',
    setup() {
        const count = ref(0);
        count.value++; // 有疑问的往下看笔者介绍
        console.log(count.value);
        return {
            count
        };
    }
};
</script>

Здесь также есть примечание: если вы хотите изменить переменную, созданную с помощью ref, вы можете толькоxxx.valueвносить изменения так же, как вы хотитеjsЧтобы получить доступ к его значению, вы должны использоватьxxx.value, присвойте значение непосредственно счетчику, напримерcount++, этот способ записи даст ошибку.

Подсчитано, что здесь есть и другие друзья, чтобы спросить, почему ты здесь?templateиспользуется в шаблоне{{count}}Не нужно добавлять при посещении.value, здесь на самом деле, когда вы используете выражение интерполяции, оно будет автоматически расширено внутри, поэтому мы можем использовать его напрямую.

Если мы положимreactiveа такжеrefКакие странные и хитроумные приемы будут сочетаться в его использовании😱, продолжайте дарить каштан:

const count = ref(0)
const state = reactive({
  count
})

console.log(state.count) // 0

state.count = 1
console.log(count.value) // 1

Когда ссылка используется или изменяется как свойство объекта реакции, она автоматически расширяется до внутреннего значения, поэтому ведет себя как обычное свойство.

computed

этоapiТакже аналогично 2.x, вы можете использоватьgetter,setter, без лишних слов, в коде:

const count = ref(1)
const plusOne = computed(() => count.value + 1)

console.log(plusOne.value) // 2

plusOne.value++ // 无效

Здесь нас не сложно найти, его метод доступа также эквивалентенref, также необходимо использоватьxxx.value, в то же время, если вы хотите изменить значение вычисляемого свойства, вы должны установить егоsetterи измените соответствующие зависимости. Не говорите чушь, посмотрите на код:

const count = ref(1)
const plusOne = computed({
  get: () => count.value + 1,
  set: val => {
    count.value = val - 1
  }
})

plusOne.value = 1
console.log(count.value) // 0

readonly

Как следует из названия, это построение атрибута, доступ к которому возможен только.Эта штука очень целенаправленная, то есть, как бы глубоко ни был вложен ваш объект, обернутый им объект должен быть доступен только для чтения, по сути, это Для прокси вполне:

const re = reactive({count: 0})
const readonlyRe = readonly(re);
readonlyRe.count++; // 无效,并且会给出警告

watchEffect

Для этого свойства вы можете использовать его с 2.xwatchОбъекты сравниваются, и да, он здесь, чтобы следить.

const count = ref(0)

watchEffect(() => console.log(count.value))
// -> 打印 0

setTimeout(() => {
  count.value++
  // -> 打印 1
}, 100)

В общем, он соберет зависимости входящей функции, и как только зависимости изменятся, он снова вызовет переданную вами функцию.react hooksДетские сапоги могут сказать, как эта вещь выглядит так многоuseEffect,фактическиVue3действительно заимствовано изreactНесколько хороших дизайнов, так что не думайте, что плагиат — это не плагиат, в конце концов, фреймворк предназначен для пользователей, и хороший дизайн должен быть достойным изучения, как иreactТак же есть урокиVueНекоторые из преимуществ оптимизации себя.

Далее продолжаем анализ этогоapi. назовите этоapiВ то же время он вернет функцию, используемую для приостановки дескриптора, мы можем явно вызвать ее для остановки текущего слушателя, а для входящего вwatchEffectфункция обратного вызова, этоapiФункция для регистрации недопустимых обратных вызовов передается при срабатывании вызова.onInvalidate. Конкретные примеры следующие:

const stop = watchEffect(onInvalidate => {
  const token = performAsyncOperation(id.value); // 执行一个异步操作
  onInvalidate(() => {
    // 依赖的id发生变化,但是异步操作还未完成,我们就可以在这里停止你的异步操作。
    token.cancel(); // 这里我们假设你的异步操作返回了一个包含取消操作的方法。
  })
})

stop(); // 我们可以使用这个方法去停止它

Если мы регистрируем недопустимый метод обратного вызова, то когда эта зависимость изменилась, но асинхронный запрос не был выполнен, это поможет нам вызвать наш внутренний регистрационный недопустимый обратный вызов.

функция жизненного цикла

Вот сравнение с 2.x:

  • beforeCreate (vue3弃用) -> 使用 setup()
  • created (vue3弃用) -> 使用 setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured

Пример использования:

import { onMounted, onUpdated, onUnmounted } from 'vue'

const MyComponent = {
  setup() {
    onMounted(() => {
      console.log('mounted!')
    })
    onUpdated(() => {
      console.log('updated!')
    })
    onUnmounted(() => {
      console.log('unmounted!')
    })
  }
}

ссылка на шаблон

перед просмотромrefПосле внедрения этого апи я точно буду сомневаться в своих друзьях, так что получуdomчто делать, этоVue3Есть и такие, расслабьтесь и слушайте, как автор продолжает объяснять.

<template>
    <div class='home'>
        <div ref="dom"></div>
    </div>
</template>

<script>

import { ref, onMounted } from 'vue'

export default {
    name: 'home',
    setup() {
        const dom = ref(null)
        onMounted(() => {
            console.log(dom.value);
        })
        return {
            dom
        }
    }
};
</script>

Из кода мы можем узнать, что теперь этот доступdomОтличие метода от предыдущего заключается в том, что нам нужно явно задать адаптивную переменную, а затем использовать ее в шаблоне до того, как мы познакомимся со способомref='xxx'сделать настройки.

конец

Прослушав рассказ автора, вы правы?Vue3Есть идея попробовать 😜.

Если вы считаете высказывание автора неуместным, пожалуйста, ткните автора в область комментариев, большое спасибо 😝.