如何解决从vuejs内渲染原始html
https://codepen.io/AnonymousCaptain/pen/eYZZOyO
我已经做到了,但我需要将“ {{data.body}}”解释为HTML。
我是一个新手,我希望那里的人能够帮助我。
到目前为止,我已经把目光投向了数字墙,看着名为v-html的指令...但是我不确定这是否是我应该使用的指令。
我还看到人们在做类似的事情:
Vue.component(“ app”,{
模板: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,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!',dolor sit amet consectetur adipisicing elit. Ab nam aliasdfasdfaas architecto officia,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?',},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>
解决方法
您可以通过以下方式使用v-html
:
<p v-html="data.body"></p>
它将在<p>
标签内呈现html。
如果要在vue中将某些文本用作html,则可以使用v-html
尽管会有警告,请不要使用v-html
,因为使用它会使您的应用容易受到XSS攻击。
此警告将始终存在,并且有充分的理由存在。为了防止XSS攻击,您只需要清理插入原始文件的html字符串。此卫生过程将删除可能导致HTML执行脚本的所有内容,从而防止XSS攻击,因此您可以使用v-html
安全地将完整的HTML节点集注入DOM。
DOMPurify经过了各种安全专家的审查,是一个用于清理原始html的合适库。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。