Версия vue-next (3.0) уже давно является открытым исходным кодом, хотя официальная версия не выпущена, это не влияет на наши попытки использовать ее в собственных проектах. Эта статья является кратким изложением моего проекта «кинотрейлер», только что переписанного на vue3.
Демонстрационный адрес проекта
Введение в проект
Я разместил на Наггетспервая статьяЭто только введение в этот проект. Я не ожидал, что прошло два года. Оглядываясь назад на рост последних двух лет... У меня есть сердце, чтобы убить себя! ! ! 🙃
Общие визуальные/интерактивные эффекты проекта не изменились, а именно:
Интерфейсный проект
создание проекта
-
использовать
vue-cliИнструмент может легко создать проект vue.При выборе стека технологий просто отметьте TypeScript. -
Проект инициализируется через
vue add vue-nextУстановите официальный плагин, чтобы обновить его версию vue до vue3.0. -
Исправлять
shims-vue.d.tsфайл, импорт.vueкомпонент, типdefineComponentтип, возвращаемый функциейdeclare module "*.vue" { import { defineComponent } from "vue"; const Component: ReturnType<typeof defineComponent>; export default Component; }
затрагивает моменты, которые необходимо изменить
-
Удалить
filtersфункция фильтра, официальная причина, чтобы сказатьfiltersФункции можно полностью реализовать с помощью функций и вычисляемых свойств, нет необходимости увеличивать затраты на обучение и|Он конфликтует с побитовыми операторами и увеличивает сложность синтаксического анализа шаблона. В частности, вы можете увидетьrfc -
отредактировано
v-modelAPI и удаленоmodelопции. Прежде чем мы разработали компоненты для двустороннего связывания, мыprops.value,передачаthis.$emit('input')для достижения двусторонней привязки. vue3.0 будет использоватьmodelValueзаменятьvalue,emit('update:modelValue')заменитьinputмероприятие. В частности, вы можете увидетьrfc
<!-- 使用组件 -->
<Comp v-mode="text" />
// modelValue 通过 attrs 获取,emit用于触发事件
export default defineComponent({
setup(props, { attrs, emit }) {
const onChange = (e) => {
emit('update:modelValue', e.target.value)
}
return { onChange }
}
})
-
TransitionкомпонентclassNameизменить, прежде чем эффект перехода будет записан вxxx-enter,xxx-leave-tocss имя класса, сейчасxxx-enterизменить наxxx-enter-from. В частности, вы можете увидетьrfc -
Изменились параметры установки плагина. Перед написанием плагина вы можете напрямую использовать входные параметры метода установки
Vue, который монтирует метод или свойство вVue.prototypeначальство. Теперь входным параметром метода установки является приложение.
// 之前插件挂载属性的方式
export default {
install: (Vue, option) => {
Vue.prototype.$axios = xxx;
}
}
// vue3.0的方式
export default {
install: (app, option) => {
app.config.globalProperties.$axios = xxxx
}
}
// 另一种方式 也可以使用 provide 、inject , 在composition API中使用
export const symbolKey = Symbol('_axios_');
// setup 函数里使用composition API
export function useAxios() {
return inject(symbolKey)
}
// 执行插件insall方法注入
export default {
install: (app, option) => {
app.provide(symbolKey, xxx)
}
}
фактическиvue3.0В версии много изменений, но так как проект не очень сложный, он не очень полный, вы можете прочитать егоrfcsОзнакомьтесь с некоторыми обсуждениями изменений.
Применение API композиции
Все компоненты этого проекта используютсяComposition APIразработан, на основеComposition APIМы можем лучше инкапсулировать общую логику.
Инкапсуляция функции запроса
Перед этим необходимо дополнительно определить и поддерживать загрузку асинхронного запроса проекта.Composition APIМы можем инкапсулировать React, похожий на swrФункция ловушки библиотеки выборки.
// 类似于这样
export function useRequest(url, params, config) {
// 统一维护的变量,最后return出去
const state = reactive({
loading: false,
error: false,
data: config.initialData
})
const fetchFunc = () => {
state.loading = true;
// 做请求的公用逻辑
axios().then(response => {
const result = response.data;
state.data = result.data;
state.loading = false;
}).catch(err => {
state.error = true;
})
}
onMounted(() => {
if (config.immediate) {
fetchFunc();
}
});
// toRefs 可以将state,拆解成多个ref,这样调用者就可以使用解构来拿到变量
return { ...toRefs(state), fetch: fetchFunc };
}
инкапсуляция событий
НапримерtouchСобытия, нам нужно не только связать события и развязать время, но также нужно разделить переменную побочного эффекта в разных обратных вызовах, мы можем разделить ее наcomposableфункция
// 类似于这样
export function useTouch(domRef, ref) {
// 是否touch进行中标志位
let initiated = false;
// 监听domRef改变
watch(domRef, (el, prev, onCleanup) => {
const touchStart = (e: TouchEvent) => {
e.preventDefault();
initiated = true;
callbacks.touchStart(e);
};
const touchMove = (e: TouchEvent) => {
e.preventDefault();
if (!initiated) return;
callbacks.touchMove(e);
};
const touchEnd = (e: TouchEvent) => {
initiated = false;
callbacks.touchEnd(e);
};
el.addEventListener("touchstart", touchStart);
el.addEventListener("touchmove", touchMove);
el.addEventListener("touchend", touchEnd);
// 取消绑定
onCleanup(() => {
el.removeEventListener("touchstart", touchStart);
el.removeEventListener("touchmove", touchMove);
el.removeEventListener("touchend", touchEnd);
});
})
}
оптимизация
Добавлен travis для отправки автоматических выпусков сборки и отправки статических ресурсов на удаленные серверы через sshpass.
language: node_js
node_js:
- 12
branchs:
- master
addons:
apt:
packages:
- sshpass
install:
"npm install"
script:
- "npm run build"
after_success:
- ./script/deploy.sh
вserverPassа такжеserverIPВсе переменные среды настроены на travis.
#!/usr/bin/env sh
# 确保脚本抛出遇到的错误
set -e
# 打包静态资源
npm run build
# 将dist文件发送到远程
sshpass -p ${serverPass} scp -o stricthostkeychecking=no -r dist/ root@${serverIP}:/home/web/movie-trailer
серверный проект
бэкэнд от использованияkoaОбновление фреймворка доEggкадр, используяKoaПри разработке приложений разработчикам необходимо загружать или разрабатывать различное промежуточное программное обеспечение для достижения функциональных улучшений, в то время какEggвыбранныйKoaКак его базовая структура, он помогает разработчикам вносить в него некоторые улучшения.
EggПомимо предоставленияController,ServiceПомимо выполнения бизнес-процессов на уровне, он также обеспечиваетextendИспользуется для расширения собственной функции (несколько расширений). Например, мы можем расширитьContext, монтирует универсальную функцию, которая возвращает результат в своем контексте.
// app/extends/context.js
module.exports = {
sendSuccess: function(result) {
this.body = {
code: 200,
errMsg: '',
data: result
}
},
sendError: function(errorMsg) {
this.body = {
code: 300,
errMsg: errorMsg,
}
}
};
// app/controller/keyword.js
class KeyWordController extends Controller {
async index() {
const { ctx, service } = this;
const keywordList = await service.keyword.index();
// 返回200成功
ctx.sendSuccess(keywordList)
}
}
До этого я сканировал фильмы Доубана через Python, а потом вручную писал скрипты через crontab,EggФреймворк помогает разработчикам устанавливать временные задачи, используяEgg, нам нужно толькоapp/scheduleСоздайте файл в каталоге для экспорта на основеSubscriptionтип.
class CrawlingDouban extends Subscription {
// 静态方法,定义执行时机
static get schedule() {
return {
cron: '0 8 * * *', // 每天8点
type: 'worker',
};
}
async subscribe() {
// 爬取逻辑
}
}
Суммировать
В процессе рефакторинга по-прежнему будут возникать некоторые проблемы, большинство из которых вызвано непрочитанными документами, поэтому по-прежнему очень важно просматривать документы. Я надеюсь, что эта статья будет полезна для всех, и я чувствую, что с проектом все в порядке, так что не скупитесь на старт! .