Введение в проект
vue3-jd-h5Это интерфейсный проект страницы H5 для электронной коммерции, основанный наVue 3.0.0-beta.1+ Реализация Vant, в основном включая домашнюю страницу, страницу категории, мою страницу, корзину и т. д.
📖Локальный оффлайн кодvue2.6в филиалеdemoв использованииmockjsДанные для разработки, пожалуйста, нажмите для визуализации 🔗здесь
⚠️Главная ветка — это код рабочей онлайн-среды, так как некоторые из фоновых интерфейсов были приостановлены😫, фактический эффект может быть не виден.
📌 В этом проекте еще много недочетов, если у вас есть партнеры, которые хотят внести в это свою лепту, милости просим отправить нам PR или issue;
🔑 Этот проект бесплатный и с открытым исходным кодом. Если есть партнеры, которые хотят развивать вторичную разработку на этой основе, они могут клонировать или форкнуть весь репозиторий. Буду очень рад, если смогу вам помочь. Если вы считаете, что этот проект хорош , пожалуйста, начните! 🙏
шаги построения vue3
- Сначала выберите локальный файл и локально клонируйте код:
git clone https://github.com/GitHubGanKai/vue-jd-h5.git
- Посмотреть все ветки:
gankaideMacBook-Pro:vue-jd-h5 gankai$ git branch -a
demo
vue-composition-api
dev
feature
gh-pages
* master
remotes/origin/HEAD -> origin/master
remotes/origin/demo
remotes/origin/vue-composition-api
remotes/origin/dev
remotes/origin/feature
remotes/origin/gh-pages
remotes/origin/master
-
переключиться на веткуvue-composition-apiНачни развиваться!
-
Запустите команду в командной строке IDEA: npm install, загрузите связанные зависимости;
-
🔧 Среда разработки Запустите команду в командной строке IDEA:
npm run dev, запустить проект; -
📦Выполните команду в командной строке IDEA:
npm run dll:build,Упаковка предметов,📱Сканируйте QR-код ниже своим мобильным телефоном для просмотра!
Инициализация проекта
💡Если вы устанавливаете пакет на низкой скорости, это потому, что сервер NPM находится за границей.Вот инструмент, который может переключать зеркала NPM в любое время 👉NRM, Иногда, когда мы разрабатываем, для ускорения установки инсталляционного пакета нам нужно переключить зеркальный источник на отечественный, но если нам нужно опубликовать какие-то свои компоненты в NPM, мы должны переключиться обратно и п. С этим нам Намного удобнее! использовать$ npm install -g nrmУстановите глобально, затем вы можете использоватьnrm lsПосмотреть все зеркала:
gankaideMacBook-Pro:~ gankai$ nrm ls
npm -------- https://registry.npmjs.org/
* yarn ------- https://registry.yarnpkg.com/
cnpm ------- http://r.cnpmjs.org/
taobao ----- https://registry.npm.taobao.org/
nj --------- https://registry.nodejitsu.com/
npmMirror -- https://skimdb.npmjs.com/registry/
edunpm ----- http://registry.enpmjs.org/
Если вам нужно использовать зеркало Taobao, выполните:nrm use taobaoВы можете переключать источники в любое время, и, конечно же, есть инструмент управления версиями пакетов npm.nvm, в основном для версии пакета управления.Если вам интересно, то можете узнать сами, а я тут не буду многословен 😊!
Установить
Перейдите в корневой каталог проекта, который вы только что клонировали, и установите@vue/composition-apiИспытайте новые возможности vue3.
npmУстановить:
npm install @vue/composition-api --save
yarnУстановить:
yarn add @vue/composition-api
CDN
<script src="https://unpkg.com/@vue/composition-api/dist/vue-composition-api.umd.js"></script>
через глобальную переменнуюwindow.vueCompositionApiиспользовать.
использовать
используя любой@vue/composition-apiПрежде чем предлагать компетенцию, вы должны сначала пройтиVue.use()Установить:
во входном файлеmain.jsсередина:
import Vue from 'vue';
import VueCompositionApi from '@vue/composition-api';
Vue.use(VueCompositionApi);
После установки плагина вы можете использовать новыйComposition APIдля разработки компонентов.
⚠️ В настоящее время vue официально предоставляет плагин для vue-cli.vue-cli-plugin-vue-next, так же можно добавить последнюю версию прямо в проект!
# in an existing Vue CLI project
vue add vue-next
Если вы хотите испытать новую версию с нуля, вы можете использовать этот метод для ее установки.Поскольку наш проект зависит от сторонних библиотек, если вы устанавливаете его глобально, сторонняя библиотека пользовательского интерфейса всего проекта не будет работать! Итак, мы все еще выбираем установку
@vue/composition-apiиспытать, чтобы потихоньку перейти на последнюю версию vue3
Основные возможности Vue 3.0 Composition-API
функция настройки
setup()Функция — это новое свойство, специально предоставленное для компонентов в vue3, которое эквивалентно версии 2.x.createdФункция, параметры логики компонентов предыдущей версии теперь обрабатываются в этой функции. Он использует vue3 для насComposition APIНовая функция обеспечивает единую запись,setupФункция будет относительно 2.x, будет вbeforeCreateпосле,createdКазнить раньше! Для получения подробной информации см. следующее:
| vue2.x | vue3 |
|---|---|
| установка (альтернативный вариант) | |
| установка (альтернативный вариант) | |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| updated | onUpdated |
| beforeDestroy | onBeforeUnmount |
| destroyed | onUnmounted |
| errorCaptured | onErrorCaptured |
новый крючок
В дополнение к эквивалентам жизненного цикла 2.x Composition API предоставляет следующие перехватчики отладки:
onRenderTrackedonRenderTriggered
Оба крючка полученыDebuggerEventпохожий наonTrackиonTriggerВарианты наблюдателя:
export default {
onRenderTriggered(e) {
debugger
// inspect which dependency is causing the component to re-render
}
}
внедрение зависимости
provideиinjectВключить что-то вроде 2.xprovide/injectВнедрение зависимостей для опций. Оба могут быть толькоsetup()Вызывается во время текущего экземпляра действия.
import { provide, inject } from '@vue/composition-api'
const ThemeSymbol = Symbol()
const Ancestor = {
setup() {
provide(ThemeSymbol, 'dark')
}
}
const Descendent = {
setup() {
const theme = inject(ThemeSymbol, 'light' /* optional default value */)
return {
theme
}
}
}
injectПринимает необязательное значение по умолчанию в качестве второго параметра. Если значение по умолчанию не указано и свойство не найдено в контексте предоставления, тоinjectвозвращениеundefined.
Внедрить реактивные данные
Чтобы поддерживать реакцию между предоставленными и введенными значениями, вы можете использоватьref
// 在父组建中
const themeRef = ref('dark')
provide(ThemeSymbol, themeRef)
// 组件中
const theme = inject(ThemeSymbol, ref('light'))
watchEffect(() => {
console.log(`theme set to: ${theme.value}`)
})
- так как
setupФункция принимает 2 формальных параметра, первый из нихinitProps, то есть значение, отправленное родительским компонентом! , второй параметробъект контекста
setupContext, основными свойствами этого объекта являются:
attrs: Object // 等同 vue 2.x中的 this.$attrs
emit: ƒ () // 等同 this.$emit()
isServer: false // 是否是服务端渲染
listeners: Object // 等同 vue2.x中的this.$listeners
parent: VueComponent // 等同 vue2.x中的this.$parent
refs: Object // 等同 vue2.x中的this.$refs
root: Vue // 这个root是我们在main.js中,使用newVue()的时候,返回的全局唯一的实例对象,注意别和单文件组建中的this混淆了
slots: {} // 等同 vue2.x中的this.$slots
ssrContext:{} // 服务端渲染相关
⚠️Уведомление:существуетsetup()невозможно получить доступ в функцииthisда, независимо от этогоthisОтносится к глобальному объекту vue (т. е. к глобальному объекту экземпляра vue, сгенерированному new в main.js) или к объекту, сформированному одним файлом.
Но что, если мы хотим получить доступ к объекту экземпляра текущего компонента? мы можем принестиgetCurrentInstanceЭто API, возвращаемое значение - текущий сформированный экземпляр!
import { computed, getCurrentInstance } from "@vue/composition-api";
export default {
name: "svg-icon",
props: {
iconClass: {
type: String,
required: true
},
className: {
type: String
}
},
setup(initProps,setupContext) {
// ⚠️注意,如果是通过vue add vue-next添加的这个地方需要结构出ctx
const ctx = getCurrentInstance();
const iconName = computed(() => {
return `#icon-${initProps.iconClass}`;
});
const svgClass = computed(() => {
if (initProps.className) {
return "svg-icon " + initProps.className;
} else {
return "svg-icon";
}
});
return {
iconName,
svgClass
};
}
};
</script>
Ссылка автоматически расширяется (разворачивается)
ref()функция используется для созданияОтзывчивыйизобъект данных,ref()Возвращаемое значение вызова функции — это обернутый объект (RefImpl), который имеет только один.valueсобственности, если мы находимся вsetupВ функцию значение объекта, к которому вы хотите получить доступ, вы можете передать.valueполучить, но если<template>в шаблоне, вы можете напрямую получить к нему доступ, нет необходимости.value!
import { ref } from '@vue/composition-api'
setup() {
const active = ref("");
const timeData = ref(36000000);
console.log('输出===>',timeData.value)
return {
active,
timeData
}
}
<template>
<p>活动状态:{{active}}</p>
<p>活动时间:{{timeData}}</p>
</template>
⚠️Примечание: не ставитьArrayположить вref, свойства индекса массива не могут быть расширены автоматически, а такжене хотетьиспользоватьArrayпрямой доступrefОбъект:
const state = reactive({
list: [ref(0)],
});
// 不会自动展开, 须使用 `.value`
state.list[0].value === 0; // true
state.list.push(ref(1));
// 不会自动展开, 须使用 `.value`
state.list[1].value === 1; // true
Когда нам нужно манипулировать DOM, как мы используем в проектеswiperНужно получить DOM, тогда мы сможем это сделать 👇!
<div class="swiper-cls">
<swiper :options="swiperOption" ref="mySwiper">
<swiper-slide v-for="(img ,index) in tabImgs.value" :key="index">
<img class="slide_img" @click="handleClick(img.linkUrl)" :src="img.imgUrl" />
</swiper-slide>
</swiper>
</div>
затем вsetupопределить функциюconst mySwiper = ref(null);, раньше в vue2.x мы проходилиthis.$refs.mySwiperчтобы получить объект DOM, теперь вы также можете использоватьrefвместо этого функция, которая возвращаетmySwiperИ чтобыtemplateсвязаны вrefтакой же!
import { ref, onMounted } from "@vue/composition-api";
setup(props, { attrs, slots, parent, root, emit, refs }) {
const mySwiper = ref(null);
onMounted(() => {
// 通过mySwiper.value 即可获取到DOM对象!
// 同时也可以使用vue2.x中的refs.mySwiper ,他其实mySwiper.value 是同一个DOM对象!
mySwiper.value.swiper.slideTo(3, 1000, false);
});
return {
mySwiper
}
}
reactive
reactive()Функция принимает обычный объект и возвращает реактивный объект данных, что эквивалентноvue 2.xсерединаVue.observable()функция,vue 3.xпредоставлено вreactive()Функция для создания реактивных объектов данныхObserver,refОбычно мы хранимданные основного типа, если это ссылочный тип, мы можем использоватьreactiveфункция.
когдаreactiveВ функции получен типArrayмассив, мы можем использовать этоArrayВнешний слой обертывается объектом, а затем к объекту добавляется атрибут, например:value(Вы можете называть это свойство как угодно), и его значением является этот массив!
<script>
// 使用相关aip之前必须先引入
import { ref, reactive } from "@vue/composition-api";
export default {
name: "home",
setup(props, { attrs, slots, parent, root, emit, refs }) {
const active = ref("");
const timeData = ref(36000000);
// 将tabImgs数组中每个对象都变成响应式的对象
const tabImgs = reactive({
value: []
});
const ball = reactive({
show: false,
el: ""
});
return {
active,
timeData,
tabImgs,
...toRefs(ball),
};
}
};
</script>
затем вtemplateКогда мы хотим получить доступ к этому массиву в шаблоне, нам нужно использовать.valueчтобы получить значение этого массива.
<template>
<div class="swiper-cls">
<swiper :options="swiperOption" ref="mySwiper">
<swiper-slide v-for="(img ,index) in tabImgs.value" :key="index">
<img class="slide_img" @click="handleClick(img.linkUrl)" :src="img.imgUrl" />
</swiper-slide>
</swiper>
</div>
</template>
isRef
isRef()используется для определения того, является ли значениеref()Созданный объект; когда нужно расширить возможнуюref()При создании значения вы можете использоватьisRefсудить!
import { isRef } from '@vue/composition-api'
setup(){
const headerActive = ref(false);
// 在setup函数中,如果是响应式的对象,在访问属性的时候,一定要加上.value来访问!
const unwrapped = isRef(headerActive) ? headerActive.value : headerActive
return {}
}
toRefs
toRefsфункция будетреактивный объектпреобразовать внормальный объект, где каждое свойство возвращаемого объекта указывает на соответствующее свойство исходного объекта.ref, будет очень полезно при преобразовании всех свойств объекта в реактивные!
import { reactive,toRefs } from '@vue/composition-api'
setup(){
// ball 是一个 Observer
const ball = reactive({
show: false,
el: ""
});
// ballToRefs 就是一个普通的Object,但是ballToRefs里面的所有属性都是响应式的(RefImpl)
const ballToRefs = toRefs(ball)
// ref和原始属性是“链接的”
ball.show = true
console.log(ballToRefs.show) // true
ballToRefs.show.value = false
console.log(ballToRefs.show) // false
return {
...ballToRefs // 将ballToRefs对象展开,我们就可以直接在template模板中直接这样使用这个对象上的所有属性!
}
}
Нажимаем кнопку добавить, шарик влетает в анимацию корзины:
<template>
<div class="ballWrap">
<transition @before-enter="beforeEnter" @enter="enter" @afterEnter="afterEnter">
<!-- 可以直接使用show-->
<div class="ball" v-if="show">
<li class="inner">
<span class="cubeic-add" @click="addToCart($event,item)">
<svg-icon class="add-icon" icon-class="add"></svg-icon>
</span>
</li>
</div>
</transition>
</div>
</template>
computed
computedПервый параметр функции может принимать функцию или объект! Если это функция, по умолчаниюgetterфункцию, а дляgetterВозвращаемое значение возвращает доступный только для чтенияrefобъект.
import { computed } from '@vue/composition-api'
const count = ref(1)
// computed接收一个函数作为入参
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // 错误,plusOne是只读的!
Или это может быть объект, вы можете использоватьgetиsetобъект функции для создания доступного для записиrefобъект.
const count = ref(1)
// computed接收一个对象作为入参
const plusOne = computed({
get: () => count.value + 1,
set: val => {
count.value = val - 1
}
})
plusOne.value = 1
console.log(count.value) // 0
watch
watch(source, cb, options?)
ДолженwatchAPI с 2.xthis.$watch(и соответствующийwatchвариант) полностью эквивалентен.
Соблюдайте единый источник
Источником данных наблюдателя может быть функция-получатель, возвращающая значение, или он может быть напрямую ссылкой:
// watching a getter函数
const state = reactive({ count: 0 })
watch(
() => state.count, // 返回值的getter函数
(count, prevCount,onCleanup) => {
/* ... */
}
)
// directly watching a ref
const count = ref(0)
watch(
count, // 也可以直接是ref
(count, prevCount,onCleanup) => {
/* ... */
})
смотреть несколько источников
Наблюдатели также могут использовать массивы для одновременного мониторинга нескольких источников:
const me = reactive({ age: 24, name: 'gk' })
// reactive类型的
watch(
[() => me.age, () => me.name], // 监听reactive多个数据源,可以传入一个数组类型,返回getter函数
([age, name], [oldAge, oldName]) => {
console.log(age) // 新的 age 值
console.log(name) // 新的 name 值
console.log(oldAge) // 旧的 age 值
console.log(oldName) // 新的 name 值
},
// options
{
lazy: true //默认 在 watch 被创建的时候执行回调函数中的代码,如果lazy为true ,怎创建的时候,不执行!
}
)
setInterval(() => {
me.age++
me.name = 'oldMe'
}, 7000000)
// ref类型的
const work = ref('web')
const addres = ref('sz')
watch(
[work,address], // 监听多个ref数据源
([work, addres], [oldwork, oldaddres]) => {
//......
},
{
lazy: true
}
)
watchПривязка к жизненному циклу компонента, при удалении компонента часы также останавливаются автоматически. В других случаях он возвращает дескриптор остановки, который можно вызвать, чтобы явно остановить наблюдатель:
// watch 返回一个函数句柄,我们可以决定该watch的停止和开始!
const stopWatch = watch(
[work,address], // 监听多个ref数据源
([work, addres], [oldwork, oldaddres]) => {
//......
},
{
lazy: true
}
)
// 调用停止函数,清除对work和address的监视
stopWatch()
Очистить недопустимые асинхронные задачи в часах
<div class="search-con">
<svg-icon class="search-icon" icon-class="search"></svg-icon>
<input v-focus placeholder="搜索、关键词" v-model="searchText" />
</div>
setup(props, { attrs, slots, parent, root, emit, refs }){
const CancelToken = root.$http.CancelToken
const source = CancelToken.source()
// 定义响应式数据 searchText
const searchText = ref('')
// 向后台发送异步请求
const getSearchResult = searchText => {
root.$http.post("http://test.happymmall.com/search",{text:searchText}, {
cancelToken: source.token
}).then(res => {
// .....
});
return source.cancel
}
// 定义 watch 监听
watch(
searchText,
(searchText, oldSearchText, onCleanup) => {
// 发送axios请求,并得到取消axios请求的 cancel函数
const cancel = getSearchResult(searchText)
// 若 watch 监听被重复执行了,则会先清除上次未完成的异步请求
onCleanup(cancel)
},
// watch 刚被创建的时候不执行
{ lazy: true }
)
return {
searchText
}
}
Наконец
Vue3 добавляет Composition API. Новый API совместим с Vue2.x, и нам нужно только ввести пакет @vue/composition-api отдельно в проект, чтобы решить отдельные проблемы, которые у нас сейчас есть в Vue2.x. Например: как организовать логику и как извлечь и повторно использовать логику среди нескольких компонентов. Основываясь на текущем API Vue 2.x, у нас есть некоторые общие шаблоны повторного использования логики, но есть более или менее некоторые проблемы:
Эти режимы включают в себя:
- Mixins
- Компоненты высшего порядка (также известные как HOC)
- Компоненты без рендеринга (компоненты, которые инкапсулируют логику на основе слотов с областью действия/слотов с областью действия)
В целом вышеперечисленные модели имеют следующие проблемы:
- Источник данных в шаблоне не ясен. Например, когда в компоненте используется несколько миксинов, может быть сложно определить, из какого миксина происходит свойство, просто взглянув на шаблон. У HOC аналогичная проблема.
- Конфликт пространства имен. Нет никакой гарантии, что примеси, разработанные разными разработчиками, не будут использовать одно и то же имя свойства или метода. У HOC аналогичная проблема с инъекционными пропсами.
- представление. Как HOC, так и Renderless Components требуют дополнительной вложенности экземпляров компонентов для инкапсуляции логики, что приводит к ненужным потерям производительности.
В vue3 новыйComposition API. и новыйAPIсовместимыйVue2.x, просто нужно внести отдельно в проект@vue/composition-apiЭтого пакета достаточно, и он может решить большинство наших текущих проблем, описанных выше. Между тем, если я обновлюсь непосредственно доVue3.x, у меня еще много дел, пока стороннюю библиотеку ui, используемую в текущем проекте, нужно переделывать, а многие ямы после апгрейда нужно засыпать! Когда я только начинал, я строил прямо на нынешних строительных лесах.vue add vue-nextУстанавливайте и обновляйте, но пока есть места, которые полагаются на сторонние экологические библиотеки, есть много ям. . .
Vue3.xОбъект по умолчанию не экспортируетсяexport default, в сторонней экосистеме обычно используетсяVue.xxx()Чтобы сделать зависимости, теперь эти грамматики нужно переписывать, а объем работы не маленький!
Если это новая команда или небольшой проект, вы можете попробовать использовать vue3 для пробной разработки и постепенно переходить, когдаVue3.xПосле официального релиза и окружающей среды вы можете использовать vue3 напрямую!
существуетbilibiliВо время прямого эфира Эван Ю также сказал, что текущая бета-версия vue3, самое главное,Улучшить стабильность, и правильноПоддержка сторонних библиотек инструментов, если вы являетесь автором сторонней библиотеки, вы можете начать прямо сейчас и ознакомиться с исходным кодом. Наши разработчики могут сначала прочитать и понять, как использовать все API.
Извините
⚠️В настоящее время этот проект изменяет только веткуvue-composition-apiвнизsrc/views/home/index.vueиsrc/views/classify/index.vueВпрочем, остальные модификации одинаковы для этих двух файлов.Если вам интересно, можете форкнуть прошлый, написать другие страницы с Composition API3, и попрактиковаться своими руками! Ознакомьтесь с новым API, а я буду постепенно улучшать другие страницы! Всем ⛽️ Давай! Когда официальная версия будет официально выпущена, мы сможем быстро приступить к работе! Надеюсь увидеть вас всех!
Заканчивать
❤️ Прочитав три вещи: Если вы найдете этот контент вдохновляющим, я хотел бы пригласить вас сделать мне небольшую услугу:
- Ставьте лайки, чтобы этот контент увидело больше людей, а также вам было удобно найти этот контент в любой момент (фавориты не лайкаются, они все хулиганят -_-);
- Следите за нами и время от времени распространяйте статьи;
- Также смотрите другие статьи;
🎉Вы можете написать свой собственный опыт обучения в области сообщений, чтобы обсудить его со мной и другими учениками. Если вы чувствуете, что что-то приобрели, вы также можете поделиться статьей со своими друзьями.
Этот проект лучше работает на мобильном терминале, вы можете отсканировать следующий QR-код, чтобы испытать его! 👇
В этой статье используетсяmdniceнабор текста