百科狗-知识改变命运!
--

自定义指令 - 对底层 DOM 访问 - vue 组件复用

乐乐12个月前 (11-21)阅读数 9#技术干货
文章标签指令

自定义指令

除了 Vue 内置的一系列指令(比如v-modelv-show)之外,Vue 还允许你注册自定义的指令。

我们已经介绍了两种在 Vue 中重用代码的方式:组件和组合式函数。组件是主要的构建模块,而组合式函数则侧重于有状态的逻辑。另一方面,自定义指令主要是为了重用涉及普通元素的对底层 DOM 访问的逻辑

一个自定义指令由一个包含类似组件生命周期钩子的对象来定义。指令钩子函数,以所绑定元素作为其参数。

下面是一个自定义指令的例子,当一个input元素被 Vue 插入到 DOM 中后,它会被自动聚焦:

 

假设你还未点击页面中的其他地方,那么上面这个input元素则会被自动聚焦。该指令比autofocus attribute 更有用,因为它不仅仅可以在页面加载完成后运行,还可以在 Vue 动态插入元素后运行。

将一个自定义指令全局注册到应用层级也是一种常见的做法:

const app = createApp({})

// 使 v-focus 在所有组件中都可用
app.directive('focus', {
  /* ... */
})


只有当所需功能只能通过直接的 DOM 操作来实现时,才应该使用自定义指令。其他情况下应该尽可能地使用v-bind这样的内置指令来声明式地使用模板,这样更高效,也对服务端渲染更友好。



指令钩子

一个指令的定义对象可以提供几种钩子函数(都是可选的):

const myDirective = {

  // 在绑定元素的 attribute 前调用
  // 或事件监听器应用前调用
  created(el, binding, vnode, prevVnode) {},

  // 在元素被插入到 DOM 前调用
  beforeMount(el, binding, vnode, prevVnode) {},

  // 在绑定元素的父组件及他自己的所有子节点都 挂载 完成后调用
  mounted(el, binding, vnode, prevVnode) {},

  // 绑定元素的父组件更新前调用
  beforeUpdate(el, binding, vnode, prevVnode) {},

  // 在绑定元素的父组件 及他自己的所有子节点都 更新 完成后调用
  updated(el, binding, vnode, prevVnode) {},

  // 绑定元素的父组件卸载之前调用
  beforeUnmount(el, binding, vnode, prevVnode) {},

  // 绑定元素的父组件卸载之后调用
  unmounted(el, binding, vnode, prevVnode) {}
  }
}


钩子参数

指令的钩子会传递以下几种参数:

  • el:指令绑定到的元素。这可以用于直接操作 DOM。
  • binding:一个对象,包含以下属性
    • value:传递给指令的值。例如v-my-directive="1 + 1"之中,值就是2。
    • oldValue:之前的值,仅在beforeUpdateupdated中可用。无论值是否更改,它都可用。
    • arg:传递给指令的参数,例如v-my-directive:foo之中,参数就是foo。
    • modifiers:一个对象,包含使用到的所有修饰符。例如v-my-directive.foo.bar之中,修饰符对象会是{foo: true, bar: true}。
    • instance:使用该指令的组件实例。
    • dir:指令定义对象
  • vnode:代表绑定元素的底层 VNode。
  • prevNode:之前的渲染中代表指令所绑定元素的 VNode。仅在beforeUpdateupdated钩子中可用。

举个例子,像下面这样使用指令:

binding参数会是一个这样的对象:

{
  arg: 'foo',
  modifiers: { baz: true },
  value: /* `baz` 的值 */,
  oldValue: /* 上一次更新时 `baz` 的值 */
}

自定义指令 - 对底层 DOM 访问 - vue 组件复用


和内置指令类似,自定义指令的参数也可以是动态的,举个例子:

这里指令的参数,会基于组件状态arg属性,响应式地更新。


除了el外,你应该将这些参数都视为只读的,并一律不更改它们。若你需要在不同的钩子间共享信息,推荐方法是通过元素的dataset attribute。


例如你想要创建一个自定义指令,用来通过固定布局将元素固定在页面上。我们可以创建一个自定义指令,它的值以像素为单位更新被固定元素的位置,把该元素固定在距离页面顶部或者左侧 200 像素的位置。这时使用动态参数就可以非常方便地根据每个组件实例来进行更新。

Scroll down inside this section ↓

I am pinned onto the page at 200px to the left.

app.directive('pin', {
  mounted(el, binding) {
    el.style.position = 'fixed'
    // binding.arg 是我们传递给指令的参数
    const s = binding.arg || 'top'
    el.style[s] = binding.value + 'px'
  }
})



简化形式

对于自定义指令来说,mountedupdated需要相同的行为、又并不关心其他钩子的情况很常见。这种情况下我们可以直接用一个函数来定义指令:

template
js
app.directive('color', (el, binding) => {
  // 这会在 `mounted` 和 `updated` 时都调用
  el.style.color = binding.value
})


对象字面量

如果你的指令需要多个值,你可以向它传递一个 JavaScript 对象字面量。请记住,指令也可以接收任何合法的 JavaScript 表达式

template
js
app.directive('demo', (el, binding)=> {
  console.log(binding.value.color)  // => "白色"
  console.log(binding.value.text)   // => "你好!"
})


在组件上使用

当在组件上使用自定义指令时,它会始终应用于组件的根节点,和透传 attributes 类似。

我的组件内容

如果组件可能含有多个根节点,应用于组件上的指令不会起效,会被忽略,还会抛出一个警告。和 attribute 不同,指令不可以通过v-bind="$attrs"来传递给一个不同的元素。总而言之,不推荐在组件上使用自定义指令

鹏仔微信 15129739599 鹏仔QQ344225443 鹏仔前端 pjxi.com 共享博客 sharedbk.com

免责声明:我们致力于保护作者版权,注重分享,当前被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理!邮箱:344225443@qq.com)

图片声明:本站部分配图来自网络。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

内容声明:本文中引用的各种信息及资料(包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主体(包括但不限于公司、媒体、协会等机构)的官方网站或公开发表的信息。部分内容参考包括:(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供参考使用,不准确地方联系删除处理!本站为非盈利性质站点,本着为中国教育事业出一份力,发布内容不收取任何费用也不接任何广告!)