Vue.js通过外部库动态更改DOM(jQuery样式)

时间:2020-08-31 10:40:46

标签: jquery vue.js

假设我使用Vue.JS完成了我的项目。我有很多使用Vue.JS组件的HTML,等等...我的表单,输入,按钮...很多东西都有它们的title属性...现在我希望使这些标题看起来像多花哨。在jQuery中,很容易创建一个小的lib(并且有很多),而无需触摸现有的html。

如何实现“ 提示方式”?

[编辑-更多示例]

  1. 想象一下,我希望添加github.com/Akryum/v-tooltip指令,但不希望重构我的所有代码,并在我的所有html中都包含v-tooltip属性(称其为惰性)。因此,我想执行类似$('a[title]').each(function(){ $(this).attr('v-title', $(this).attr('title')); });的操作,以自动将v-title指令应用于具有title属性的所有链接...。我知道我可以在使用jQuery或vanilla js初始化Vue.js之前进行此操作,但这就是有点傻。
  2. 假设我使用Vuetify,并且出于调试目的,我希望所有v-btn组件在单击时都可以放置到console.log中。在jQuery中,就像$('.mybutton').click(function(){ console.log($(this).data() ); });
  3. 一样简单
  4. 我希望在标题/工具提示中显示每个输入的当前值。但是再说一次-无需重构我的所有代码,因为也许我只是需要它作为用户体验的临时措施或A / B测试,并且第二天/每周将其删除...因为某些伪代码看起来像{{1 }}

8 个答案:

答案 0 :(得分:4)

vuejs中,您有一个名为Directive的功能,它对于处理这种情况非常有用。只需创建一个全局指令(因为您似乎将在多个地方使用它)并在其中添加您感兴趣的所有必要样式和行为。

答案 1 :(得分:3)

我认为,由于Vue 3通过覆盖默认渲染器的新型模块化体系结构,您可以实现所需的功能。您可以在this great article

中找到一些示例

我认为这不是一个好主意,但我可以想象一个人应该能够以这种方式在Vue中创建类似jQuery的体验...。

编辑

我看到了您的修改(添加了示例),我需要添加一些内容。当我谈论“类似于jQuery的体验”时,它实际上是在运行时通过更改虚拟DOM修补实际DOM的方式来修改DOM。

但是您所有的示例都使用了某些Vue功能,这些功能是完全独立的(在堆栈中更高)。例如,添加指令或更改属性-这必须在模板本身上完成(并且模板会在构建时编译为渲染函数),或者通过替换默认的createElement(通常称为h)函数来完成,它是imported globally in Vue 3,所以我不确定是否可以替换它...

这确实是不同的,而且方式更加困难...

答案 2 :(得分:2)

Vue定制Directives是解决此问题的最佳解决方案。基本上Directives是可以附加到DOM元素的微小命令。当您需要低级访问时,它们通常非常有用HTML元素来控制一些行为。在此指令中添加所需的样式或行为,并在所需的位置使用。

创建自定义指令的步骤。

例如,您要为背景设置指令,将其命名为CustomBackgroundDirective,然后首先创建一个名为CustomBackgroundDirective.js的新文件,例如。

import Vue from 'vue';

const defaultBackgroundColor = '#86bbff'

// Initialize the custom-background directive.
export const CustomBackground = {
  bind(el, binding, vnode) {
    // Allow users to customise the color by passing an expression.
    const color = binding.expression || defaultBackgroundColor

    // el might not be present for server-side rendering.
    if (el) {
      // Set the element's background color.
      el.style.backgroundColor = color
    }
  }
}

// You can also make it available globally.
Vue.directive('custom-background', CustomBackground)


现在要在组件中使用它,只需将其添加到以v-为前缀的组件模板中

<template>
  <div>
    <p v-custom-background>Baby blue looks good on me.</p>
    <p v-custom-background="#0f0">I prefer neon green.</p>
  </div>
</template>

<script>
import { CustomBackground } from './CustomBackgroundDirective.js';

export default {
  directives: {
    CustomBackground
  }
}
</script>


此外,该指令还有一些钩子可供您使用,每个钩子都可以选择几个参数。挂钩如下:

  • bind –一旦指令附加到元素,就会发生这种情况。
  • 已插入–将元素插入到 父DOM。
  • update –当元素更新但子元素更新时调用此钩子 尚未更新。
  • componentUpdated –一旦组件和 子项已更新。
  • unbind –删除指令后将调用此钩子。

答案 3 :(得分:1)

您不需要Vue,JavaScript或jQuery!

可以通过纯HTML / CSS完成工具提示。

我知道这不能解决您所有其他示例。但是,由于很多开发人员在不一定总是需要JavaScript时会使用它,因此我认为此答案可能对其他人有帮助。

[data-title]:hover::after {
  content: attr(data-title);
}
<p data-title="title">Hover me </p>

有关详细说明,请参见:

答案 4 :(得分:0)

您可以只使用现代CSS: https://css-tricks.com/css-content/#example-trick-css3-tooltips

如果这不能满足您的需求,那么接下来要做的最简单的事情就是制作一个具有所需视觉效果的组件,然后在必要时添加它。

Vue正在控制DOM的呈现,因此它不会像jQuery那样工作,它解析DOM然后注入自己的元素。如果您真的想对此付诸东流,则应该能够在Vue中使用渲染功能和自定义合并策略创建全局mixin,该策略将基于对渲染组件的检查注入mixin工具提示。我不确定我是否会称其为“ Vue方式”。

答案 5 :(得分:0)

您无法使用VueJS进行描述。 jQuery和VueJS之间有根本的区别。

  1. jQuery操作dom
  2. VueJS使用虚拟dom

虚拟dom具有与真实dom相同的属性,但是必须更快,因为它不会在屏幕上绘制任何内容。然后将其与真实dom进行比较,并根据更改内容进行更新。

当您不断操纵dom并重新绘制网站时,速度会变慢,并且保持网站状态会很棘手。这就是VueJS使用带有道具和事件的组件的原因。

因此,Vue使dom对数据更改做出反应,而不是编辑html元素本身。

Vue通过ref属性直接操作dom的能力确实有限,但是建议尽可能避免使用它。

“重要方式”是使用单个文件组件来创建您的网站。请参阅:https://vuejs.org/v2/guide/single-file-components.html以及mixins和指令。

这意味着网站上每个“事物”都有一个组成部分,例如<MyButton><NavigationBar>等。

如果一切都以这种方式设置,则只需更改单个文件中的模板或样式,网站上的每个<MyButton>都会更改。您永远都不会像jquery那样操纵dom来即时更改它。

尽管这不是“干净的”,但没有什么可以阻止您将vuejs和jquery结合在一起。因此,vuejs将使用虚拟dom,更新实际dom,然后由jquery对其进行操作。

由于存在一些“魔术事件”和两个影响网站外观的框架,因此很难跟踪状态。例如在vue中进行一些样式设置,然后jquery覆盖或更改它。

答案 6 :(得分:0)

自2015年以来,我就一直使用Vue构建应用程序和网站,在那之前,我多年来一直是大量的jQuery用户。在查看了其他答案和您的回答后,我认为您所寻求的答案实际上与Vue没有关系。

我的第一个想法是像其他人提到的“指令”。

您似乎想要使用jQuery时曾经使用过的语法来选择DOM元素并以链式方式应用更改;这可以使用香草JavaScript来完成。您面临的挑战是在Vue中工作并等待组件完成渲染,然后再尝试选择所有可能的DOM节点。有一些技巧,例如使用<div id="container"> Before parent <div id="parent"> <div id="child1"> Child 1 should be in the background. </div> <div id="child2"> Child 2 should be in the foreground.<br> It covers Child 1 (overlay).<br> It is larger than Child 1. </div> Parent should grow to contain both children. </div> After parent </div>等待子组件完成渲染,然后再尝试选择所有可能的DOM节点。

我可以说我不再需要或不想使用jQuery,并且还没有遇到需要$nextTick()之类的用例。

如果您可以分享有关正在尝试实现的目标的更多信息,则可能会给出更明确的答案。我确实相信这里有一个简单的解决方案,但是如果不了解您的挑战,就很难回答。

答案 7 :(得分:-1)

Vuetify,如果有帮助的话。我会用CSS甚至更少的代码来做,看看标题在生成的HTML中是如何表示的。例如,如果它是名为v-title的属性,则CSS规则为

[v-title] {
    /*Your rules here*/
}

将应用于具有该属性的元素。您可以更改它,例如

h1[v-title] {
    /*Your rules here*/
}

将应用于具有该属性的h1元素。或者,

div > [v-title] {
    /*Your rules here*/
}

将适用于具有该属性的任何元素,只要其父元素为div。但是,如果您需要第三方设计,则可以找到它,例如:https://vuetifyjs.com/en/components/subheaders/

除非您被迫不这样做,否则我建议您实施自己的设计,因为自定义第三方设计有其局限性。