Translate

Поиск по этому блогу

понедельник, 3 июня 2019 г.

React-Сайт ( III ). Цены-локация секции.

В этой части сделаем две очень важные секции - секция вывода цены и локации.




Все статьи этого проекта:




Задачу разделим на два этапа. На первом этапе создадим секцию цен. Это довольно простая задача, но есть одно но.



Если посмотреть на картинку, то все выглядит довольно просто. У нас есть три блока, которые находятся внутри секции. Каждый блок имеет свои значения цены, описания, позиции и главное, то чего вы не видите на статической картинке - нам нужно выводить блоки с последовательным проявлением. Вначале должен показаться блок. который по центру и после задержки в пол сек. уже первый и третий блоки.

Кнопки, мы уже создали отдельный компонент MyButton в который мы передадим нужные свойства. Это можно во внимание уже не брать.

Задачу можно решить разными путями. Я решил все это создать в одном компоненте. Данные можно передать в этот компонент извне, но так как мы можем их сохранять в самом компоненте. то это еще одно упрощение задачи. Данные можно сохранить в виде отдельных массивов (массив - цен, описаний, и пр.), тогда мы сможем их выводить в нужном порядке используя индекс в одном переборе (map()) и по индексу выводить значения из других массивов. Например так:

 const arr_1 = ['Price-1', 'Price-2', 'Price-3'];
 const arr_2 = ['Description-1', 'Description-2', 'Description-3'];
 const arr_3 = ['Something-1','Something-2','Something-3'];

 function iter(arr_1, arr_2, arr_3){
   arr_1.map((item, index)=>(console.log("Price = "+ arr_1[index] + "; Description = " + arr_2[index] + "; Something = " + arr_3[index] + "Index = " + "; Index = " + index)))
 }
 iter(arr_1, arr_2, arr_3);

// Price = Price-1; Description = Description-1; Something = Something-1Index = ; Index = 0
// Price = Price-2; Description = Description-2; Something = Something-2Index = ; Index = 1
// Price = Price-3; Description = Description-3; Something = Something-3Index = ; Index = 2




В данном случае способ вывода в консоль значения не имеет. Главное что омы получаем таким образом доступ к нужным данным, которые все равно, мы будем выводить в jsx.

Второй вариант - это (обычный) сделать один массив данным с отдельными объектами - в виде каждого блока. У каждого объекта будут ключи - поля (name, price, description, position, link, delay). Вы можете выбрать любой вариант,который вам больше нравится. Главное. что в любом случае у нас будет возможность задать нужную задержку выполнения появления блока - delay и применить ее к нужному блоку.

Способ хранения данных (внутри отдельного компонента или во внешнем файле) для нас сейчас значения не имеет, но стоит обратить внимание на то как вы храните эти значения. Я встречал сохранение статических данных в state компонента. Считаю это излишним, потому что в стейтах есть смысл хранить изменяемые значения, а не статические, как в данном случае. Это облегчит создание самих компонентов, ускорит их работу и избавит от проблем отладки в будущем. Хватит слов. К коду.

Создадим отдельную папку и индексовый файл для нашего компонента в папке компонентов. Как мы и договорились, это будет компонент без состояния. Сразу же подключим и выведем его в файле App.js

import Pricing from './Compomemts/Pricing';

<Pricing />

Для Components/Pricing/index.js
import React from "react";

const Pricing = () => {
  return (
     <div className="bck_black">
       <div className="center_wrapper pricing_section">
         <h2>Pricing</h2>

         <div className="pricing_wrapper">Some text</div>
       </div>
     </div>

);
};

export default Pricing;



Убедились, что все работает. Слева внизу появится в браузере слово - Pricing.

Теперь внутри нашего компонента создадим общую разметку для вывода трех блоков - выше в коде красным. Добавляем слили

recourses/style.css
/* ====================>>> PRICING <<<=================================== */


.pricing_section {
    padding: 70px 0px;
}


.pricing_section h2 {
    color: #ffffff;
    text-transform: uppercase;
    text-align: center;
    font-size: 50px;
    margin: 0;
}

.pricing_wrapper {
    display: flex;
    flex-wrap: wrap;
}
.pricing_wrapper .pricing_item{
    flex-grow: 1;
    width: 33%;
    padding: 20px;
    box-sizing: border-box;
}

.pricing_wrapper .pricing_inner_wrapper {
    border:2px solid #ffa800;
    padding: 50px 20px;
}

.pricing_inner_wrapper .pricing_title {
    color: #ffffff;
    text-align: center;
    border-bottom: 1px solid #ffa800;
    padding-bottom: 20px;
}
.pricing_inner_wrapper .pricing_title span:nth-child(1) {
    font-size: 50px;
    display: block;
}
.pricing_inner_wrapper .pricing_title span:nth-child(2) {
    text-transform: uppercase;
    font-size: 28px;
    font-weight: 300;
}
.pricing_inner_wrapper .pricing_description {
    color: #b8b8b8;
    font-weight: 300;
    font-size: 14px;
    text-align: center;
    padding: 20px 0px;
    min-height: 70px;
}

.pricing_inner_wrapper .pricing_buttons {
     text-align: center;
}



После этого в браузере мы увидим наше слово выеденное один раз.



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

Components/Pricing/index.js
  const data = [
    {
      prices: 100,
      positions: "Balcony",
      desc:
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt uts",
      linkto: "https://twitter.com/JroslavK",
      delay: 500
    },
    {
      prices: 150,
      positions: "Medium",
      desc:
        "Dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea",
      linkto:
        "https://www.facebook.com/Yaroslav-Web-Master-1446556072148794/?modal=admin_todo_tour",
      delay: 0
    },
    {
      prices: 250,
      positions: "Star",
      desc:
        "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
      linkto:
        "https://www.facebook.com/groups/1786288918273718/?ref=bookmarks",
      delay: 500
    }
  ];


Импортируем в этот файл кнопку MyButton, которую мы создали в прошлом посте.

import MyButton from '../Utils/myButton';

Сразу же импортируем и Zoom эффект из react-reveal

import Zoom from "react-reveal/Zoom";

В этот компонент - Zoom мы будем оборачивать наши компоненты в цикле и передавать им задержку показа на странице - datadelay каждого компонента отдельно.

Там где у нас сейчас выводится слово Some thing, мы будем выводить функцию, которая будет перебирать наши данные (методом map) и вернет разметку в которую поместит соответствующие данные каждого блока.

Функцию привожу ниже. В ней нет ничего необычного. Все как всегда. перебираем данные и выводим в нужных местах разметки.

Components/Pricing/index.js
const showBoxes = () =≶
  data.map((item, i) =≶ (
    <Zoom delay={item.delay} key={i}≶
      <div className="pricing_item"≶
        <div className="pricing_inner_wrapper"≶
          <div className="pricing_title"≶
            <span≶${item.prices}</span≶
            <span≶{item.positions}</span≶
          </div≶
          <div className="pricing_description"≶{item.desc}</div≶
          <div className="pricing_buttons"≶
            <MyButton
              text="Purchase"
              bck="#ffa800"
              color="#ffffff"
              link={item.linkto}
            /≶
          </div≶
        </div≶
      </div≶
    </Zoom≶
  ));



Для того, чтобы все нормально отобразилось на странице, мы вместо вывода слова Some thing сделаем вызов нашей функции.

<div className="pricing_wrapper">{showBoxes()}</div>

Теперь как только компонент загрузится, вызовется функция, которая вернет нам готовую разметку для каждого из трех блоков, уже с соответствующими данными.

Components/Pricing/index.js полностью

import React from "react";
import Zoom from "react-reveal/Zoom";
import MyButton from "../Utils/myButton";

const Pricing = () => {
  const data = [
    {
      prices: 100,
      positions: "Balcony",
      desc:
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt uts",
      linkto: "https://twitter.com/JroslavK",
      delay: 500
    },
    {
      prices: 150,
      positions: "Medium",
      desc:
        "Dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea",
      linkto:
        "https://www.facebook.com/Yaroslav-Web-Master-1446556072148794/?modal=admin_todo_tour",
      delay: 0
    },
    {
      prices: 250,
      positions: "Star",
      desc:
        "Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
      linkto: "https://www.facebook.com/groups/1786288918273718/?ref=bookmarks",
      delay: 500
    }
  ];

  const showBoxes = () =>
    data.map((item, i) => (
      <Zoom delay={item.delay} key={i}>
        <div className="pricing_item">
          <div className="pricing_inner_wrapper">
            <div className="pricing_title">
              <span>${item.prices}</span>
              <span>{item.positions}</span>
            </div>
            <div className="pricing_description">{item.desc}</div>
            <div className="pricing_buttons">
              <MyButton
                text="Purchase"
                bck="#ffa800"
                color="#ffffff"
                link={item.linkto}
              />
            </div>
          </div>
        </div>
      </Zoom>
    ));
  return (
    <div className="bck_black">
      <div className="center_wrapper pricing_section">
        <h2>Pricing</h2>

        <div className="pricing_wrapper">{showBoxes()}</div>
      </div>
    </div>
  );
};

export default Pricing;



Если посмотреть в браузере, то можно увидеть, что получилось именно то, что и хотели.



Блоки выводятся в нужной последовательности.

Да.Прошу прощения. Я по невнимательности опустил опечатку в файле Itils/MyButton.js, там в свойствах кнопки, должно быть конечно size="small". После того, как все исправил, я убедился что ошибок в консоли нет.

Все файлы проекта на этом этапе смотрите в репо - react-site-slider-abc
ci -m "Pricing section"


Локация

Цель - вывести секцию, которая займет 100% ширины и на которой будет показана гугл-карта с местонахождением события.

Здесь все проще, чем вы могли бы подумать. В папке компонентов для этого создадим отдельную папку Location с индексовым файлом - index.js и с обычным кодом для компонента без состояния:

src/Components/Location/index.js
import React from "react";

const Location = () => {
  return (
         <div >
          //   Здесь будет вся разметка
         </div>
      )
};

export default Location;


Добавим классы, для разметки.

Основной див у нас поучит className="location_wrapper", а внутри него создадим отдельный див, для вывода наименования секции - className="location_tag"

Сразу добавим стили:

resources/style.css

.location_wrapper {
    position:relative;
}

.location_tag {
    position: absolute;
    bottom: 0px;
    width: 100%;
}
.location_tag div{
    background: #2c2c2c;
    color: #ffffff;
    text-transform: uppercase;
    width: 220px;
    margin: 0 auto;
    font-size: 29px;
    padding: 15px 20px;
    text-align: center;
}


Далее идем в Гугл карты и находим нужный нам регион и объект. Наша задача получить код для фрейма, который мы и выведем в компоненте реакт.

Вводим адрес. В моем случае это будет Amsterdam, Gedempt Hamerkanaal 231, De Kromhouthal. Нажимаем поделится - Share



В другом окне выбираем "встроенная карта" - Embeded Map



Убеждаемся, что у нас то, что надо показано на малом фрейме и берем нужный код - любым способом его копируем.



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

Теперь немного его доработаем. например изменим allowfullscreen на allowFullScreen добавим ширину 100% и высоту 500px. Да и важно. Теперь нам нужно отдельно добавитьtitle, название выберете самостоятельно любое. Я написал просто location. Свойство frameborder="0" удалим совсем.

src/Components/Location/index.js полностью
import React from "react";

const Location = () => {
  return (
    <div className="location_wrapper">
      <iframe
        src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2435.290628985655!2d4.918337915802386!3d52.383281579788566!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x47c609abb3be496b%3A0x1a140c53c426f7c7!2sthe+Kromhouthal!5e0!3m2!1sen!2sua!4v1559491565118!5m2!1sen!2sua"
        width="100%"
        height="500px"
        allowFullScreen
        title="location"
      />
      <div className="location_tag">
        <div>Location</div>
      </div>
    </div>
  );
};

export default Location;



Идем в основной файл - App.js подключаем

import Location from './Compomemts/Location';

и выводим этот компонент на страницу, сразу после последнего компонента.

В итоге у нас получится вот так:



Все файлы проекта на этом этапе смотрите в репо - react-site-slider-abc
ci -m "Location section"


Подвал сайта - футер

На этом я остановлюсь коротко. У нас будет самый простой подвал, с самой простой разметкой. Пэтому мы создадим его в папке, которую создали еще в первой части, и в которой у нас все для хэдера-фуера.

Наша задача будет просто вывести разметку и задать ей некую задержку проявления - Fade.Ранее мы уже работали с этим эффектом и потому я останавливаться на этом подробно не буду.

src/Components/Header_Footer/Footer.js
import React from "react";
import Fade from "react-reveal/Fade";

const Footer = () => {
  return (
    <footer className="bck_red">
      <Fade delay={500}>
        <div className="font_righteous footer_logo_venue">
          wmg react-meeting
        </div>
        <div className="footer_copyright">
          The venue 2019. © All rights reserved.
          <br />
          Made by Kolesnikov Yaroslav
        </div>
      </Fade>
    </footer>
  );
};

export default Footer;



Добавляем стили:

resources/style.css
/* ====================>>> FOOTER <<<========================= */
footer {
    padding:50px 0px;
    text-align: center;
    font-size: 60px;
    color:#ffffff;
    background: red;
}

footer .footer_copyright {
    font-size: 18px;
}



Подключаем и выводим компонент на страницу - как обычно в файле App.js



Все файлы проекта на этом этапе смотрите в репо - react-site-slider-abc
ci -m "Footer section"




                                                                                                                                                             

Телеграм канал - Full Stack JavaScript Developer

Комментариев нет:

Отправить комментарий



Хотите освоить самые современные методы написания React приложений? Надоели простые проекты? Нужны курсы, книги, руководства, индивидуальные занятия по React и не только? Хотите стать разработчиком полного цикла, освоить стек MERN, или вы только начинаете свой путь в программировании, и не знаете с чего начать, то пишите через форму связи, подписывайтесь на мой канал в Телеге, вступайте в группу на Facebook.Пишите мне - kolesnikovy70 почта gmail.com