В этом уроке мы собираемся переписать компонент временной шкалы, встроенный в ReactJs, по Флорин Поп Вэджам. Вы можете увидеть компонент в действии Здесь Анкет
Скаффолд приложение vuejs с помощью Vite
Я стараюсь использовать VITE всякий раз, когда дает возможность.
Это увеличивает скорость разработки на невероятное количество из -за таких функций, как мгновенный запуск сервера и молния HMR (замена горячего модуля).
- Давайте инициируем наш проект:
npm init vite@latest
- Следуйте по приглашению и выберите
Vueкак наши структуры и как наш вариант. CDв сгенерированный каталог и установите зависимости сNPM УстановкаАнкет- Запустите свой новый проект Vite + Vuejs, используя
npm запустить devАнкет
Создание компонента Vuejs
Теперь забавные вещи. Давайте поработаем над преобразованием кода ReactJS.
App.vue выглядит очень похоже на версию ReactJS:
// App.vue
// React Version
const App = () => (
<>
React Timeline
)
Ключевое отличие здесь – тег шаблона , важная часть синтаксиса Vuejs.
Давайте теперь копаться в компоненте временной шкалы – Timeline.vue
Компонент временной шкалы – это то, где происходит сбор данных и контейнер.
В этом примере мы собираем данные из нашего локального data.json файл. Не должно потребоваться слишком много дополнительных работ, чтобы этот компонент работал с живыми данными, используя такой пакет, как Аксиос .
В то время как версия ReactJS занимает меньше вертикального пространства, версию Vuejs намного проще читать. Вместо того, чтобы применять встроенную функцию карты, мы используем V-for Для применения той же функциональности.
Vuejs прикрепляет динамические данные о свойстве под названием v-bind Анкет Шортхолд для V-Bind-это : . Как видите : data = data это эквивалент Vuejs data = {data} Анкет
Также обратите внимание, Vuejs не использует ClassName Чтобы применить свой CSS. Вместо этого вы можете использовать классический класс ключевое слово.
// React Version
const Timeline = () =>
timelineData.length > 0 && (
{timelineData.map((data, idx) => (
))}
)
// components/Timeline.vue
Вот пример того, как выглядят данные:
[
{
"text": "Started working on the app-ideas repository",
"date": "February 25 2021",
"category": {
"tag": "app-ideas",
"color": "#FFDB14"
},
"link": {
"url": "https://github.com/florinpop17/app-ideas",
"text": "Check it out on GitHub"
}
},
...
]
Преобразование компонента TimeLineItem в Vuejs
Компонент TimeLineitem – это место, где происходит большая часть логики пользовательского интерфейса. Сейчас мы играем с данными, которые мы собрали в компоненте сроков.
Не так много происходит вне разрушения объекта данных и стиля по мере необходимости.
Мы разрушаем данные в Vuejs иначе, чем в ReactJS.
- При использовании данных между двумя элементами HTML вы должны уничтожить их, используя две кудрявые кронштейны
{{}} - При доступе к данным в
V-Bind:, вы разрушаете его, используя отдельные вьющиеся кронштейны{данные} - При доступе к данным в директиве, такой как
V-if, вы вводите данныеv-if = "data"
const TimelineItem = ({ data }) => (
)
// components/TimelineItem.vue{{ data.category.tag }}{{ data.text }}
{{ data.link.text }}
Дополнительная конфигурация Vuejs
Чтобы получить CSS, приведенный ниже, чтобы уколоть наш компонент, нам необходимо разоблачить CSS для работы в нашем приложении Vuejs. Для этого примера я разместил импорт в моем main.js файл.
import { createApp } from 'vue'
import App from './App.vue'
import './assets/main.css'
createApp(App).mount('#app')
Стилизация компонента с использованием CSS
Для этого компонента я использую main.css Файл размещен в нашем активы каталог. Вот CSS, используемые в этом компоненте:
/* assets/main.css */
@import url('https://fonts.googleapis.com/css?family=Lato');
* {
box-sizing: border-box;
}
body {
background-image: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
min-height: 100vh;
font-family: 'Lato', sans-serif;
margin: 0;
}
h1 {
text-align: center;
}
#app {
padding: 0 20px;
width: 100%;
}
.timeline-container {
display: flex;
flex-direction: column;
position: relative;
margin: 40px 0;
}
.timeline-container::after {
background-color: #e17b77;
content: '';
position: absolute;
left: calc(50% - 2px);
width: 4px;
height: 100%;
}
.timeline-item {
display: flex;
justify-content: flex-end;
padding-right: 30px;
position: relative;
margin: 10px 0;
width: 50%;
}
.timeline-item:nth-child(odd) {
align-self: flex-end;
justify-content: flex-start;
padding-left: 30px;
padding-right: 0;
}
.timeline-item-content {
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
border-radius: 5px;
background-color: #fff;
display: flex;
flex-direction: column;
align-items: flex-end;
padding: 15px;
position: relative;
width: 400px;
max-width: 70%;
text-align: right;
}
.timeline-item-content::after {
content: ' ';
background-color: #fff;
box-shadow: 1px -1px 1px rgba(0, 0, 0, 0.2);
position: absolute;
right: -7.5px;
top: calc(50% - 7.5px);
transform: rotate(45deg);
width: 15px;
height: 15px;
}
.timeline-item:nth-child(odd) .timeline-item-content {
text-align: left;
align-items: flex-start;
}
.timeline-item:nth-child(odd) .timeline-item-content::after {
right: auto;
left: -7.5px;
box-shadow: -1px 1px 1px rgba(0, 0, 0, 0.2);
}
.timeline-item-content .tag {
color: #fff;
font-size: 12px;
font-weight: bold;
top: 5px;
left: 5px;
letter-spacing: 1px;
padding: 5px;
position: absolute;
text-transform: uppercase;
}
.timeline-item:nth-child(odd) .timeline-item-content .tag {
left: auto;
right: 5px;
}
.timeline-item-content time {
color: #777;
font-size: 12px;
font-weight: bold;
}
.timeline-item-content p {
font-size: 16px;
line-height: 24px;
margin: 15px 0;
max-width: 250px;
}
.timeline-item-content a {
color: #333;
text-decoration: none;
font-size: 14px;
font-weight: bold;
}
.timeline-item-content a::after {
content: ' ►';
font-size: 12px;
}
.timeline-item-content .circle {
background-color: #fff;
border: 3px solid #e17b77;
border-radius: 50%;
position: absolute;
top: calc(50% - 10px);
right: -40px;
width: 20px;
height: 20px;
z-index: 100;
}
.timeline-item:nth-child(odd) .timeline-item-content .circle {
right: auto;
left: -40px;
}
@media only screen and (max-width: 1023px) {
.timeline-item-content {
max-width: 100%;
}
}
@media only screen and (max-width: 767px) {
.timeline-item-content,
.timeline-item:nth-child(odd) .timeline-item-content {
padding: 15px 10px;
text-align: center;
align-items: center;
}
.timeline-item-content .tag {
width: calc(100% - 10px);
text-align: center;
}
.timeline-item-content time {
margin-top: 20px;
}
.timeline-item-content a {
text-decoration: underline;
}
.timeline-item-content a::after {
display: none;
}
}
footer {
background-color: #222;
color: #fff;
font-size: 14px;
bottom: 0;
position: fixed;
left: 0;
right: 0;
text-align: center;
z-index: 999;
}
footer p {
margin: 10px 0;
}
footer i {
color: red;
}
footer a {
color: #3c97bf;
text-decoration: none;
}
Дополнительные ресурсы
- Репозиторий GitHub с исходным кодом – https://github.com/CodyBontecou/timeline-component-vuejs
- Флорин Поп сделал YouTube видео Прогулка по строительству этого компонента с помощью ReactJS.
- Reactjs Codepen
Оригинал: “https://dev.to/codybontecou/convert-a-reactjs-component-to-vuejs-2lek”