当前位置: 首页 > wzjs >正文

学习做网站营销广告文案

学习做网站,营销广告文案,怎么做网站弹幕效果,网站建设电话咨询文章目录 前言一、原理说明二、注册与使用1. 全局注册2. 局部注册3. 使用方式 三、典型应用场景四、案例:权限控制指令五、注意事项 v-draggable✅ 目标效果:🧩 1. 自定义指令定义🧱 2. 在项目中注册🧪 3. 使用示例&am…

文章目录

  • 前言
      • 一、原理说明
      • 二、注册与使用
        • 1. 全局注册
        • 2. 局部注册
        • 3. 使用方式
      • 三、典型应用场景
      • 四、案例:权限控制指令
      • 五、注意事项
  • v-draggable
    • ✅ 目标效果:
    • 🧩 1. 自定义指令定义
    • 🧱 2. 在项目中注册
    • 🧪 3. 使用示例
    • 📝 说明:
    • ✅ 自定义指令的底层实现原理概览
    • 📦 相关核心函数 & 文件位置(Vue 3)
    • 🧩 源码分析:流程详解
      • ① 编译模板为虚拟节点时
      • ② `withDirectives()` 函数
      • ③ `mountElement()` 阶段:执行 mounted 钩子
      • ④ `invokeDirectiveHook()` 执行钩子
    • 🧠 自定义指令对象结构(本质)
    • ✅ 总结:Vue 3 自定义指令运行机制


前言

Vue 3 自定义指令(Custom Directives)是对 DOM 元素的底层操作进行封装的一种机制,适用于处理组件模板中难以通过普通属性或事件完成的逻辑,例如拖拽、自动聚焦、懒加载、权限控制等场景。


一、原理说明

Vue 3 中,自定义指令是通过组合式 API directive 函数注册的,本质上是对某个 DOM 元素生命周期钩子的扩展封装。底层由 Directive 对象描述,具备以下钩子函数:

const myDirective = {created(el, binding, vnode, prevVnode) {},    // 元素创建后调用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: 包含传递给指令的值、修饰符等
  • vnode: 虚拟节点
  • prevVnode: 之前的虚拟节点

二、注册与使用

1. 全局注册
const app = createApp(App)app.directive('focus', {mounted(el) {el.focus()}
})
2. 局部注册
export default {directives: {focus: {mounted(el) {el.focus()}}}
}
3. 使用方式
<input v-focus />

三、典型应用场景

场景描述
自动聚焦页面加载后 input 自动聚焦
拖拽指令实现元素的拖动行为
权限控制根据权限隐藏/禁用某些 DOM 元素
懒加载图片进入可视区域再加载
节流防抖限制用户频繁点击按钮的行为
动态样式绑定更底层地控制样式/类名,比如动画、transition 控制

四、案例:权限控制指令

app.directive('permission', {mounted(el, binding) {const userPermissions = ['read']if (!userPermissions.includes(binding.value)) {el.parentNode?.removeChild(el)}}
})
<button v-permission="'admin'">仅管理员可见</button>

五、注意事项

  1. 组件首选:大部分逻辑推荐使用组件封装,只有在需要直接操作 DOM 的时候才用指令。
  2. 指令副作用清理:在 unmounted 中做清理(如移除监听器、取消定时器)。
  3. 性能考虑:不要在 updated 中重复进行复杂操作。

v-draggable

我们以 拖拽指令 v-draggable 为例,讲解一个完整的 Vue 3 自定义指令应用。


✅ 目标效果:

使任意元素可拖动,按住鼠标左键拖动到任意位置。


🧩 1. 自定义指令定义

// directives/draggable.ts
import type { Directive } from 'vue'const draggable: Directive = {mounted(el) {el.style.position = 'absolute'el.style.cursor = 'move'let offsetX = 0let offsetY = 0const parent = el.offsetParent || document.bodyconst parentRect = parent.getBoundingClientRect()const onMouseDown = (e: MouseEvent) => {offsetX = e.clientX - el.offsetLeftoffsetY = e.clientY - el.offsetTopdocument.addEventListener('mousemove', onMouseMove)document.addEventListener('mouseup', onMouseUp)}const onMouseMove = (e: MouseEvent) => {let left = e.clientX - offsetXlet top = e.clientY - offsetY// ✅ 限制在父容器内const maxLeft = parent.clientWidth - el.offsetWidthconst maxTop = parent.clientHeight - el.offsetHeightleft = Math.max(0, Math.min(left, maxLeft))top = Math.max(0, Math.min(top, maxTop))el.style.left = `${left}px`el.style.top = `${top}px`}const onMouseUp = () => {// ✅ 自动吸附到左右边缘const left = el.offsetLeftconst center = parent.clientWidth / 2el.style.left = left < center ? '0px' : `${parent.clientWidth - el.offsetWidth}px`document.removeEventListener('mousemove', onMouseMove)document.removeEventListener('mouseup', onMouseUp)}el.addEventListener('mousedown', onMouseDown);(el as any)._onMouseDown = onMouseDown},unmounted(el) {el.removeEventListener('mousedown', (el as any)._onMouseDown)}
}export default draggable

🧱 2. 在项目中注册

// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import draggable from './directives/draggable'const app = createApp(App)
app.directive('draggable', draggable)
app.mount('#app')

🧪 3. 使用示例

<!-- App.vue -->
<template><divv-draggablestyle="width: 100px; height: 100px; background: #42b983;">拖我</div>
</template>

📝 说明:

  • el.style.position = 'absolute':让元素能够移动
  • 鼠标按下时,记录初始偏移;
  • 鼠标移动时更新 left/top
  • 鼠标松开时清除事件监听,避免内存泄漏。

功能实现方式
拖动mousedown + mousemove + mouseup
边界限制利用 parent.clientWidth/clientHeight 计算边界
自动吸附左右释放鼠标后判断是否靠近左/右边,设置 left

Vue 3 中自定义指令的源码实现,核心位于其 runtime-core 模块,具体流程在组件渲染和更新阶段处理指令钩子(createdmountedupdated 等)。我们来深入讲解其源码执行机制。


✅ 自定义指令的底层实现原理概览

自定义指令在 Vue 编译和渲染过程中分两阶段处理:

  1. 编译阶段(仅在模板编译时):

    • v-xxx 语法解析为 withDirectives() 包裹的 VNode。
  2. 运行时渲染阶段

    • 调用 withDirectives(),将指令对象和绑定信息附加到 vnode。
    • mountElementpatchElement 时,调用各个指令生命周期钩子。

📦 相关核心函数 & 文件位置(Vue 3)

功能函数名文件位置
将指令附加到 vnodewithDirectivesruntime-core/directives.ts
执行指令生命周期钩子invokeDirectiveHookruntime-core/renderer.ts
调用时机:挂载/更新mountElement, patchElementruntime-core/renderer.ts

🧩 源码分析:流程详解

① 编译模板为虚拟节点时

模板语法:

<div v-focus="true" />

会被编译为:

withDirectives(h('div'), [[focusDirective, true]
])

withDirectives() 函数

export function withDirectives(vnode: VNode, directives: DirectiveArguments): VNode {vnode.dirs = directivesreturn vnode
}

这里会把指令数组保存在 vnode 上,供后续 mount 或 patch 时处理。


mountElement() 阶段:执行 mounted 钩子

if (dirs) {invokeDirectiveHook(vnode, null, parentComponent, 'beforeMount')
}
patchProps(...) // 设置属性等if (dirs) {queuePostRenderEffect(() => {invokeDirectiveHook(vnode, null, parentComponent, 'mounted')}, parentSuspense)
}

invokeDirectiveHook() 执行钩子

function invokeDirectiveHook(vnode: VNode,prevVNode: VNode | null,instance: ComponentInternalInstance,name: DirectiveHookName
) {const dirs = vnode.dirs!for (let i = 0; i < dirs.length; i++) {const dir = dirs[i]const hook = dir[0][name]if (hook) {callWithAsyncErrorHandling(hook,instance,ErrorCodes.DIRECTIVE_HOOK,[vnode.el,dir[1],       // binding.valuevnode,prevVNode])}}
}

👆这个函数就是最终 真正调用你写的 mounted()updated() 等函数 的地方。


🧠 自定义指令对象结构(本质)

你注册的指令最终是以下结构:

[directive: {mounted,updated,...},value,         // binding.valuearg,           // binding.argmodifiers,     // binding.modifiersinstance       // component instance
]

✅ 总结:Vue 3 自定义指令运行机制

阶段关键点
编译阶段v-xxx 被转成 withDirectives() 包装
渲染阶段vnode.dirs 被附加到 VNode
挂载时invokeDirectiveHook(..., 'mounted') 被调用
更新时invokeDirectiveHook(..., 'updated') 被调用

在这里插入图片描述

模板编译:

Vue 编译 v-xxx 为 withDirectives(h(…), [directive]) 结构。

withDirectives:

将指令数组 dirs 附加到虚拟节点 vnode 上,供后续处理。

mountElement:

创建 DOM 元素时,如果发现 vnode.dirs 存在,就调度钩子(如 mounted)。

invokeDirectiveHook:

遍历所有绑定指令,调用你注册的生命周期函数(如 mounted()、updated())。

执行你写的钩子函数:

如 el.focus()、拖拽逻辑等,操作真实 DOM。

http://www.dtcms.com/wzjs/61566.html

相关文章:

  • 网站建设海外推广 香港今日头条军事新闻
  • 网站建设联系方式博客seo怎么做
  • wordpress怎么增加字段太原seo全网营销
  • 做技术支持的网站有推广网站的公司
  • 如何注册网络公司廊坊推广seo霸屏
  • 国家企业信用公示信息网官网北京seo关键词
  • 武汉网站建设dw027谷歌商店下载官方正版
  • 使用帝国备份王搬迁织梦网站百度收录方法
  • 登别的网站应怎么做企业危机公关
  • 怎样模仿别人的网站seo零基础视频教程
  • 文档流程做网站手游推广平台有哪些
  • 驾校网站模板自己怎样开网站
  • 哪个网站可以做片头百度广告一天多少钱
  • 网站建设怎么用长尾做标题营销型网站案例
  • 怎么自己编写网站网络营销比较成功的企业
  • 国外优质设计网站百度百科合作模式
  • 在线网站优化公司今日热榜官网
  • 企业网站搜索优化外包中国seo网站
  • 美容医疗手机网站模板抖音引流推广怎么做
  • 做b2b网站销售怎样让客户找上门互联网最赚钱的行业
  • 上海做高端网站搜客通
  • 实战营销型网站建设腾讯企点app下载安装
  • 东莞做网站系统百度爱采购平台官网
  • 进一步优化新冠肺炎疫情防控措施奉化seo页面优化外包
  • 给一个公司做网站维护聚名网官网
  • 帝国cms网站搬家百度指数需求图谱
  • 公司后缀的邮箱怎么申请东莞网站建设优化技术
  • 广东网络营销服务苏州网站关键字优化
  • 华为云网站备案流程百度统计api
  • 管理公司网站建设网络销售的好处和意义