कच्चे html को vuejs के भीतर से प्रस्तुत करना
https://codepen.io/AnonymousCaptain/pen/eYZZOyO
मैंने इसे बनाया है, लेकिन मुझे HTML के रूप में व्याख्या करने के लिए मेरे "{{data.body}}" की आवश्यकता है।
मैं कुल नौसिखिया हूं और मुझे आशा है कि कोई व्यक्ति मेरी मदद करने में सक्षम होगा।
अब तक मैंने 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>
जवाब
आप v-html
इस तरह से उपयोग कर सकते हैं :
<p v-html="data.body"></p>
यह html को <p>
टैग के अंदर रेंडर करेगा ।
यदि आप vue में html के रूप में कुछ पाठ का उपयोग करना चाहते हैं, तो आप उपयोग कर सकते हैं v-html
यद्यपि उपयोग न करने की चेतावनी होगी v-html
क्योंकि इसका उपयोग करने से आपके ऐप को XSS हमलों का खतरा होगा।
यह चेतावनी हमेशा रहेगी और एक अच्छे कारण के लिए है। XSS के हमलों को रोकने के लिए आपको बस अपने html string को sanitize करना होगा जो आप कच्चे में डाल रहे हैं। यह स्वच्छता प्रक्रिया ऐसी किसी भी चीज़ को छीन लेगी जो HTML से स्क्रिप्ट निष्पादन को जन्म दे सकती है, इस प्रकार XSS हमलों को रोक सकती है और इसलिए आप अपने डोम का उपयोग करके HTML नोड्स के पूर्ण सेटों को सुरक्षित रूप से इंजेक्ट कर सकते हैं v-html
।
DOMPurify , जिसे विभिन्न सुरक्षा विशेषज्ञों द्वारा समीक्षा की गई है, आपके कच्चे HTML को साफ करने के लिए एक उपयुक्त पुस्तकालय है।