rendu html brut à partir de vuejs

Aug 17 2020

https://codepen.io/AnonymousCaptain/pen/eYZZOyO

J'ai fait cela, mais j'ai besoin que mon "{{data.body}}" soit interprété comme du HTML.

Je suis totalement novice et j'espère que quelqu'un pourra m'aider.

Jusqu'à présent, je me suis cogné la tête contre le mur numérique en regardant la directive appelée v-html... mais je ne sais pas si c'est ce que je suis censé utiliser.

J'ai aussi vu des gens faire quelque chose comme :

Vue.component("app", { modèle :HTML

https://www.digitalocean.com/community/tutorials/vuejs-raw-html-bindingC'est peut-être ce dont j'ai besoin ?

Merci de m'orienter vers une solution :)

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>

Réponses

1 zuchmanski Aug 17 2020 at 19:29

Vous pouvez utiliser v-htmlcette méthode :

<p v-html="data.body"></p>

Il affichera le HTML à l'intérieur de la <p>balise.

s4k1b Aug 17 2020 at 19:31

Si vous souhaitez utiliser du texte en tant que html dans vue, vous pouvez utiliserv-html

Bien qu'il y ait un avertissement à ne pas utiliser, v-htmlcar cela rendra votre application sujette aux attaques XSS.

Cet avertissement sera toujours là et il est là pour une bonne raison. Pour éviter les attaques XSS, il vous suffit de nettoyer votre chaîne html que vous insérez brute. Ce processus d'assainissement supprimera tout ce qui pourrait conduire à l'exécution de scripts à partir de HTML, empêchant ainsi les attaques XSS et vous permettant ainsi d'injecter en toute sécurité des ensembles complets de nœuds HTML dans votre DOM à l'aide de v-html.

DOMPurify , qui a été examiné par divers experts en sécurité, est une bibliothèque appropriée pour assainir votre code HTML brut.