简体   繁体   English

CSS styles 未应用于 Vue 组件中的 HTML

[英]CSS styles not being applied to HTML within a Vue Component

I am trying to create a rotating text animation using Vue.js and I used this CodePen as inspiration.我正在尝试使用 Vue.js 创建一个旋转文本Vue.js ,我用这个CodePen作为灵感。

  • I got all the HMTL elements properly in place (ie, as in the CodePen mentioned).我把所有的HMTL元素都放在了适当的位置(即,正如在CodePen中提到的那样)。 In short:简而言之:

    • each word is formed of several <span> elements, each containing one letter.每个单词由几个<span>元素组成,每个元素包含一个字母。
    • following a specific time interval, each <span> that holds a letter gets applied an .in and .out CSS class.在特定的时间间隔之后,每个包含一个字母的<span>都会应用一个.in.out CSS class。 This goes on indefinitely.这种情况无限期地进行。
    • here is what it looks like in the DOM :这是它在DOM中的样子:

      在此处输入图像描述

  • the problem is that no matter what CSS selectors I use, I can't target the .in and .out classes, unless I do it via Developer Tools in Chrome :问题是,无论我使用什么CSS选择器,我都无法定位.in.out类,除非我通过Chrome中的Developer Tools进行操作:

    • original output:原装 output:

      在此处输入图像描述

    • output after I added the classes in Developer Tools : output 在Developer Tools中添加类后:

      在此处输入图像描述

Here is the bare minimum code of my Vue Component :这是我的Vue Component的最低限度代码:

<template>
    <div id="app-loading">  
        <div class="words">
            <span v-for="setting in settings" v-html="setting.lettersHTML" :id="setting.id" class="word"></span>    
        </div>
    </div>
</template>


<script>
    export default {
        data() {
            return {
                settings: [
                    { word: 'WordOne', id: 1, lettersArray: null, lettersHTML: null },
                    { word: 'WordTwo', id: 2, lettersArray: null, lettersHTML: null }
                ],
                currentWord: 1
            }
        },

        created() {
            this.splitLetters();
        },

        mounted() {
            setInterval(this.changeWord, 1500);
        },

        methods: {
            splitLetters() {
                this.settings.forEach((setting) => {
                    let letters = [];
                    for (let i = 0; i < setting.word.length; i++) {
                        let letter = `<span class="letter">${ setting.word.charAt(i) }</span>`;
                        letters.push(letter);
                    }
                    setting.lettersArray = letters;
                    setting.lettersHTML = letters.join('');
                });
            },

            changeWord() {
                let current = document.getElementById(this.currentWord).getElementsByTagName('span');
                let next = (this.currentWord == this.settings.length) ? document.getElementById(1).getElementsByTagName('span') : document.getElementById(this.currentWord + 1).getElementsByTagName('span');
                // Animate the letters in the current word.
                for (let i = 0; i < current.length; i++) {
                    this.animateLetterOut(current, i);
                }
                // Animate the letters in the next word.
                for (let i = 0; i < next.length; i++) {
                    this.animateLetterIn(next, i);
                }
                this.currentWord = (this.currentWord == this.settings.length) ? 1 : this.currentWord + 1;
            },

            animateLetterOut(current, index) {
                setTimeout(() => {
                    current[index].className = 'letter out';
                }, index * 300);
            },

            animateLetterIn(next, index) {
                setTimeout(() => {
                    next[index].className = 'letter in';
                }, 340 + (index * 300));
            }
        }
    }
</script>


<style lang="scss" scoped>
    #app-loading {
        font-size: 4rem;
    }

    .words, .word {
        border: 1px solid rosybrown;
    }

    .letter {
        text-decoration: underline; // Not working.
    }

    .letter.in {
        color: red; // Not working.
    }

    .letter.out {
        color: blue; // Not working.
    }
</style>

What goes wrong that prevents these classes from being applied?是什么问题阻止了这些类的应用?

You're using v-html , but that doesn't work with scoped styles .您正在使用v-html ,但这不适用于范围样式

DOM content created with v-html are not affected by scoped styles, but you can still style them using deep selectors.使用v-html创建的 DOM 内容不受范围样式的影响,但您仍然可以使用深度选择器来设置它们的样式。

Yes,是的,

v-html v-html

doesn't work with scoped styles.不适用于范围样式。

As Brock Reece explained in his article Scoped Styles with v-html , it should be solved like this:正如 Brock Reece 在他的文章Scoped Styles with v-html 中解释的那样,应该这样解决:

<template>   
    <div class="a" v-html="content"></div> 
</template>

<script>   
    export default { 
        data() {
           return {
              content: 'this is a <a class="b">Test</a>',
           }
        },
    } 
</script>

<style scoped>   
.a >>> .b {
color: red;   
}
</style>

This worked for me:这对我有用:

<template>   
    <div class="a" v-html="content"></div> 
</template>

<script>   
    export default { 
        data() {
           return {
              content: 'this is a <a class="b">Test</a>',
           }
        },
    } 
</script>

<style scoped>   
.a ::v-deep .b { 
     color: red;
 }
</style>

Most answers are deprecated now that Vue3 is out.由于 Vue3 已经发布,大多数答案都已被弃用。 Up-to-date usage of deep selector:深度选择器的最新用法:

.letter{
  &:deep(.in) {
    color:blue;
  }
  &:deep(.out) {
    color:red;
  }
}

Vue3: In Single-File Components, scoped styles will not apply to content inside v-html, because that HTML is not processed by Vue's template compiler. Vue3:在单文件组件中,作用域 styles 将不适用于 v-html 内的内容,因为 Vue 的模板编译器不会处理 HTML。

You can use:deep() inner-selector in Vue3 project.您可以在 Vue3 项目中使用:deep() 内部选择器。

Here is a example:这是一个例子:

<script setup lang="ts">

import {onMounted,ref } from 'vue'
const content = ref("")

onMounted(()=>{
    window.addEventListener('keydown',event =>{
        content.value = `
            <div class="key">
                <span class="content">${event.keyCode}</span>
                <small>event.keyCode</small>
            </div>
        `
    })
})

</script>

<template>
    <div class="container" v-html="content">
    </div>
</template>

<style lang="scss" scoped>  

.container{
    display: flex;
    
    :deep(.key){
        font-weight: bold;
        
        .content{
            font-size: 1.5rem;
        }
        
        small{
            font-size: 14px;
        }
    }
}
</style>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM