web自动化测试入门篇06 —— 元素定位进阶技巧

news2024/12/23 13:54:42

在这里插入图片描述

 

在这里插入图片描述
😏作者简介:博主是一位测试管理者,同时也是一名对外企业兼职讲师。
📡主页地址:【Austin_zhai】
🙆目的与景愿:旨在于能帮助更多的测试行业人员提升软硬技能,分享行业相关最新信息。
💎声明:博主日常工作较为繁忙,文章会不定期更新,各类行业或职场问题欢迎大家私信,有空必回。

在这里插入图片描述

 
 

阅读目录

  • 1. 目的
  • 2. 定位简介
    • 2.1 CSS Selector定位
      • 2.1.1 选择器语法
      • 2.1.2 组合定位
    • 2.2 XPath定位
      • 2.2.1 相对路径定位
      • 2.2.2 相对路径的运算符运用
      • 2.2.3 轴
      • 2.2.4 函数
  • 3. 注意点
    • 3.1 CSS Selector的使用注意点
    • 3.2 XPath的使用注意点

1. 目的

  web自动化测试作为软件自动化测试领域中绕不过去的一个“香饽饽”,通常都会作为广大测试从业者的首选学习对象,相较于C/S架构的自动化来说,B/S有着其无法忽视的诸多优势,从行业发展趋、研发模式特点、测试工具支持,其整体的完整生态已经远远超过了C/S架构方面的测试价值。

  我们上一次介绍了基于配置文件方式的元素管理的方法,接下去博主会就一些元素的高级定位方法来做一个较为全面的讲解。这些高级定位技巧虽然不会在日常的工作中高频出现,但在一些基础定位方法无法见效的场景中却往往会达到意想不到的效果。

 
 

2. 定位简介

  上几期中介绍到的常用元素定位方式这里就不在展开篇幅进行赘述了,其实在我们日常的web自动化测试的脚本设计过程中,常常会碰到因为代码规范或开发同学个人的习惯,导致web页面中的元素某些属性值重复或缺失的现象出现,此时再用ID、CLASSNAME等常用的元素定位方法往往就会定位不到你想要的元素。那么我们这期就着重介绍一下CSS Selector与XPath这两种定位方法。

 

2.1 CSS Selector定位

  CSS Selector虽然也是较为常用的定位方式,但其出镜率远远不如ID、Class Name等定位。作为元素定位的基准来说,我们的选取准则仍然是唯一性、可读性、维护性这三兄弟,所以当普通定位方式失效之后,我们会优先选择CSS Selector,之后才是XPath。

  CSS Selector是通过HTML 元素的 class、id、标签名、属性等来定位元素,同时也正因此特性,该定位方式就具有很高的灵活性与可读性,精准度也较高。另外也正是由于其可读性精准度高,在执行测试脚本时其执行速度也是较为快速。

2.1.1 选择器语法

  相较于其他的单一定位方式,CSS Selector本身涵盖有以下这些基本语法,这个也是我们后期进行组合定位的重要基础与依据。

标签选择器 —— 选择特定标签类型的元素。EX:div
类选择器 —— 选择具有特定类名的元素。EX:.class (.表示选择类)
ID选择器 —— 选择具有特定ID的元素。EX:#id (#表示选择ID)
属性选择器 —— 选择具有特定属性的元素。EX:[attribute=value]
子选择器 —— 选择某个元素的直接子元素。EX:parent > child
后代选择器 —— 选择某个元素的后代元素。EX:ancestor descendant

2.1.2 组合定位

  当我们掌握了以上这些选择器的全部用法之后,那么在我们设计脚本的过程中运用灵活的组合方式来进行高进度的元素定位。

 

【标签+类】

比如我们可以组合标签名与类名两个属性,这里我们的HTML代码为:

<div class="SignFlow-tab" role="button" tabindex="0">登录</div>

 
我们使用【标签+类】的组合方式来进行元素定位

driver.find_element(By.CSS_SELECTOR, "div.SignFlow-tab")

 

【标签+属性】

举例如下HTML代码:

<link data-rh="true" rel="apple-touch-icon" href="https://static.xxx.com/icon-eac.png" sizes="60x60">

 
我们使用【标签+属性】的组合方式来进行元素定位

driver.find_element(By.CSS_SELECTOR, "link[href]")

 

【类+属性】

举例如下HTML代码:

<input name="digits" type="number" class="Input i7cW1UcwT6ThdhTakqFm" placeholder="输入六位短信验证码" value="">

 
我们使用【类+属性】的组合方式来进行元素定位
这里需要注意的是,这个input元素拥有多个属性,这边是查找了三个属性以做到尽量的定位精准为目的,如果只抽取任意两个或多个组合都是可以的。

driver.find_element(By.CSS_SELECTOR, "input.Input.i7cW1UcwT6ThdhTakqFm[name=digits]")

 

【后代+类】

示例代码如下:

<div class="SignFlow-tabs">
  <span class="SignFlow-tab" role="button" tabindex="0">密码登录</span>
  <span class="SignFlow-tab" role="button" tabindex="-1">短信登录</span>
</div>

 
我们使用【后代+类】的组合方式来进行元素定位
这里需要说明一下的是,在html中一个元素被另一个元素所包含,就类似于上面的这段html代码,最外层的div元素是父元素,span元素就是子元素,这个相信应该很好理解。而后代选择器是可以指定父元素中的任意子元素的,也就是说这个选择器可以选择div元素下所有具有SignFlow-tab类属性的span子元素。另外就是无论这些span子元素是否直接作为子元素,或者嵌套在更深层次的子元素中,都是可以被后代选择器指定的。

driver.find_element(By.CSS_SELECTOR, "div.SignFlow-tabs span.SignFlow-tab")

 

【子+类】

示例代码如下:

<div class="SignFlow-tabs">
  <span class="SignFlow-tab" role="button" tabindex="0">密码登录</span>
  <span role="button" tabindex="-1">
    <span class="SignFlow-tab">短信登录</span>
  </span>
</div>

 
我们使用【子+类】的组合方式来进行元素定位
对于前面介绍的后代选择器来说,子选择器和其的区别在于:子选择器只会选择直接子元素,而后代选择器则可以选择所有子孙元素。写法也需要区别开,子选择器使用“>”,而后代选择器使用空格。

driver.find_element(By.CSS_SELECTOR, "div.SignFlow-tabs > span.SignFlow-tab")

 
 

2.2 XPath定位

  XPath定位可以说是广大测开同学的最后一根救命稻草,所有搞不定的元素定位都可以用该定位方式来达成,当然其中也存在着很多风险在其中,最粗暴也最不可取的方式就是直接复制XPath的绝对路径来进行定位,取值晦涩难懂不说,维护性也几乎不存在。那么我该如何用好XPath定位这个最终手段呢?让我们接着往下看。

 

2.2.1 相对路径定位

  既然不我们不提倡使用绝对路径来进行XPath方式定位,那么相对路径自然就是其另一面的良好解决方案。在相对路径的定位方法中,我们则需要指定一些关键字和符号来构建路径,以实现准确定位。

以下是日常中我们经常会用到的一些路径定位关键字:

. 表示当前节点,即定位的起点
… 表示当前节点的父节点
// 表示从根节点开始查找元素,不考虑当前节点位置
@ 表示元素的属性

光说可能有点抽象,那我们就来看一个对应的例子:
某个HTML的源代码如下:

<html>
    <head>
        <title>UI自动化测试平台首页</title>
    </head>
    <body>
        <div id="ui_automation_t">
            <h1>这个是标题1</h1>
            <p>这个是测试信息</p>
        </div>
    </body>
</html>

 
如果我们要定位对应的<p>标签元素,那我们的XPath相对路径就可以这么写:

//div[@id='ui_automation_t']/p

这段相对路径该怎么理解呢?其实很简单,我们结合着上面相对路径的关键字来解读一下。首先 // 是从根节点开始查找,div则是查找下面的所有div元素,然后在所有的div元素中搜索id属性值为ui_automation_t的元素,最后在匹配到的结果中定位下面的所有p元素。相对路径定位的好处就是完全不用考虑结构变化会带来的元素路径变动影响,除非是元素本身发生了变化或是被取消了。

 

2.2.2 相对路径的运算符运用

  在XPath的相对路径定位中我们也可以使用运算符来进行对应属性的定位。很多的条件判断都可以用运算符来进行达成。

【等于】
很好理解,等于运算符用于匹配元素的属性值是否等于指定的值。

driver.find_element(By.XPATH, "//input[@name='discount']")

 

【包含】
contains() 函数用于匹配元素的属性值是否包含指定的字符串。

driver.find_element(By.XPATH, "//input[contains(@class, 'icon-title')]")

 

【与或】
and与or都属于逻辑运算符,可以用于连接多个表达式。

driver.find_element(By.XPATH, "//input[@name='discount' and @type='content']")

 

2.2.3 轴

  既然说到了XPath,就绕不过“轴”这个概念,说直白点它就是用来表示当前页面中节点一个大合集,掌握了轴的用法可以帮助我们快速的定位页面中的节点,在复杂的页面中,经常会有多层嵌套的的结构,我们可以跳过一些不相关的节点来直接定位到所需的节点(避免遍历),从而提升脚本的执行效率。

 

同样的,我们来看看轴相关的一些基础定义:

ancestor 轴 —— 选择当前节点的所有祖先节点
descendant 轴 —— 选择当前节点的所有子孙节点
parent 轴 —— 选择当前节点的父节点
child 轴 —— 选择当前节点的所有子节点
preceding-sibling 轴 —— 选择当前节点之前的所有兄弟节点
following-sibling 轴 —— 选择当前节点之后的所有兄弟节点
self 轴 —— 选择当前节点本身

 

【ancestor 轴】

例如有下面这样一个HTML代码:

<div class="k_interface">
  <div class="c_app">
    <span class="g_center"></span>
  </div>
</div>

如果我们想要定位span元素的祖先元素(parent)时,就可以使用ancestor 轴实现:

driver.find_element(By.XPATH, "//span[@class='g_center']/ancestor::div[@class='k_interface']")

上面的这个相对路径表达式用到了ancestor轴,ancestor表示在//span[@class=‘g_center’]的定位结果后使用该轴搜索其节点上的祖先元素,而该祖先的元素指定为div[@class=‘k_interface’]。但这里有一个地方需要注意的是,轴定位的结果都是一个节点的合集,所以我们定位的时候需要调用find_element方法,而千万不要用find_elements,如果要选择该节点中的所有的节点,我们可以使用ancestor-or-self轴来实现,用法同上,依然调用find_element且用ancestor-or-self关键字来替换掉ancestor即可。

 

【descendant 轴】

示例代码如下:

<div class="k_interface">
  <div class="c_app">
    <span>test_page</span>
  </div>
  <div class="c_app">
    <input id="text" placeholder="Enter your case">
  </div>
  <div class="g_center">
    <button>Submit</button>
  </div>
</div>

需要定位k_interface元素的后代元素时,就可以使用descendant轴实现:

driver.find_element(By.XPATH, "//div[@class='k_interface']//descendant::input[@id='text']")

如果需要查询与其相关的所有后代元素,使用通配符*代替:

driver.find_element(By.XPATH, "//div[@class='k_interface']//descendant::*")

上面的descendant轴中的后代元素与之前所的子元素区别也是类似的,可以获取到其父节点下所有间接与直接的任意后代元素。

 

【parent 轴】

示例代码如下:

<div class="k_interface">
  <p class="c_app">test_index</p>
</div>

查找某个元素的父元素,我们就可以使用parent轴来实现:

driver.find_element(By.XPATH, "//p[@class='c_app']/parent::div")

这里我们通过p元素的class属性c_app来获取其父元素div。同理需要进行复数获取的时候使用*代表即可。

 

【child 轴】

有如下一段代码:

<div class="k_interface">
  <div class="c_app">
    <span class="g_center">test_group_1</span>
  </div>
  <div class="c_app">
    <span class="g_center">test_group_2</span>
  </div>
</div>

如果我们要获取父元素下的第二级div元素下的test_group_2元素,就可以使用child轴。

driver.find_element(By.XPATH, "//div[@class='k_interface']/*[2]/*")

这里使用child轴来获取后,/*[2]/*代表的就是第二个div元素下的后代元素test_group_2。

 

【preceding-sibling 轴】

示例代码如下:

<ul>
  <li>Beijing</li>
  <li>Shanghai</li>
  <li class="selected">Guangzhou</li>
  <li>Nanjing</li>
  <li>Jinan</li>
</ul>

如果我们想要定位Beijing和Shanghai两个元素,就可以使用以下的路径表达式。

driver.find_element(By.XPATH, "//li[@class='selected']/preceding-sibling::li[position()<=2]")

代码中的//li[@class=‘selected’]会选择到Guangzhou这个元素,因为这里指定了class的属性,然后我们使用preceding-sibling轴选择该元素之前的所有同级元素,加之使用了li[position()<=2]的特定条件来筛选出前两个元素。

 

【following-sibling 轴】

还是同样的一套代码:

<ul>
  <li>Beijing</li>
  <li>Shanghai</li>
  <li class="selected">Guangzhou</li>
  <li>Nanjing</li>
  <li>Jinan</li>
</ul>

假如我们需要选中Nanjing与Jinan这两个元素,就可以使用以下的路径表达式。

driver.find_element(By.XPATH, "//li[@class='selected']/following-sibling::li")

同样的,//li[@class=‘selected’]不多解释,这里使用following-sibling轴来选择该元素之后的所有同级元素,因为这里选取了之后的所有元素,所以就不需要进行特定的位置条件筛选了,直接指定标签名即可。

 

【self 轴】

实例代码如下:

<div id="a_word">
  <p class="selected">The word is a.</p>
</div>

这里我们如果要选中p元素,直接使用self轴即可。

driver.find_element(By.XPATH, "//p[@class='selected']/self::node()")

上面的代码使用了self::node()表示当前选择的节点,但它和其他的轴特性不同,一般情况下我们直接使用.就可以了,没有必要大费周章。

 
 

2.2.4 函数

  上面的相对路径定位方法中我们可以看到一些关于函数的用法,比如position()<=2等,其实XPath定位方式是支持多种内置函数的,用好这些内置函数也可以帮助我们更加精准高效的定位到自己需要的元素。下面我们就来介绍一下,一些常用的内置函数。

 

starts-with()

这个函数用来匹配元素的属性值是否以指定的字符串开头。

driver.find_element(By.XPATH, "//input[starts-with(@id, 'ke')]")

如上代码,这里我们使用starts-with来匹配元素的id属性是否以ke开头。

 

contains()

这个函数用来检查元素中的文本内容是否包含指定的字符串。

driver.find_element(By.XPATH, "//div[contains(text(), 'fill')]")

这里我们使用contains来检查div元素的文本内容是否包含fill。

 

substring()

这个函数用于截取字符串中的指定部分内容。

driver.find_element(By.XPATH, "//span[substring(text(), 1, 3) = 'key']")

以上代码是将span元素进行截取,截取内容为前三个字符,这里的= 'key'是用来做结果比较的,查看截取的结果是否等于指定的字符内容。需要注意的是,匹配的起始数是1,而不像是下标中的从0开始计算。如果比较的结果不匹配,那么这个元素的查找结果仍然会抛出一个NoSuchElementException的异常。

 

count()

count函数用于获取指定元素的数量。

if driver.find_elements(By.XPATH, "count(//div[@class='advance']) > 1"):
    print("找到了符合条件的元素!")
else:
    print("没有找到符合条件的元素。")

这里我们直接使用count函数来对元素进行个数判断并返回对应的打印结果。

elements = driver.find_elements(By.XPATH, "count(//div[@class='my-class']) > 1")
if elements:
    print("元素个数大于 1")
else:
    print("元素个数小于等于 1")

判断方法随意,不过在使用count函数时,需要使用find_elements方法而不是find_element

 
 

3. 注意点

  以上就是CSS Selector与XPath的一些进阶元素定位技巧,那么在我们的日常工作中,有哪些需要注意的点呢?

 

3.1 CSS Selector的使用注意点

  1. 使用CSS Selector定位元素的时候尽量避免单独使用某个属性来定位,比如div标签这样的,页面中肯定存在多个,单独使用会导致定位到多个元素而无法特定下来导致报错;

  2. 如果没有十足的把握,尽量少用*通配符进行定位,往往匹配了某个节点的全部元素或某个指定特征的全部元素,这样的结果特别是在后期脚本运行或维护阶段特别的要命;

  3. 组合定位与选择器的语法一定要熟悉,什么时候用空格什么时候用特定符号要熟练,代码中的字符绝大部分都是英文,一旦用错了这些,排查起来这些字符与空格也会变得较为困难;

  4. 页面中也会存在一些动态生产的元素属性,这个很多做测开的同学都碰到过,我们一般都会用attribute来协助进行定位;

  5. 有些同学喜欢使用嵌套的形式在使用选择器,不是不行,但这样的编程形式会无形降低代码本身的可读性与提升后期维护成本,得不偿失;

 

3.2 XPath的使用注意点

  1. 不要使用绝对路径,不要使用绝对路径,不要使用绝对路径,重要的事情说三遍;

  2. 相对于元素较多或较为复杂结构的页面,使用相对路径并多结合轴、运算符、内置函数来提升表达式的精简与精准程度,提高代码的可读性;

  3. 一段较为繁琐的表达式,可以尝试将其拆解开进行表达,这个也是提高测试执行效率的技巧之一;

  4. 浏览器内开发者工具中的copy xpath可以看看,但做做参看就行,实用性讲真不高。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/440160.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

camunda的manual task节点用途

Camunda的Manual Task用于在流程中暂停执行&#xff0c;直到人工干预完成某个任务。与User Task不同&#xff0c;Manual Task没有分配给特定用户或用户组&#xff0c;而是需要手动启动并指定下一步流程。 Manual Task可以用于以下场景&#xff1a; 1、流程执行需要等待人工干…

13-nginx

一 初始Nginx 1 Nginx概述 Nginx是一款轻量级的Web服务器、反向代理服务器&#xff0c;由于它的内存占用少&#xff0c;启动极快&#xff0c;高并发能力强&#xff0c;在互联网项目中广泛应用。Nginx 专为性能优化而开发&#xff0c;使用异步非阻塞事件驱动模型。 常见服务器 …

MySQL基础——约束

前言 MySQL在我们工作中都会用到&#xff0c;那么我们最常接触的就是增删改查&#xff0c;而对于增删改查来说&#xff0c;我们更多的是查询。但是面试中&#xff0c;面试官又不会问你什么查询是怎么写的&#xff0c;都是问一些索引啊&#xff0c;事务啊&#xff0c; 底层结构…

搞懂 API:XML 和 Json的差异到底有多大

XML和JSON是两种常见的数据格式&#xff0c;它们在现代网络应用中起着重要的作用。本文将介绍XML和JSON的基础知识&#xff0c;并比较它们之间的差异。 XML XML&#xff0c;即可扩展标记语言&#xff08;eXtensible Markup Language&#xff09;&#xff0c;是一种用于描述数…

部署个人博客系统

目录 1.安装jdk 2.安装tomcat 3.数据库 4.部署博客系统 1.建库建表 2.微调代码 3.打包 4.拷贝 5.访问博客系统 为了能将我们写的项目部署到云服务器上 首先需要将部署时所依赖的环境搭建好 需要安装jdk,tomcat,mysql 1.安装jdk 直接使用包管理器进行安装,基于yum安装…

深入拆解 Java 虚拟机-打卡|开篇词 | 为什么我们要学习Java虚拟机?

文章目录 计划缘起跟郑老师学习学习JVM的好处 计划 缘起 JVM对我来说是高深莫测的东西&#xff0c;从事软件开发有些年头了&#xff0c;很难深入的去学习它&#xff0c;一来是工作中没有亟需用到这些&#xff0c;都是写一些业务代码&#xff0c;二来是觉得困难没有坚持下去&a…

每天一道大厂SQL题【Day22】华泰证券真题实战(四)

每天一道大厂SQL题【Day22】华泰证券真题实战(四) 大家好&#xff0c;我是Maynor。相信大家和我一样&#xff0c;都有一个大厂梦&#xff0c;作为一名资深大数据选手&#xff0c;深知SQL重要性&#xff0c;接下来我准备用100天时间&#xff0c;基于大数据岗面试中的经典SQL题&…

【Java-Java集合】Java集合详解与区别

【Java-Java集合】Java集合详解与区别 1&#xff09;概述2&#xff09;集合框架图2.1.总框架图2.2.Iterable 框架图2.3.Map 框架图 3&#xff09;List3.1.ArrayList 类继承图3.2.LinkedList 类继承图 4&#xff09;Set4.1.HashSet 类继承图4.2.LinkedHashSet 类继承图4.3.TreeS…

C/C++开发中使用pkg-config来引用依赖库

在使用C/C进行开发的过程中&#xff0c;经常需要引用其它的库&#xff0c;可能是系统已经安装好的&#xff0c;也可能是其它的外部库。 如果是系统支持的库&#xff0c;可能在不同的系统下&#xff0c;其路径也不相同&#xff0c;在项目开发的时候跨平台将会是一个问题。比如&…

从零开始云服务器网卡抓包

从零开始云服务器网卡抓包 一. 服务器上新增自己的用户二. 添加组件libpcap四. 安装测试环境六. 编写demo代码七. 正式项目代码编译八. 结果展示 一. 服务器上新增自己的用户 我这边是ubuntu服务器&#xff0c;其默认username为ubuntu&#xff0c;使用创建服务器时候的密码通过…

10.基于共享储能电站的工业用户日前优化经济调度(论文复现)

matlab代码&#xff1a;基于共享储能电站的工业用户日前优化经济调度 相关程序代码资源&#xff1a;风、光、负荷场景生成&#xff1b;风电出力各场景及概率&#xff1b;光伏出力各场景及概率&#xff1b;负荷各场景及概率&#xff1b;场景的削减&#xff1b;样本概率初始化&a…

【云原生进阶之容器】第六章容器网络6.5.1--Calico网络方案综述

《云原生进阶之容器》专题索引: 第一章Docker核心技术1.1节——Docker综述第一章Docker核心技术1.2节——Linux容器LXC第一章Docker核心技术1.3节——命名空间Namespace第一章Docker核心技术1.4节——chroot技术第一章Docker核心技术1.5.1节——cgroup综述

Spring Web容器响应异常排查_Poller线程异常退出

问题一_系统响应异常 问题现象 04-11 18点左右客户反馈系统很慢&#xff1b;18点多&#xff0c;反馈pda登录异常&#xff1b; 19:20左右&#xff0c;本地网页登录&#xff0c;某些请求超时&#xff1b;某些正常&#xff1b; 短时间定位后无头绪&#xff0c;保留了stack和dum…

球友的一个帖子,半夜三点给我整睡不着了……

文章目录 一、起因二、建议1、括号和缩进2、仔细审题3、独立思考4、早起的好办法5、chatgpt会代替人类吗&#xff1f; 三、解决1、数据结构2、初始化3、判定 一、起因 事情的起因源自于星球里面一位球友的帖子&#xff0c;本来三点醒来上完厕所打算继续睡&#xff0c;突然手机响…

无人机应急救援有保障吗?如何实现救援?

无人机应急救援有保障吗?如何实现救援?中国自然灾害种类较多&#xff0c;分布地域广&#xff0c;发生频率较高。当遭遇洪水、火灾、洪水、地震、暴雪等灾害事故时&#xff0c;常规的信息通信基础设施受到损伤&#xff0c;导致信号中断。如果灾害事故地点相对偏僻&#xff0c;…

淄博旅游“一夜爆火”,五一流量大盘已经开启

全民调休换来的五一小长假即将来临&#xff0c;经过几年“禁锢”后&#xff0c;这两年的旅游业开始回暖。 而今年国内旅游黑马竟指向了新人淄博。 山东淄博烧烤一直以来都“小有名气”&#xff0c;但是这只在周边城市&#xff0c;或者部分人群里传播&#xff0c;而在今年&…

来使用分支语句和循环语句实现一个小游戏吧(猜数字游戏)

猜数字游戏 1.代码展示2.菜单设计3.主函数部分3.随机数设计 1.代码展示 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <stdlib.h> #include <time.h>void menu() {printf("************************\n");printf("*** 1.p…

移动端导航设计

根据产品层级的深度和广度&#xff0c;选择适合的导航模式&#xff0c;是产品设计中的关键一环。 任何APP的组织信息都需要以某种导航框架固定起来&#xff0c;一个新的产品合适的导航框架&#xff0c;决定了产品之后的延伸和扩展。 移动端的屏幕尺寸就这么大&#xff0c;操作方…

java定位系统源码,通过独特的射频处理,配合先进的位置算法,可以有效计算出复杂环境下的人员与物品的活动信息

智慧工厂人员定位系统源码&#xff0c;区域电子围栏管控源码 文末获取联系&#xff01; 在工厂日常生产活动中&#xff0c;企业很难精准地掌握访客和承包商等各类人员的实际位置&#xff0c;且无法实时监控巡检人员的巡检路线&#xff0c;当厂区发生灾情或其他异常状况时&#…

Layer组件多个iframe弹出层打开与关闭及参数传递

Layer官网地址&#xff1a;http://layer.layui.com/ 1、多个iframe弹出层&#xff08;非嵌套&#xff09; 1.打开iframe弹出层js代码 &#xff08;1&#xff09;示例一&#xff1a; content参数可传入要打开的页面&#xff0c;type参数传2&#xff0c;即可打开iframe类型的弹层…