Как создать веб-сайт портфолио React на базе Cosmic JS
В этом уроке я собираюсь продемонстрировать, как создать веб-сайт портфолио фотографий, используя React, Styled-Components и Космический JS. Давайте начнем.
TL;DR
Посмотреть и установить демо
Посмотреть код на GitHub
вступление
Космический JS обеспечивает хороший бэкэнд для ваших веб-приложений. Это полнофункциональная система управления контентом (CMS) с многочисленными опциями, которая позволяет всем членам вашей команды совместно управлять контентом. Cosmic JS предоставляет множество возможностей для разработчиков: администраторы Bucket могут назначать разные роли членам своей команды, создавать одиночные или множественные отношения между объектами и многое другое.
В этом примере я использую:
- метаполе отношения нескольких объектов
- изображения / файлы
- ввод объектов по умолчанию
РеактJS: простая и гибкая JS-библиотека для создания клиентского приложения. React CLI позволяет создавать одностраничные приложения без настройки.
Стилизованные компоненты: альтернатива Static CSS, позволяет создавать отдельные компоненты для улучшения вашего приложения и расширения его возможностей.
Начиная
1. На панели управления Cosmic JS нажмите » Добавить новое ведро«.
1.1** Установить приложение **- Кнопка «Установить приложение», назначить имя приложения и «Сохранить корзину». После этого выберите приложение из списка приложений и нажмите «Установить бесплатно». И вы создали все необходимые для приложения объекты. Последнее, что нужно сделать: Скопируйте ключ API с рабочего стола Cosmic JS> Основные настройки> Слаг ковша.
1.2 С нуля — кнопку начать с нуля, назначить имя приложения и «Сохранить ведро». Для этого приложения вам нужно создать три типа объектов. Изображения, категории и сайты.
Картинки : Входные данные по умолчанию плюс дополнительные метаполя, называемые: «img» в качестве типа объекта изображения/файла, проверены по мере необходимости.
Категории : ввод по умолчанию плюс дополнительные метаполя, называемые: «изображения» как отношения нескольких объектов (выберите ограничение «Поиск по изображениям») и объект изображения/файла, называемый: «img».
Места : Тип ввода по умолчанию плюс дополнительные метаполя под названием «изображение».
Я создал Bucket для своего приложения и теперь готов погрузиться в код. Ссылка для вашего Ведро Слизняк.
Код
Клонируйте репозиторий с Github или создайте его с нуля. Этот пакет показывает все зависимости, используемые для приложения:
{
"name": "portfolio",
"version": "0.1.0",
"private": true,
"dependencies": {
"cosmicjs": "^3.2.14",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"react-pose": "^4.0.4",
"react-pose-text": "^3.1.0",
"react-router-dom": "^4.3.1",
"react-scripts": "2.1.1",
"styled-components": "^4.1.3",
"styled-loaders": "^0.3.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
После того, как вы установили React и все зависимости, вы готовы писать код.
Все данные скачиваются отдельно, параметр отправляется в react-router. После перехода к одному сообщению один элемент извлекается и отображается в компоненте.
Краткое пояснение о файловой структуре.
- Наша первая задача — создать файловую структуру для проекта.
App.js по умолчанию, компонент папки:
кнопки (все созданные кнопки),
заголовки (все заголовки),
страница (все страницы),
части (все компоненты без состояния только в стиле const),
раздел (класс и функциональные компоненты, которые управляют данными и импортируют другие компоненты из файла частей),
л нет (поставщик темы глобального стиля макета приложения).
утилиты (цвет и тема объекта).
App.js
│ index.js
│ serviceWorker.js
│
├───components
│ ├───buttons
│ │ Button.js
│ │
│ ├───headers
│ │ H1.js
│ │ H2.js
│ │
│ ├───page
│ │ Contact.js
│ │
│ ├───parts
│ │ Anchor.js
│ │ Caption.js
│ │ Card.js
│ │ CategoryCard.js
│ │ Center.js
│ │ Contain.js
│ │ Figure.js
│ │ Paragraph.js
│ │ PositionContainer.js
│ │
│ └───section
│ Category.js
│ Footer.js
│ Nav.js
│ PartGrid.js
│ Single.js
│ Wrap.js
│
├───layout
│ Layout.js
│
└───utils
colors.js
theme.js
Что внутри
Файл App.js, в котором находится маршрутизация и импорт макета, состояние интерактивных элементов. Здесь мы передаем данные, которые мы можем получить в другом компоненте в качестве реквизита.
import React, { Component } from 'react';
import {BrowserRouter, Switch, Route} from 'react-router-dom';
//CSS COMPONENT IMPORTS
import './font-awesome-4.7.0/css/font-awesome.min.css';
import Layout from './layout/Layout';
import Wrap from './components/section/Wrap';
import Category from './components/section/Category';
import PartGrid from './components/section/PartGrid';
import Contact from './components/page/Contact';
import Single from './components/section/Single';
import Footer from './components/section/Footer';
import Center from './components/parts/Center';
class App extends Component {
state = {
category:null,
hg:false
}
componentDidMount = async () => {
const Cosmic = require('cosmicjs');
const api = Cosmic();
const bucket = api.bucket({
slug: 'ec055990-f24c-11e8-9231-9b47e8f95b7e'
})
const data = await bucket.getObjects({
type: 'categories'
})
this.setState({
category: data.objects,
})
document.addEventListener('scroll', () => {
if(window.pageYOffset > 50 ) {
this.setState({
hg: true
})
}
else{
this.setState({
hg: false
})
}
});
}
handleMenu = () => {
this.setState((prevProps) => ({visable: !prevProps.visable }));
}
render() {
console.log(this.state.category);
return (
<div className="App">
<Layout>
<BrowserRouter>
<>
<Wrap hg={this.state.hg} />
<Switch>
<Route path="/" exact render={(props) => <Category category={this.state.category}/>}/>
<Route path="/contact" exact component={Contact} />
<Route path="/img/:slug" component={Single} exact />
<Route path="/:slug" component={PartGrid} exact />
</Switch>
</>
</BrowserRouter>
<Center fs> " A portfolio is a set of pictures by someone, or photographs of examples of their work, which they use when entering competitions or applying for work. "</Center>
<Footer/>
</Layout>
</div>
);
}
}
export default App;
Раздел
Категория.js отображается как домашняя страница. Это отображает данные, загруженные в качестве реквизита из компонента app.js. Он также импортирует стилизованные компоненты из папки «parts».
import React from 'react'
import CategoryCard from './../parts/CategoryCard';
import CaptionWrap from '../parts/Caption';
import Button from './../buttons/Button';
import H1 from '../headers/H1';
import ContainerCategory from './../parts/Contain';
import Position from './../parts/PositionContainer';
import { Link } from 'react-router-dom'
import Par from './../parts/Paragraph';
export default function Category(props) {
console.log("Props category", props);
return (
<ContainerCategory>
{props.category && props.category.map((item, index) => {
return(
<CategoryCard key={index} index={index + 1}>
<img src={item.metadata.img.url} alt="img" index={index + 1} />
<CaptionWrap index={index + 1}>
<Position index={index + 1}>
<H1 isBig>{item.title}</H1>
<Par dangerouslySetInnerHTML={{__html:item.content}}></Par>
<Link to={'/' + item.slug}><Button >See more</Button> </Link>
</Position>
</CaptionWrap>
</CategoryCard>
)
})}
</ContainerCategory>
)
}
PartGrid.js — компонент состояния собирает данные из Cosmic JS. Страница с фотографиями в выбранной категории содержит ссылку на одну фотографию.
import React, { Component } from 'react'
import styled from 'styled-components'
import Card from '../parts/Card';
import Img from '../parts/Figure';
import Anchor from './../parts/Anchor';
import { Link } from 'react-router-dom';
const GridContainer = styled.div`
min-height:100%;
display:grid;
margin:150px auto;
justify-items:center;
grid-template-column:1fr;
grid-template-rows:400px;
grid-gap:10px;
${({theme}) => theme.media.mobile} {
grid-template-columns:320px 320px;
width:640px;
}
${({theme}) => theme.media.tablet} {
grid-template-columns:320px 320px 320px;
width:960px;
}
${({theme}) => theme.media.desktop} {
grid-template-columns:320px 320px 320px 320px;
width:1280px;
margin:200px auto 450px auto;
}
`;
export default class PartGrid extends Component {
state ={
picture: []
}
componentDidMount = async() => {
const slug = this.props.match.params.slug;
const Cosmic = require('cosmicjs')
const api = Cosmic()
const bucket = api.bucket({
slug: 'imageapp'
})
const data = await bucket.getObject({
slug: `${slug}`
})
this.setState({
picture:data.object
})
}
render() {
return (
<GridContainer column={true}>
{ this.state.picture.metadata && this.state.picture.metadata.images.map((item, index) => {
return(
<Card key={index}>
<Img src={item.metadata.img.url} alt="grid-img"/>
<Anchor as={Link} to={'/img/' + item.slug}>
<i className="fa fa-link" aria-hidden="true"></i>
</Anchor>
</Card>
)
})}
</GridContainer>
)
}
}
Сингл.js — Это также компонент, содержащий состояние. Получает данные для одной фотографии от Cosmic JS.
import React, { Component } from 'react'
import CategoryCard from './../parts/CategoryCard';
import CaptionWrap from '../parts/Caption';
import Button from './../buttons/Button';
import H1 from '../headers/H1';
import ContainerCategory from './../parts/Contain';
import Position from './../parts/PositionContainer';
import { Link } from 'react-router-dom';
import Par from './../parts/Paragraph';
export default class Single extends Component {
state ={
img: null
}
componentDidMount = async() => {
const link = this.props.match.params.slug;
const Cosmic = require('cosmicjs')
const api = Cosmic()
const bucket = api.bucket({
slug: 'imageapp'
})
const data = await bucket.getObject({
slug: `${link}`
})
this.setState({
img:data.object
})
}
render() {
return (
<ContainerCategory>
<CategoryCard index={0}>
{this.state.img && <img src={this.state.img.metadata.img.url} alt="img" index={0} /> }
<CaptionWrap index={0}>
<Position index={0}>
{this.state.img && <H1 isBig>{this.state.img.title}</H1>}
{this.state.img && <Par dangerouslySetInnerHTML={{__html:this.state.img.content}}></Par>}
</Position>
</CaptionWrap>
</CategoryCard>
<br/> <br/>
<Link to={'/'}><Button >Go back</Button></Link>
</ContainerCategory>
)
}
}
Макет.js — содержит провайдер темы и глобальный стиль. Поскольку мы использовали провайдер темы, мы можем подключить CSS к React и использовать переменные CSS в зависимости от реквизитов компонента.
import React from 'react'
import {createGlobalStyle, ThemeProvider} from 'styled-components';
import { theme } from './../utils/theme';
const GlobalStyle = createGlobalStyle`
body {
padding: 0;
box-sizing:border-box;
margin 0;
background:${({theme}) => theme.colors.light}
font-family: Montserrat,'Segoe UI', sans-serif ;
color:${({theme}) => theme.colors.dark}
}
`;
export default function Layout({children}) {
return (
<ThemeProvider theme={theme}>
<>
<GlobalStyle />
{children}
</>
</ThemeProvider>
)
}
Nav.js — отдельный компонент состояния с собственными стилизованными компонентами и состоянием.
Части
В этой папке находятся только отдельные теги HTML, стилизованные в CSS (styled-components) и экспортируемые как отдельные компоненты.
Кнопки и заголовки
Стилизация отдельных HTML-тегов в styled-components): h1, кнопка и т. д.
Страница
Contact.js — компонент состояния, который извлекает данные из Cosmic JS и отображает их в приложении.
Утилиты
Все глобальные переменные, которые мы можем использовать в нашем приложении, такие как цвета, медиа-запрос, размер шрифта и т. д. Переменные из файлов, которые мы можем передавать в качестве реквизита другим компонентам и использовать в стилизованных компонентах.
export const colors = {
dark: '#1B1B1E',
darkOne: '#373F51',
middle: '#373F51',
// light: '#D8DBE2',
lightOne: '#A9BCD0',
light: 'white'
}
import {colors} from './colors';
export const theme = {
colors,
fontWg: {
thin:300,
reg:400,
fat:800
},
media: {
desktop: '@media(min-width: 1324px)',
tablet: '@media(min-width: 1024px)',
mobile: '@media(min-width: 665px)',
}
}
Вывод
Мы только что создали простое приложение, используя стилизованные компоненты, React JS и Cosmic JS. В начале мы увидели, как создать Bucket для нашего приложения. Затем мы создали шаблон с помощью React CLI и установили зависимости. После создания структуры папок и компонентов стилей в CSS мы загрузили данные из Cosmic JS для отображения в приложении.
Cosmic JS имеет отличный API для каждого приложения в сочетании с множеством опций для разработчиков и редакторов контента, которые позволяют беспрепятственно управлять контентом. Стилизованные компоненты позволяют создавать независимые компоненты, поэтому приложение может быть создано многими людьми, не вызывая конфликтов, таких как (имя класса в css) и т. д. В одной команде React CLI позволяет нам создать шаблон для нашего приложения.
Я рекомендую вам установить приложение, добавить свои компоненты и расширить функциональность. Веселиться!
Если у вас есть какие-либо комментарии или вопросы о создании приложений с помощью Cosmic JS, свяжитесь с нами в Twitter а также присоединиться к беседе в Slack.