#html #vue.js #vuejs2
#HTML #vue.js #vuejs2
Вопрос:
https://codepen.io/AnonymousCaptain/pen/eYZZOyO
Я сделал это, но мне нужно, чтобы мои «{{data.body}}» интерпретировались как HTML.
Я абсолютный новичок и надеюсь, что кто-нибудь там сможет мне помочь.
До сих пор я бился головой о цифровую стену, глядя на директиву под названием v-html… но я не уверен, что это то, что я должен использовать.
Я также видел, как люди делают что-то вроде:
Vue.component(«приложение», { шаблон: HTML
https://www.digitalocean.com/community/tutorials/vuejs-raw-html-binding Это может быть то, что мне нужно?
Пожалуйста, укажите мне на решение 🙂
new Vue({
el: '#magiccardapp',
data: {
message: 'Hello',
tabs: {
'Title 1': {
subtitle: 'some text here',
title: 'Awesome Title',
body: 'Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ab nam alias architecto officia, dolores animi qui debitis incidunt eius temporibus nostrum nihil soluta commodi molestiae necessitatibus ducimus amet. Suscipit, saepe!',
img_1: 'https://placedog.net/320/180/?random',
img_2: 'https://placedog.net/320/180/?random'
},
'Title 2': {
subtitle: 'some cool text here',
title: 'This is great',
body: 'Lorem ipsasdfasdfasd alias architecto officia, dolores animi qui debitis incidunt eius temporibus nostrum nihil soluta commodi molestiae necessitatibus ducimus amet. Suscipit, saepe!',
img_1: 'https://placedog.net/320/180/',
img_2: 'https://placedog.net/320/180/'
},
'Title 3': {
subtitle: 'some epic text here',
title: 'Look I'm a title!',
body: 'Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ab nam aliasdfasdfaas architecto officia, dolores animi qui debitis incidunt eius temporibus nostrum nihil soluta commodi molestiae necessitatibus ducimus amet. Suscipit, saepe!',
img_1: 'https://cdn.mos.cms.futurecdn.net/QjuZKXnkLQgsYsL98uhL9X-320-80.jpg',
img_2: 'https://aldf.org/wp-content/uploads/2018/06/sad-dog-1846066_1920-320x180.jpg'
},
'Title 4': {
subtitle: 'some other text here',
title: 'LOREM IPSUM?',
body: 'Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ab nam alias architecto officia, dolores animi qui debitis incidunt eius temporibus nostrum nihil soluta commodi molestiae necessitatibus ducimus amet. Suscipit, saepe!',
img_1: 'https://cdn.mos.cms.futurecdn.net/QjuZKXnkLQgsYsL98uhL9X-320-80.jpg',
img_2: 'https://aldf.org/wp-content/uploads/2018/06/sad-dog-1846066_1920-320x180.jpg'
},
},
activeTab: 'Title 1',
},
computed:{
tabContent() {
return this.tabs[this.activeTab];
},
},
methods: {
setTabActive(tab) {
this.activeTab = tab;
}
},
components:{
'TabContent': {
props: {
data: Object,
},
}
},
})
/*tabs*/
magiccarddeck {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
grid-gap: 1rem 1rem;
align-items: center;
max-width: 1000px;
padding: 1rem 1rem;
font-family: "Open Sans",
sans-serif;
text-align: center;
}
magiccard:hover {
transform: scale(1.05);
border-radius: 0.25rem;
overflow: hidden;
transition: 1s;
-webkit-transition: 1s;
}
.line {
height: 2px;
width: 100%;
margin: auto;
background-color: #c38e3d;
}
magiccard {
background: ghostwhite;
border-radius: 0.25rem;
overflow: hidden;
transition: 1s;
-webkit-transition: 1s;
cursor: pointer;
height: 100%;
color: black;
border: 0.3rem solid #c38e3d;
height: max-content;
filter: brightness(50%);
}
magiccard:hover {
filter: brightness(100%);
}
magiccard.active {
cursor: unset;
transform: scale(1.05);
filter: brightness(100%);
}
magiccard h3 {
justify-content: center;
letter-spacing: 4px;
margin: 0px;
color: black;
font-weight: 400;
font-size: 20px;
line-height: 90%;
padding-left: 0%;
padding-top: 3%;
padding-bottom: 3%;
border-radius: 20px;
}
magiccard p {
line-height: 1.6;
}
/* BOTTOM */
section {
font-family: "Open Sans",
sans-serif;
font-weight: 800;
color: ghostwhite;
font-size: 12px;
}
#workshopgrid {
padding: 1rem 1rem;
max-width: 1000px;
justify-self: center;
}
workshopbox {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr;
border: 0.3rem solid #c38e3d;
border-radius: 0.5rem;
background: ghostwhite;
padding: 1rem 2rem;
grid-template-areas:
'text'
'img';
}
@media (min-width: 800px) {
workshopbox {
grid-template-columns: 3fr 1fr;
grid-template-areas:
'text img';
}
workshopdescription {
border-right-style: groove;
padding-right: 2%;
}
workshopimg {
padding-left: 1rem;
}
}
@media (max-width: 799px) {
workshopbox {}
workshopdescription {
border-bottom-style: groove;
}
workshopimg {
padding-top: 1rem;
}
}
.workshoptext {
grid-area: 1 / 1 / 2 / 2;
grid-area: text;
margin: 0px;
color: black;
font-weight: 400;
font-size: 15px;
line-height: 100%;
padding-top: 3%;
padding-bottom: 2%;
}
workshopdescription {
grid-area: 1 / 1 / 2 / 2;
grid-area: text;
margin: 0px;
color: black;
font-weight: 400;
font-size: 15px;
line-height: 100%;
padding-top: 3%;
padding-bottom: 2%;
}
workshopdescription h1 {
line-height: initial;
}
workshopimg {
grid-area: 1 / 2 / 2 / 3;
grid-area: img;
display: grid;
grid-gap: 1rem;
color: black;
align-content: center;
/* border-left: 1px solid; */
justify-content: center;
}
/*transitions*/
.fade-enter-active > *,
.fade-leave-active > * {
transition-duration: 200ms;
transition-property: opacity, transform;
transition-timing-function: cubic-bezier(0.6, 0.15, 0.35, 0.8);
}
.fade-enter > *,
.fade-leave-to > * {
opacity: 0;
transform: translateY(40px);
}
.fade-enter-active > *:nth-child(2) {
transition-delay: 100ms;
}
.fade-enter-active > *:nth-child(3) {
transition-delay: 200ms;
}
.fade-leave-active > *:nth-child(1) {
transition-delay: 200ms;
}
.fade-leave-active > *:nth-child(2) {
transition-delay: 100ms;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<main id="magiccardapp">
<magiccarddeck>
<magiccard v-for="(tab, tabName) in tabs" :key="tabName" @click="setTabActive(tabName)" :class="{'active': tabName === activeTab}">
<h3 class="tab-copy">{{ tabName }}</h3>
<div class="line"></div>
{{tab.subtitle}}
</magiccard>
</magiccarddeck>
<section id="workshopgrid">
<workshopbox>
<workshopdescription>
<transition name="fade" mode="out-in" appear :duration="500">
<tab-content v-for="(tabContent, t) in tabs" :data="tabContent" :key="'content' t" v-if="t === activeTab" inline-template>
<div class="content">
<h1>{{data.title}}</h1>
<p>{{data.body}}</p>
</div>
</tab-content>
</transition>
</workshopdescription>
<tab-content v-for="(tabContent, t) in tabs" :data="tabContent" :key="'workshopimg' t" v-if="t === activeTab" inline-template>
<workshopimg>
<img :src="data.img_1">
<img :src="data.img_2">
</workshopimg>
</tab-content>
</workshopbox>
</section>
</main>
Ответ №1:
Вы можете использовать v-html
этот способ:
<p v-html="data.body"></p>
Он будет отображать html внутри <p>
тега.
Комментарии:
1. Как было только что прокомментировано выше, это, по-видимому, небезопасно? Я ищу способ просто записать огромную нагрузку
HTML TAGS
в моем javascript. Мне это нужно для форматирования текста (добавления классов и т.д.) И особенно, мне это нужно для добавления маркированных списков.2. Вы могли бы использовать средство очистки со списком тегов или атрибутов, внесенных в белый список ( github.com/apostrophecms/sanitize-html ) или рендеринг markdown ( github.com/miaolz123/vue-markdown ) для поддержки базового форматирования (жирный шрифт, курсив, списки, ссылки, изображения и т.д.).
Ответ №2:
Если вы хотите использовать некоторый текст в качестве html в vue, вы можете использовать v-html
Хотя будет предупреждение не использовать v-html
, потому что использование этого сделает ваше приложение подверженным атакам XSS.
Это предупреждение всегда будет там, и на то есть веская причина. Для предотвращения XSS-атак вам просто нужно очистить вашу HTML-строку, которую вы вставляете в необработанном виде. Этот процесс очистки удалит из HTML все, что может привести к выполнению скрипта, тем самым предотвращая атаки XSS, и поэтому вы можете безопасно внедрять полные наборы узлов HTML в свой DOM с помощью v-html
.
DOMPurify, который был рассмотрен различными экспертами по безопасности, является подходящей библиотекой для очистки вашего необработанного html.
Комментарии:
1. Я бы предпочел узнать, как сделать это надлежащим безопасным способом 🙂 Пожалуйста, помогите мне, сенсей!
2. Есть ли у меня «{{data.body}}» или «<p>{{data.body}}</p> в моем HTML… У меня все еще есть та же проблема, связанная с желанием, возможно, нескольких абзацев с дополнительными классами, маркированными списками… Я надеюсь, вы понимаете, что я имею в виду.
3. Отредактировал мой ответ, надеюсь, это поможет 🙂
4. Оба этих ответа решили мою проблему. Похоже, зухмански нуждается в повышении баллов, и я надеюсь, вы не против, если я приму его ответ. Я продолжу исследование использования дезинфицирующих средств 🙂 Жаль, что я могу принять только 1 ответ.