我试图使用Svelte做一些条件样式和突出显示方程。虽然我已经成功地将全局静态样式应用于类,但我不知道当事件发生时如何做到这一点(比如类的一个实例悬停在上面)。
我是否需要创建一个存储值(即一些布尔值,当类悬停时设置为true)来使用条件样式?或者我可以像下面的例子一样写一个函数,它将针对类的所有实例?我有点不清楚为什么在样式上针对类需要:global(classname)
格式。
App.svelte
<script>
// import Component
import Katex from "./Katex.svelte"
// math equations
const math1 = "a\htmlClass{test}{x}^2+bx+c=0";
const math2 = "x=-\frac{-b\pm\sqrt{b^2-4ac}}{2a}";
const math3 = "V=\frac{1}{3}\pi r^2 h";
// set up array and index for reactivity and initialize
const mathArray = [math1, math2, math3];
let index = 0;
$: math = mathArray[index];
// changeMath function for button click
function changeMath() {
// increase index
index = (index+1)%3;
}
function hoverByClass(classname,colorover,colorout="transparent")
{
var elms=document.getElementsByClassName(classname);
console.log(elms);
for(var i=0;i<elms.length;i++)
{
elms[i].onmouseover = function()
{
for(var k=0;k<elms.length;k++)
{
elms[k].style.backgroundColor=colorover;
}
};
elms[i].onmouseout = function()
{
for(var k=0;k<elms.length;k++)
{
elms[k].style.backgroundColor=colorout;
}
};
}
}
hoverByClass("test","pink");
</script>
<h1>KaTeX svelte component demo</h1>
<h2>Inline math</h2>
Our math equation: <Katex {math}/> and it is inline.
<h2>Displayed math</h2>
Our math equation: <Katex {math} displayMode/> and it is displayed.
<h2>Reactivity</h2>
<button on:click={changeMath}>
Displaying equation {index}
</button>
<h2>Static math expression within HTML</h2>
<Katex math={"V=\pi\textrm{ m}^3"}/>
<style>
:global(.test) {
color: red
}
</style>
Katex.svelte
<script>
import katex from "katex";
export let math;
export let displayMode = false;
const options = {
displayMode: displayMode,
throwOnError: false,
trust: true
}
$: katexString = katex.renderToString(math, options);
</script>
<svelte:head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css" integrity="sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X" crossorigin="anonymous">
</svelte:head>
{@html katexString}
如果我理解正确的话,你有一个带有任意嵌套元素的DOM结构,你会想要突出显示共享相同类的结构部分。
你会得到这样的结构:
<div>
<p>This is some text <span class="a">highlight</span></p>
<span class="a">Another highlight</span>
<ul>
<li>Some listitem</li>
<li class="a">Some listitem</li>
<li class="b">Some listitem</li>
<li class="b">Some listitem</li>
</ul>
</div>
如果您选择具有class="a"
all的元素无论元素在文档中的位置如何,都应该突出显示它们。这种随意的放置使得在css中使用兄弟选择器是不可能的。
没有简单的解决办法,但我将给你我的尝试:
这是完整的代码和一些解释
<script>
import { onMount } from 'svelte'
let hash = {}
let wrapper
onMount(() => {
[...wrapper.querySelectorAll('[class]')].forEach(el => {
if (hash[el.className]) return
else hash[el.className] = [...wrapper.querySelectorAll(`[class="${el.className}"]`)]
})
Object.values(hash).forEach(nodes => {
nodes.forEach(node => {
node.addEventListener('mouseover', () => nodes.forEach(n => n.classList.add('hovered')))
node.addEventListener('mouseout', () => nodes.forEach(n => n.classList.remove('hovered')))
})
})
})
</script>
<div bind:this={wrapper}>
<p>
Blablabla <span class="a">AAA</span>
</p>
<span class="a">BBBB</span>
<ul>
<li>BBB</li>
<li class="a b">BBB</li>
<li class="b">BBB</li>
<li class="b">BBB</li>
</ul>
</div>
<style>
div :global(.hovered) {
background-color: red;
}
</style>
我做的第一件事是使用bind:this
来获得换行元素(在你的情况下,你会把它放在{@html katexString}
周围,这将使高亮只应用于这个特定子树。
做querySelector
是一个复杂的操作,所以我们将在onMount
期间收集所有相关节点的哈希表(这种假设内容永远不会改变,但由于它是用@html
呈现的,我相信这样做是安全的)。
正如您在onMount
中看到的那样,我使用包装器元素将选择器限制在页面的这一部分,这比检查整个文档要快得多,并且可能是您想要的。
我不完全确定你想做什么,但为了简单起见,我只是抓住每一个后代,有一个类,并为每个类做一个哈希部分。如果你只想要某些类,你可以在这里写一堆选择器:
hash['selector-1'] = wrapper.querySelectorAll('.selector-1');
hash['selector-2'] = wrapper.querySelectorAll('.selector-2')];
hash['selector-3'] = wrapper.querySelectorAll('.selector-3');
一旦创建了这个散列表,我们就可以遍历每个选择器,并为该选择器的所有元素附加两个事件侦听器。一个鼠标悬停在事件上,然后再次将一个新类应用于它的每个伙伴。还有一个mouseout,再次移除这个类。
这仍然意味着您必须添加hovered
类。因为在标记中不使用类,所以除非您自己发现使用:global()
,否则它将被Svelte删除。使用全局类确实不太好,因为你可能会在代码的其他地方产生意想不到的影响,但是你可以像我在上面的代码中那样对它进行作用域。
行
div > :global(.hovered) { background-color: red; }
将被处理成
div.svelte-12345 .hovered { background-color: red; }
所以红色背景将只应用于。悬停元素在这个特定的div内,而不会泄漏整个代码库。
关于REPL的演示
这里是相同的,以使用您的代码并使用文档范围的querySelector代替(如果需要,您可能仍然可以通过将绑定高一级并将此节点传递到组件中来进行限制)其他关于REPL
的演示