От автора: я люблю не только вести блог, но и читать блоги! Традиционно, когда блогеры излагают некоторые научные факты или ссылаются на другие посты, они должны добавить ссылку на источники. Вопрос для читателей: стоит ли прекратить читать пост и перейти к чтению источника сейчас? Потому что в посте у нас может быть до 10 ссылок на разные источники. Что нам делать – продолжать читать или перейти по ссылке?
Вот почему в настоящее время средство просмотра содержимого ссылок является обязательной функцией для блогов и даже чатов. Вы уже видели их в самых разных формах на Facebook*, LinkedIn, Twitter, WhatsApp и т. д.
Основным преимуществом предварительного просмотра содержимого ссылки является то, что читатели могут увидеть, что они прочитают позже, прежде чем перейти по ссылке.
Обычно предварительный просмотр содержимого ссылки содержит имя домена (URL), заголовок, текст и изображение. Вы также можете добавить дополнительную информацию, предоставляя больше данных для содержимого.
В этой статье я покажу вам, как можно быстро разработать функцию просмотра содержимого ссылок для блога с помощью React, Vue и Vanilla JavaScript.
По принципу от простых до более сложных концепций, давайте начнем с реализации на Vanilla JavaScript.
Часть I: Предварительный просмотр содержимого ссылок на VanillaJS
Первый шаг — добавить простой текстовый контент в index.html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<!--index.html--> <html lang="en"> <head> <meta charset="UTF-8"> <title>Link Content Previewer</title> </head> <body> <div class="wrapper"> <p>Hi there!</p> <p>I would like to share some frontend tips and tricks that I have already applied to some of my projects.</p> <p>Happily coming back with <br/> my <a href="//dev.to/ilonacodes/frontend-shorts-vue-js-vanilla-js-digital-dices-og" class="link-with-preview" > frontend shorts </a> series on <a href="//dev.to" class="link-with-preview" > dev.to. </a> Let me show you how... </p> </div> </body> </html> |
Далее нам необходимо создать элемент card, который будет включать и отображать информацию из указанного источника:
1 2 3 4 5 6 7 8 9 |
<!--index.html--> ... <div class="card"> <img src="" class="card-img-top"> <div class="card-body"> <h5 class="card-title"></h5> <p class="card-text"></p> </div> </div> |
Вы видите, что я использую Bootstrap 4 и собственные CSS-классы для стилизации карточек. Их также нужно импортировать в head:
1 2 3 4 5 |
<!--index.html--> ... <link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"> <link rel="stylesheet" href="index.css"> ... |
Благодаря функционалу Boostrap 4, позиционирование элементов и некоторые базовые стили автоматически применяются из библиотеки. Итак, файл index.css не большой, поэтому ниже вы найдете все необходимые стили для функции предварительного просмотра содержимого ссылки:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
/*index.css*/ body { font-size: 24px; } .wrapper { width: 500px; top: 50%; left: 50%; transform: translate(-50%, -50%); position: absolute; } .card { width: 150px; display: none; font-size: 10px; color: black; position: absolute; z-index: 100; bottom: 30px; left: 50%; transform: translateX(-50%); } .link-with-preview { position: relative; } .card img { width: 150px; } .card-title { font-size: 14px; } |
Чтобы заставить работать предпросмотр содержимого ссылок, нам нужно написать JavaScript. Я надеюсь, вы не забыли добавить script в конце body в index.html:
1 2 3 |
<!--index.html--> ... <script src="index.js"></script> |
Мы готовы приступить к JavaScript:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
const card = document.querySelector(".card"); const hideLinkPreview = () => { return card.style.display = 'none'; }; const showLinkPreview = event => { const image = event.currentTarget.getAttribute("data-image"); card.querySelector('img').setAttribute("src", image); const title = event.currentTarget.getAttribute("data-title"); card.querySelector('h5').textContent = title; const text = event.currentTarget.getAttribute("data-text"); card.querySelector('p').textContent = text; event.currentTarget.appendChild(card); return card.style.display = 'inline-block'; }; document.querySelectorAll(".link-with-preview").forEach(el => { el.addEventListener("mouseover", showLinkPreview); el.addEventListener("mouseleave", hideLinkPreview) }); |
Объявляем card и реализуем две функции hideLinkPreview(event) и showLinkPreview(event) с параметром event. В нашем случае это события onmouseover и onmouse leave для ссылки <a />.
hideLinkPreview(event) работает просто. Она просто скрывает предварительный просмотр содержимого (карточку) при событии отведения мыши.
Для showLinkPreview(event) важно получить из ссылки <a /> такие атрибуты, как data-image, data-title и data-text, установить их в экземпляре card, чтобы отобразить предварительный просмотр содержимого ресурса при событии наведения курсора мыши.
event.currentTarget.appendChild(card); помогает нам добавить в card окно предварительного просмотра содержимого ссылки и правильно расположить / отцентрировать карточку над ссылкой.
Передаем все необходимые данные в index.html для предварительного просмотра непустого card в браузере при наведении.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
<!--index.html--> <html lang="en"> <head> <meta charset="UTF-8"> <title>Link Content Previewer</title> <link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"> <link rel="stylesheet" href="index.css"> </head> <body> <div class="wrapper"> <p>Hi there!</p> <p>I would like to share some frontend tips and tricks that I have already applied to some of my projects.</p> <p>Happily coming back with <br/> my <a href="//dev.to/ilonacodes/frontend-shorts-vue-js-vanilla-js-digital-dices-og" onmouseover="showLinkPreview()" onmouseleave="hideLinkPreview()" class="link-with-preview" data-image="//dev-to-uploads.s3.amazonaws.com/i/3zp478dfafzy1mgfaevn.jpg" data-title="Frontend Shorts: Vue.js + Vanilla.js — Digital Dices" data-text="Let me show you how you can implement a dice-rolling simulator in less than 30 minutes of your time on the front-end." >frontend shorts</a> series on <a href="//dev.to" onmouseover="showLinkPreview()" onmouseleave="hideLinkPreview()" class="link-with-preview" data-image="//thepracticaldev.s3.amazonaws.com/i/6hqmcjaxbgbon8ydw93z.png" data-title="DEV Community" data-text="Where programmers share ideas and help each other grow—A constructive and inclusive social network." > dev.to. </a> Let me show you how... </p> </div> <div class="card"> <img src="" class="card-img-top"> <div class="card-body"> <h5 class="card-title"></h5> <p class="card-text"></p> </div> </div> <script src="index.js"></script> </body> </html> |
Полный исходный код реализации VanillaJS вы можете найти:
Часть II. Предварительный просмотр содержимого ссылок с помощью Vue.js
Как вы уже догадались, index.html и index.css будет выглядеть аналогично реализации index.html и index.css из VanillaJS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<div id="app"> <div class="wrapper"> <p>Hi there!</p> <p>I would like to share some frontend tips and tricks that I have already applied to some of my projects.</p> <p>Happily coming back with <br/> my <link-previewer href="//dev.to/ilonacodes/frontend-shorts-vue-js-vanilla-js-digital-dices-og" text="frontend shorts" preview-img="//dev-to-uploads.s3.amazonaws.com/i/3zp478dfafzy1mgfaevn.jpg" preview-title="Frontend Shorts: Vue.js + Vanilla.js — Digital Dices" preview-text="Let me show you how you can implement a dice-rolling simulator in less than 30 minutes of your time on the front-end." ></link-previewer> series on <link-previewer href="//dev.to" text="dev.to." preview-img="//thepracticaldev.s3.amazonaws.com/i/6hqmcjaxbgbon8ydw93z.png" preview-title="DEV Community" preview-text="Where programmers share ideas and help each other grow—A constructive and inclusive social network." ></link-previewer> Let me show you how... </p> </div> </div> |
Чтобы использовать фреймворк Vue.js, вам нужно добавить скрипт Vue.js:
1 |
<script src="//cdn.jsdelivr.net/npm/vue@2.6.11"></script> |
В соответствии с index.html, нам не хватает компонента link-previewer с соответствующими реквизита: href, text, previewTitle, previewImg и previewText. Давайте создадим компонент link-previewer с Vue.js в index.html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
... <script> Vue.component('link-previewer', { props: ['href', 'text', 'previewTitle', 'previewImg', 'previewText'], data() { return { shown: false }; }, methods: { show() { this.shown = true; }, hide() { this.shown = false; } }, // this enables proper syntax highlighting and auto-completion in the IDE for the HTML code snippet below: //language=HTML template: ` <a v-bind:href="href" v-on:mouseover="show" v-on:mouseleave="hide" class="link-with-preview" > {{ text }} <div class="card" v-bind:class="{'card-show': shown}"> <img v-bind:src="previewImg" alt="" class="card-img-top"> <div class="card-body"> <h5 class="card-title">{{ previewTitle }}</h5> <div class="card-text"> {{ previewText }} </div> </div> </div> </a> ` }); const app = new Vue({ el: '#app' }); </script> |
Единственные данные, которые изменяют состояние компонента link-previewer, это shown: false в data()
Это зависит от вызова методов show() и hide()
В случае реализации Vue.js компонент card с указанными реквизитами будет построен как template.
Данные передаются из link-previewer в card с помощью сокращения v-bind, и событие через v-on.
Полное решение на Vue.js вы можете найти здесь: Vue.js — index.html.
Часть III. Предварительный просмотр содержимого ссылок с помощью React.js
HTML-структура компонента App.js практически такая же, как и index.html для реализации VanillaJS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
// App.js import React from "react"; import "./styles.css"; import { LinkPreviewer } from "./LinkPreviewer"; export default function App() { return ( <div className="App"> <div> <p>Hi there!</p> <p> I would like to share some frontend tips and tricks that I have already applied to some of my projects. </p> <p> Happily coming back with <br /> my <LinkPreviewer href="//dev.to/ilonacodes/frontend-shorts-vue-js-vanilla-js-digital-dices-og" image="//thepracticaldev.s3.amazonaws.com/i/6hqmcjaxbgbon8ydw93z.png" title="Frontend Shorts: Vue.js + Vanilla.js — Digital Dices" text="Let me show you how you can implement a dice-rolling simulator in less than 30 minutes of your time on the front-end." > frontend shorts </LinkPreviewer> series on <LinkPreviewer href="//dev.to" image="//thepracticaldev.s3.amazonaws.com/i/6hqmcjaxbgbon8ydw93z.png" title="DEV Community" text="Where programmers share ideas and help each other grow—A constructive and inclusive social network." > dev.to </LinkPreviewer> </p> </div> </div> ); } |
Разница лишь в том, что нам нужно создать компонент LinkPreviewer и использовать его для визуализации нужных данных для предварительного просмотра содержимого ссылки:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
// LinkPreviewer import React, { useState } from "react"; import "./styles.css"; export const LinkPreviewer = props => { const [isShown, setIsShown] = useState(false); return ( <a href={props.href} className="link-with-preview" onMouseEnter={() => setIsShown(true)} onMouseLeave={() => setIsShown(false)} > <span> {props.children} </span> {isShown && ( <Card image={props.image} title={props.title} text={props.text} /> )} </a> ); }; const Card = props => { return ( <div className="card"> <img src={props.image} className="card-img-top" alt="" /> <div className="card-body"> <h5 className="card-title">{props.title}</h5> <p className="card-text">{props.text}</p> </div> </div> ); }; |
LinkPreviewer возвращает <a/> с нужными свойствами, событиями и классами стилей для воспроизведения предварительного просмотра содержимого ссылок в браузере.
Компонент Card отображает содержимое как изображение, заголовок и текст источника при предварительном просмотре, когда isShown — true.
Благодаря React Hook const [isShown, setIsShown] = useState(false); мы можем просто обрабатывать два события onMouseEnter и onMouseLeave из LinkPreviewer при наведении курсора, и скрывать и отображать предварительный просмотр содержимого ссылки.
CSS-классы идентичны index.css подходу VanillaJS. Сниппеты кода реализации React вы можете найти здесь.
Заключение
Как видите, реализовать функцию предварительного просмотра содержимого ссылки просто, не зависимо от того, какую среду JavaScript или библиотеку вы используете. Потому что любая реализация будет несильно отличаться от другой. Подход остается прежним.
Если вы являетесь разработчиком или технически подкованным человеком, у которого есть собственный блог, то вам не нужно полагаться на стороннюю библиотеку, чтобы получить такой функционал. Вы можете разработать его самостоятельно. Спасибо за прочтение! Надеюсь, вы нашли этот краткий пост полезным и практичным.
Автор: Ilona Codes
Источник: //dev.to
Редакция: Команда webformyself.
* Признана экстремистской организацией и запрещена в Российской Федерации.