vue 自定义指令 为什么可以拿到真实dom参数啊 他不是还在虚拟dom吗
在 Vue 中,自定义指令的 bind
、inserted
、update
和 componentUpdated
四个钩子函数中,第一个参数 el
表示指令所绑定的元素,它是真实的 DOM 元素,而不是虚拟 DOM。当 Vue 编译模板时,会将模板转换为虚拟 DOM,然后通过虚拟 DOM 更新真实 DOM,这个过程中会执行自定义指令的钩子函数。
在自定义指令的钩子函数中,可以通过 el
参数访问到真实的 DOM 元素,因为 Vue 在执行钩子函数时已经将虚拟 DOM 转换为真实 DOM 并插入到页面中。所以,自定义指令可以拿到真实 DOM 参数。
在 Vue 中,虚拟 DOM 是用来描述真实 DOM 的一种数据结构,每个虚拟 DOM 节点都有对应的真实 DOM 节点,而且在渲染过程中,Vue 会将虚拟 DOM 转换成真实 DOM 并插入到页面中
在自定义指令中,通过钩子函数 bind、inserted、update、componentUpdated、unbind 可以访问到真实 DOM,这是因为在这些钩子函数执行时,Vue 已经将虚拟 DOM 转换成了真实 DOM 并插入到页面中
在 bind 钩子函数中,可以通过参数 el 获取到真实 DOM 元素,而在 update 钩子函数中,可以通过参数 el 和 vnode 获取到更新后的真实 DOM 元素和虚拟 DOM 节点
总结来说自定义指令中的钩子函数是在虚拟 DOM 中执行的,但是在执行过程中,Vue 已经将虚拟 DOM 转换成了真实 DOM 并插入到页面中,因此可以访问到真实 DOM 参数
// 判断用户是否 传入了render , 没传入时,可能传入了template。template没有传入时候,就拿最外面的 <div id="#app"></div>作为模板
// 将我们的html -> 词法解析 (开始标签 , 结束标签,属性,文本)
// ast语法树 用来描述html语法的 stack = []
// codegen <div>hello</div> -> _c('div',{},'hello') -> 让字符串解析 _c创建元素
// 方式:
// 使用方式 01:模板引擎 new Function + with 来实现 -> render函数
// + 02:字符串解析转化为代码后 eval 好性能 会有作用域问题 -> 不使用
// 之后生成虚拟dom
对于自定义指令来说,可以通过钩子函数来获取到真实的DOM参数。在自定义指令定义时,可以用bind、inserted、update、componentUpdated和unbind这几个钩子函数来完成相应的操作。其中, bind:只会执行一次,在指令第一次绑定到元素上时执行,该钩子函数可以接收到el、binding参数。 inserted:只会执行一次,在被绑定元素插入父节点时执行,该钩子函数可以接收到el、binding、vnode、oldVnode参数。 update:在指令所在元素上发生任何更新时执行,但是可能发生在子组件的更新之前。该钩子函数可以接收到el、binding、vnode、oldVnode参数。 componentUpdated:在指令所在元素及其子元素全部更新后执行。该钩子函数可以接收到el、binding、vnode、oldVnode参数。 unbind:只会执行一次,在指令解绑时执行,该钩子函数可以接收到el、binding参数。 在这些钩子函数中,除了bind之外,其他函数中的el参数都代表指令所在的DOM元素,可以通过该参数获取到真实的DOM参数。可以使用vue提供的$refs属性或getElementById、getElementsByClassName、getElementsByTagName等方法来获取指定的DOM元素,然后在钩子函数中进行操作。示例代码如下:
Vue.directive('myDirective', {
bind: function(el, binding) {
// el代表指令所在的DOM元素,通过该参数可以获取到真实的DOM元素
console.log(el.tagName); // 获取元素标签名
console.log(el.getAttribute('id')); // 获取元素id属性
// 可以使用vue提供的$refs属性或getElementById、getElementsByClassName、getElementsByTagName等方法来获取指定的DOM元素
console.log(this.$refs.myElement); // 获取ref为myElement的元素
// binding包含了指令和绑定的值
console.log(binding.name); // 获取指令名称
console.log(binding.value); // 获取绑定的值
},
inserted: function(el) {
// el代表指令所在的DOM元素,通过该参数可以获取到真实的DOM元素
console.log(el.tagName); // 获取元素标签名
// 可以使用vue提供的$refs属性或getElementById、getElementsByClassName、getElementsByTagName等方法来获取指定的DOM元素
console.log(this.$refs.myElement); // 获取ref为myElement的元素
},
update: function(el) {
// el代表指令所在的DOM元素,通过该参数可以获取到真实的DOM元素
console.log(el.tagName); // 获取元素标签名
// 可以使用vue提供的$refs属性或getElementById、getElementsByClassName、getElementsByTagName等方法来获取指定的DOM元素
console.log(this.$refs.myElement); // 获取ref为myElement的元素
},
componentUpdated: function(el) {
// el代表指令所在的DOM元素,通过该参数可以获取到真实的DOM元素
console.log(el.tagName); // 获取元素标签名
// 可以使用vue提供的$refs属性或getElementById、getElementsByClassName、getElementsByTagName等方法来获取指定的DOM元素
console.log(this.$refs.myElement); // 获取ref为myElement的元素
},
unbind: function(el) {
// el代表指令所在的DOM元素,通过该参数可以获取到真实的DOM元素
console.log(el.tagName); // 获取元素标签名
// 可以使用vue提供的$refs属性或getElementById、getElementsByClassName、getElementsByTagName等方法来获取指定的DOM元素
console.log(this.$refs.myElement); // 获取ref为myElement的元素
}
});