DOM文档 获取dom节点 ,使用document对象 通过函数来获取函数 利用循环来获取数据

这篇博客主要介绍了如何使用JavaScript中的document对象来获取DOM节点,包括html、body和head标签。此外,还详细讲解了通过firstElementChild、lastElementChild、nextElementSibling和previousElementSibling属性来获取和遍历元素。同时,通过getElementById、getElementsByClassName、getElementsByName和getElementsByTagName方法获取指定属性的元素,并展示了querySelector和querySelectorAll在获取多个元素时的应用。

 获取dom节点 ,使用document对象

// 获取DOM节点 使用的是document对象
        console.log(document.documentElement) //文档种所有的标签  html
        console.log(document.body) //获取文档中 body中的标签
        console.log(document.head) //获取文档中head中的标签

        // 获取
        var body = document.body
        var div1 = body.firstElementChild  //获取第一个元素
        var div2 = body.lastElementChild  //获取最后一个元素
        console.log(body.firstElementChild) //获取到的是body 的第一个元素
        console.log(body.firstChild) //获取到body 里面第一个元素的全部内容 (包括空格换行)
        console.log(body.lastElementChild) //获取到了body 最后一个标签的内容
        console.log(div1.nextElementSibling) //获取到div下面第一个相邻兄弟元素的下一个
        console.log(div2.previousElementSibling) //获取相邻兄弟元素的上一个

 通过函数来获取函数

 //通过函数来获取元素
        console.log(document.getElementById("div1")) // getElementById("div1") 获取元素的id
        console.log(document.getElementsByClassName("div2")) //获取的的 是 class 的值
        console.log(document.getElementsByName("sex")) //获取到的是属性name 的值
        console.log(document.getElementsByTagName("input")) //getElementsByTagName("input") 获取到标签名字

 利用循环来获取数据

console.log(document.querySelector("div")) //获取一个div
        console.log(document.querySelectorAll("div")) //获取全部的div 以数组的方式呈现
        //通过循环吧div输出
        var divs = document.querySelectorAll("div")
        for (let i = 0; i < divs.length; i++) {
            // const element = array[i];
            console.log(divs[i]) //获取标签里面的内容
        }

 

<think> 我们之前的问题是关于Swiper循环模式(loop: true)下,复制的slide中的子组件MultipleLineOmissions(用于多行文本省略)在复制后省略样式失效的问题。 现在,用户想通过document.querySelector获取DOM元素,然后触发该DOM里的函数来解决这个问题。 回顾: MultipleLineOmissions组件在mounted生命周期中实现了文本的省略功能(根据文本内容判断是否超过一行,超过则应用省略样式)。但在Swiper的循环模式下,由于是复制节点,可能复制时组件的mounted生命周期没有再次执行(因为Vue组件不会为复制的节点重新创建组件实例),所以省略样式没有应用。 因此,我们需要在复制的节点上也执行一次MultipleLineOmissions组件的省略逻辑。 思路: 1. 获取到所有复制的slide(Swiper会为复制的slide添加特定类名,如'swiper-slide-duplicate')中的MultipleLineOmissions组件对应的DOM元素。 2. 然后调用这些元素上挂载的省略函数(假设这个函数是MultipleLineOmissions组件内部的一个方法,比如叫做`applyOmission`)。 但是,这里有几个关键点: - 如何访问到组件内部的方法?通常,我们不会将组件内部方法暴露在DOM元素上。 - 如果组件内部方法没有直接暴露,我们可以考虑通过Vue组件实例来调用?但是复制的节点不是Vue组件实例,而是纯DOM节点。 因此,我们需要调整MultipleLineOmissions组件的实现,使其省略逻辑可以通过某种方式在外部触发,或者将省略逻辑写成公共方法绑定在DOM元素上(例如,在mounted中不仅执行一次,而且将这个函数绑定在DOM元素上,以便后续调用)。 步骤建议: 步骤1:修改MultipleLineOmissions组件,使其在mounted时将省略函数绑定到DOM元素上(例如,使用自定义属性或直接挂载到DOM对象上)。 例如,在MultipleLineOmissions组件的mounted中: this.$el.applyOmission = this.applyOmission; // 假设组件内部有一个applyOmission方法 步骤2:在Swiper初始化后,我们通过document.querySelectorAll选择所有复制的slide中的MultipleLineOmissions组件的根DOM元素,然后调用它们的applyOmission方法。 但是,注意:复制的slide是纯DOM克隆,不会执行Vue组件的生命周期,所以我们需要在Swiper初始化完成后,手动触发这些复制节点的省略函数。 具体代码实现: 1. 修改MultipleLineOmissions组件: 在组件的mounted钩子中,将省略方法绑定到组件的根元素上。 ```javascript // MultipleLineOmissions.vue export default { mounted() { this.applyOmission(); // 将方法绑定到DOM元素上,以便外部访问 this.$el.applyOmission = this.applyOmission.bind(this); }, methods: { applyOmission() { // 这里是省略逻辑 // 例如:根据文本内容设置样式 } } } ``` 2. 在Swiper初始化后,找到所有复制的slide中的MultipleLineOmissions组件的根元素,调用applyOmission方法。 ```javascript // 创建Swiper实例 const swiper = new Swiper('.swiper-container', { loop: true, // 其他配置... on: { init: function () { // Swiper初始化完成后执行 setTimeout(() => { // 获取所有复制的slide const duplicateSlides = document.querySelectorAll('.swiper-slide-duplicate'); duplicateSlides.forEach(slide => { // 在复制的slide中查找MultipleLineOmissions组件的根元素 const omissionEl = slide.querySelector('.multiple-line-omission'); // 假设组件根元素有一个类名'multiple-line-omission' if (omissionEl && omissionEl.applyOmission) { omissionEl.applyOmission(); } }); }, 0); } } }); ``` 注意:这里使用setTimeout是为了确保DOM已经渲染完成。 但是,这种方法依赖于在DOM元素上绑定方法,可能不是最佳实践(因为直接操作DOM和绑定方法到DOM上可能会引起内存泄漏或冲突)。另一种更Vue的方式是使用Vue的ref,但复制的节点不是Vue实例,所以无法通过ref获取组件实例。 因此,如果不想在DOM上绑定方法,我们可以将省略逻辑提取为独立的函数,然后在组件的mounted中调用,同时也在需要的地方直接调用该函数(但需要传入DOM元素)。但是这样需要修改组件的实现,将内部逻辑暴露为纯函数。 另一种思路:使用事件。在组件的mounted中触发一个自定义事件,然后在父组件中监听这个事件保存这些组件的引用。但是复制的节点不会触发mounted,所以此路不通。 所以,我们采用上述在DOM元素上绑定方法的方式,注意在组件销毁时解除绑定(避免内存泄漏): 在MultipleLineOmissions组件的beforeDestroy钩子中: delete this.$el.applyOmission; 但是,复制的节点不是Vue组件,所以不会触发销毁钩子。因此,我们只需要在原始组件的销毁钩子中解除绑定,而复制的节点在Swiper销毁时会被Swiper自动清理。 另外,Swiper在滑动时可能会动态添加/删除slide(例如slidesPerView:'auto'),因此我们还需要在Swiper的slideChange事件中检查触发复制节点的省略逻辑?但是这样可能会频繁触发。考虑到复制节点只在初始化时创建,所以只在init事件中处理应该足够。 总结步骤: 1. 修改MultipleLineOmissions组件,在mounted时将applyOmission方法绑定到组件的根DOM元素上,在组件销毁前删除。 2. 在Swiper的init回调中,使用document.querySelectorAll获取所有复制slide中的组件根元素,调用绑定的applyOmission方法。 代码示例: MultipleLineOmissions.vue: ```vue <template> <div class="multiple-line-omission" ref="container"> <!-- 省略内容 --> </div> </template> <script> export default { mounted() { this.applyOmission(); // 绑定到DOM元素 this.$el.applyOmission = this.applyOmission.bind(this); }, beforeDestroy() { // 销毁时解除绑定 delete this.$el.applyOmission; }, methods: { applyOmission() { // 省略逻辑,例如: const el = this.$refs.container; // 计算文本是否超出,然后设置样式 } } } </script> ``` 在Swiper初始化中: ```javascript new Swiper('.swiper-container', { loop: true, on: { init: function() { // 注意:Swiper初始化时可能还未将复制节点插入DOM,所以使用setTimeout确保 setTimeout(() => { document.querySelectorAll('.swiper-slide-duplicate .multiple-line-omission').forEach(el => { if (el.applyOmission) { el.applyOmission(); } }); }, 0); } } }); ``` 注意:如果复制节点在Swiper初始化后动态添加(例如在responsive下改变slidesPerView),则需要在Swiper的update事件中也执行上述逻辑。 另外,如果MultipleLineOmissions组件在复制的slide中可能有多个,则上述代码中的选择器`.swiper-slide-duplicate .multiple-line-omission`会选中所有。 最后,如果用户使用的是Vue,且Swiper的slide内容是动态生成的,可能需要考虑在数据更新后重新触发省略逻辑,这时可以结合使用Vue的nextTick和Swiper的update。 但是,根据用户描述,问题仅在循环模式下复制的节点出现,所以上述方法应该足够。 因此,回答用户的问题:通过document.querySelector获取DOM后,如何触发该DOM里的函数? 答案:首先确保该DOM元素上已经绑定了我们需要的函数(如上面在组件的mounted中绑定的applyOmission),然后直接调用即可,如:`domElement.applyOmission()`。 但是要注意,如果组件没有绑定这个方法,那么调用就会失败。所以关键在于如何绑定。 如果用户不能修改MultipleLineOmissions组件(比如是第三方组件),那么可能需要寻找其他方式,例如通过组件内部使用的类名或样式来手动应用省略样式?这可能会很复杂。 因此,最佳方案是能够修改MultipleLineOmissions组件,使其支持外部触发。 另外,如果用户使用Vue3,可以使用ref获取组件实例,但是复制的节点不是由Vue创建的,所以无法通过ref获取。因此,我们仍然推荐上述方法。 总结步骤: 1. 修改子组件,在mounted时将省略方法绑定到其根DOM元素上。 2. 在Swiper初始化后,通过document.querySelectorAll选择复制的slide中的这些DOM元素,调用绑定的方法。 注意:选择器的使用,要能够精确找到这些元素。 最后,提供完整的代码示例。 如果用户无法修改子组件,那么可能需要考虑其他hack方法,例如重新计算样式,但不如直接触发子组件的省略函数可靠。 相关问题: 1. 如何避免在DOM元素上绑定方法导致的内存泄漏? 2. Swiper在动态添加slide时如何保证省略样式生效? 3. 如何为动态加载的内容应用多行省略? </think> 针对通过 `document.querySelector` 获取 DOM 后触发组件内部函数解决 Swiper 循环模式下的文本省略问题,以下是完整的解决方案: ### 解决方案步骤 1. **在组件中暴露公共方法** 在 `MultipleLineOmissions` 组件中暴露一个可调用的更新方法: ```javascript // MultipleLineOmissions.vue export default { methods: { // 暴露给外部调用的更新方法 updateEllipsis() { this.calculateEllipsis(); // 调用原有的省略计算逻辑 }, calculateEllipsis() { // 原有的省略计算逻辑 const el = this.$el; if (el.scrollHeight > el.clientHeight) { el.classList.add('ellipsis-active'); } else { el.classList.remove('ellipsis-active'); } } }, mounted() { this.calculateEllipsis(); } } ``` 2. **通过 DOM 获取组件实例** 在父组件中通过 `ref` 获取组件实例: ```javascript // Swiper父组件 <template> <swiper :loop="true"> <swiper-slide v-for="(item, index) in items" :key="index"> <MultipleLineOmissions ref="omissionRefs" :text="item.text"/> </swiper-slide> </swiper> </template> ``` 3. **在 Swiper 初始化后触发更新** ```javascript const swiper = new Swiper('.swiper', { loop: true, on: { init: function() { // 1. 获取所有组件实例 const components = this.$refs.omissionRefs; // 2. 获取复制的DOM节点 const duplicatedSlides = document.querySelectorAll( '.swiper-slide-duplicate .multiple-line-omission' ); // 3. 对复制节点触发更新 duplicatedSlides.forEach(slide => { const component = components.find(comp => comp.$el === slide ); if (component) { component.updateEllipsis(); // 调用组件方法 } }); } } }); ``` ### 特殊场景处理 **当无法直接获取组件实例时**(如动态生成的组件): ```javascript // 通过自定义事件触发更新 duplicatedSlides.forEach(slide => { const event = new CustomEvent('updateEllipsis'); slide.dispatchEvent(event); }); // 在组件内部监听事件 mounted() { this.$el.addEventListener('updateEllipsis', this.calculateEllipsis); }, beforeDestroy() { this.$el.removeEventListener('updateEllipsis', this.calculateEllipsis); } ``` ### 通用优化建议 1. **添加重排触发**(解决布局计算问题): ```javascript component.updateEllipsis(); // 强制重排 slide.style.display = 'none'; slide.offsetHeight; // 触发重排 slide.style.display = ''; ``` 2. **响应式处理**(窗口大小变化时): ```javascript window.addEventListener('resize', () => { document.querySelectorAll('.multiple-line-omission').forEach(el => { el.dispatchEvent(new CustomEvent('updateEllipsis')); }); }); ``` 3. **Swiper 特定事件处理**: ```javascript swiper.on('slideChange', () => { swiper.$el.querySelectorAll('.swiper-slide-active .multiple-line-omission') .forEach(el => { el.dispatchEvent(new CustomEvent('updateEllipsis')); }); }); ``` ### 完整示例代码 ```javascript // 初始化Swiper后执行 const initEllipsis = () => { const omissionEls = document.querySelectorAll('.multiple-line-omission'); omissionEls.forEach(el => { // 1. 直接检查是否需要省略 if (el.scrollHeight > el.clientHeight) { el.classList.add('ellipsis-active'); } // 2. 通过组件实例更新 if (el.__vue__) { el.__vue__.updateEllipsis(); } // 3. 通过事件触发更新 el.dispatchEvent(new CustomEvent('triggerEllipsis')); }); }; new Swiper('.swiper', { loop: true, on: { init: initEllipsis, resize: initEllipsis } }); ``` ### 注意事项 1. 使用 `__vue__` 属性可直接访问 Vue 组件实例(仅开发环境稳定) 2. 生产环境建议使用 `ref` 或自定义事件 3. 循环模式下克隆节点不会触发 Vue 生命周期钩子 4. 使用 `observer: true` 配置可响应 DOM 变化: ```javascript new Swiper('.swiper', { loop: true, observer: true, observeSlideChildren: true }); ``` ### 相关问题 1. 如何检测文本溢出的最佳方法是什么? 2. 在 Vue 中如何跨组件通信? 3. Swiper 循环模式下有哪些常见问题? 4. 如何优化频繁触发的重排操作? 5. 虚拟 DOM 和真实 DOM 操作的区别是什么? > 通过组合使用 DOM 查询、组件实例访问和自定义事件,可有效解决 Swiper 循环模式下的样式更新问题。建议优先使用 Vue 的 `ref` 机制,特殊场景下配合 DOM 操作作为补充[^1][^2][^3][^4
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值