整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

JavaScript 正则命名分组

击右上方红色按钮关注“web秀”,让你真正秀起来

前言

以往我们只是习惯于通过数组下标来访问正则匹配到的分组,但分组达到4、5个时,标识起来就会非常麻烦。V8早已实现了正则命名分组提案,只是我们很少使用,本文将介绍JS的正则命名分组。

JavaScript 正则命名分组

过去

假设要使用正则匹配一个日期的年月日,以往我们会这样做:

const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/;

const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj[1]; // 1999
const month = matchObj[2]; // 12
const day = matchObj[3]; // 31

这里有几个缺点:

  • 要找到一个分组的位置,你必须要去数括号的位置,有时嵌套起来会更令人头疼。
  • 后面维护代码的同学阅读起来,还要根据下标找到正则里面对应的括号,并且要再次阅读括号里面的正则才知道含义。
  • 当你调整正则捕获分组的数量、顺序或嵌套时,你必要还要对下面的代码做调整。

所有这些问题,都可以通过正则命名分组来解决。

现在

现在你只需要给分组里面一个命名标识即可:

(?<year>\d{4})

这里,我们用变量year标记了上一个捕获组#1。 该名称必须是合法的JavaScript标识符。 匹配后,您可以通过matchObj.groups.year访问捕获的字符串。

让我们通过命名分组重写前面的代码:

const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;

const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj.groups.year; // 1999
const month = matchObj.groups.month; // 12
const day = matchObj.groups.day; // 31

如果正则里面有了命名分组,那么匹配结果会多了一个groups 的属性,这个属性中包含了一切命名分组的捕获结果。配合上解构大法使用又是一股清流:

const {groups: {day, year}} = RE_DATE.exec('1999-12-31');
console.log(year); // 1999
console.log(day); // 31

当然,即使你使用了命名分组,那么返回的结果还可以通过以往的数组下标方式访问:

const year2 = matchObj[1]; // 1999
const month2 = matchObj[2]; // 12
const day2 = matchObj[3]; // 31

命名分组具有以下优点:

  • 找到分组的“ID”更容易。
  • 匹配的代码变得自描述性,因为分组的ID描述了捕获的内容。
  • 如果更改分组的顺序,则不必更改匹配的代码。
  • 分组的名称也使正则表达式更易于理解,因为您可以直接看到每个组的用途。

反向引用

反向引用命名分组\k<name> 看下面这个匹配重复单词的例子:

const RE_TWICE = /^(?<word>[a-z]+)!\k<word>$/;
RE_TWICE.test('abc!abc'); // true
RE_TWICE.test('abc!ab'); // false

同时也可以使用以往的反向引用方式:

const RE_TWICE = /^(?<word>[a-z]+)!\1$/;
RE_TWICE.test('abc!abc'); // true
RE_TWICE.test('abc!ab'); // false

replace( )

字符串方法replace()以两种方式支持命名分组:

方式一

const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
console.log('1999-12-31'.replace(RE_DATE, '$<month>/$<day>/$<year>'));
// 12/31/1999

如果replace不一定是直接返回新的拼接字符串,那么可以看看下面的办法:

方式二

const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
console.log('1999-12-31'.replace(
 RE_DATE,
 (g, y, m, d, offset, input, {year, month, day}) =>
 month+'/'+day+'/'+year));
 // 12/31/1999

看看这replace的callback形参密密麻麻看得心慌慌,很多都用不上,那么我们看看更简单的写法:

console.log('1999-12-31'.replace(RE_DATE,
 (...args) => {
 const {year, month, day} = args.slice(-1)[0];
 return month+'/'+day+'/'+year;
 }));
 // 12/31/1999

这里配合上spread operator直取最后一个参数,再接上一个解构大法,结果又是一股清流。

命名分组没有匹配结果?

如果可选的命名组不被匹配,则其属性值被设置为undefined,但key是仍存在:

const RE_OPT_A = /^(?<as>a+)?$/;
const matchObj = RE_OPT_A.exec('');

// We have a match:
console.log(matchObj[0] === ''); // true

// Group <as> didn’t match anything:
console.log(matchObj.groups.as === undefined); // true

// But property as exists:
console.log('as' in matchObj.groups); // true

异常情况

分组名不能有重复项:

/(?<foo>a)(?<foo>b)/ // SyntaxError: Duplicate capture group name

反向引用一个不存在的分组名:

/\k<foo>/u // SyntaxError: Invalid named capture referenced
/\k<foo>/.test("k<foo>") // true, 非 Unicode 下为了向后兼容,k 前面的 \ 会被丢弃

在 reaplce() 方法的替换字符串中引用一个不存在的分组:

"abc".replace(/(?<foo>.*)/, "$<bar>") // SyntaxError: Invalid replacement string
"abc".replace(/(.*)/, "$<bar>") // "$<bar>",不包含命名分组时会向后兼容

说明

Chrome60 已支持命名分组 通过babel插件处理兼容问题 babel-plugin-transform-modern-regexp

公告

喜欢小编的点击关注,了解更多知识!

avaScript复选框的分组单选实现

近期在制作MVC实例教学课件中,选择使用了在线考试作为题材进行页面的设计,在线考试主要提供单项选择题,用户点击选择项之后提交服务器端。页面布局时使用了复选按钮进行了选项的设置。本文主要讨论分组复选框模拟实现单选功能。


实现效果

本例设计使用复选按钮模拟单选按钮主要原因是出于页面的美观。考试页面需要将复选按钮按照题目进行分组,并且针对同一题目只允许选择一个,即模拟实现单选功能。设计页面效果如下图:

考试页面设计效果

考试页面设计效果如上图,按照题目编号分组后实现单选功能。操作动画演示如下图:

动态实现效果展示


实现基本思路

使用复选框模拟分组单选按钮设计及实现效果描述如上所示,其实现主要需要借助JavaScript前端交互脚本技术。具体实现思路描述如下:

1、获取被点击复选框编号

获取复选框被点击的编号id主要目的是需要通过编号判断当前复选框属于哪一个分组。进而确定第几道题的第几个选项被点击。

2、获取被点击复选框同组复选框编号

在获取当前点击复选框之后可以通过取余数运算获取余数。设计每个题目必须具有四个选项。通过%4进行取余数。根据余数获取本组其他复选框的ID值。如余数为0,表示当前被点击的是本组最后一个复选框。

3、设置本组其他复选框为未选中状态

在获取本组其他复选框之后,可以进一步通过JavaScript文档对象模型的getElementById()方法获取每一个复选框,并设置其checked属性值为false,表示未选中。


编码实现

在明确基本实现思路之后可以进行前端HTML页面的设计及JavaScript的编码操作实现等。按照设计思路,需要将试题中出现的所有复选框都设置ID属性。且ID属性需要按照从 1递增进行设置。设计Name属性用于实现分组,即同一题目四个选项对应的复选框Name相同。前端HTML代码描述如下:

input标记及属性设置

input标记及属性设置描述如上图所示,设置id用于标志每一个复选框,设计name标志分组,设计onclick事件用于接受模拟单选操作。

本例设计函数setValue()用于实现处理模拟单选操作,该函数传递标志自身的this。在接收到this之后可以通过它获取对应的id值,并进行进一步处理。基本操作步骤如下:

1、var eid=this.id;

获取当前点击复选框对应的id值并存储变量eid中。

2、var i=eid%4

取余数判断当前复选框在所属组中的位次。

3、var el=new Array(3)

.结构标记:作用就是为了提升标记的语义性,每个结构有每个不同的标记。

1.头部标记:<header></header>,用于定义页面的页眉,最上面的内容。等同于<div id="header"></div>,作用一样。就是相当于一个容器,装其他的元素。

2.导航标记:<nav></nav>,用于定义页面的导航链接部分。等同于<div id="nav"></div>

例如可以这样写导航:

<nav>

<ul>

<li></li>

</ul>

</nav>

3.主体标记:<section></section>作用:定义页面主体内容中的小节,现在section可以表示整个页面的主体内容等同于<div id="main"></div>

4.<article></article>作用:用于描述文本性较强,或者艺术气息较强的内容。一般情况下,论坛中的帖子信息,报纸信息,博客或微博中的条目信息。用户回复信息,有限考虑放在article中

5.<footer></footer>定义页面中或某个区域中的脚注信息,页面最底部的信息。

6.边栏:<aside></aside>定义页面侧边栏,靠边的信息

以上结构标记为的就是独立定义结构,替代div。

表单

表单的作用:显示,收集信息,并且将信息提交给服务器

(在注册,登陆的时候,网页就会提供一些供用户填写的表单,表单元素会把填写的信息提交服务器进行处理 )

表单包含两组内容

1.表单元素<form>

<form></form>

注意:使用表单控件提交数据时,表单不能省略

属性:

1.action:后台处理程序的地址(服务器端工程师提供),默认会提交给本页。

2.method:方式,表单的提交方式。不同的提交方式约束的内容不一样。

常用取值:2个

get:

1.显示提交数据,会将提交信息显示在地址栏上面,安全性不高,又叫显示提交

2.大小限制,最大支持到2kb的提交。

3.如果不设置method属性,默认就是get方式提交(显示提交,最大2kb)

4.使用场合:向服务器索取数据时,优先使用get

post:

1.隐式提交数据,不会将提交的信息显示在地址栏上,安全性较高,所有有关密码的信息提交时,必须用post

2.post没有大小限制。

3.使用场合:安全性要求较高的页面,传递数据量较大的时候

3.enctype

作用:设置对表单中提交的数据的编码方式,规范哪些数据可以提交给服务器

取值:

1.application/x-www-form-urlencoded,默认值,可以将普通的文本,特殊的字符,一起提交给服务器。

2.multipart/form-date,允许将表单中的文件,传递给服务器,普通文本不能直接传递。

3.text/plain,只能将普通文本传递给服务器,特殊字符不允许。

4.id

5.name

2.表单控件

什么是表单控件

包含在表单中的元素,具备可视化外观,并且可以接受用户输入的数据。

分类

1.input元素

2.textare文本域

3.select和option选项框

一.input元素,主要作用就是收集用户信息

语法:<input>

属性:

type,根据不同的类型值可以创建不同的输入控件,用户名,密码,按钮形式的

value,控件的值,提交给服务器的数据。

name,控件的名称。必须设置,否则无法提交,服务器主要根据name这个控件的名称,来获取value

disabled,禁用控件,该属性可以没有值。

1.文本框和密码框

文本框:<input type="text">

允许用户输入任意字符的数据,明文显示

密码框:<input type="password">

允许用户输入任意字符的数据,密文显示

属性:

maxlength:限制输入的字符数

readonly:只读,无需给值

value:控件值,同时也可以设置控件

注意:input元素下,如果不写type值,或者type值写错时,都默认为文本框。

单选框和复选框

1.单选框:<input type="radio">

属性:

1.name:定义名称并且实现控件分组,一组内的元素才能实现单选

2.value:控件值

3.checked:设置默认被选中,不需要值

2.复选框

<input type="checkbox">

属性:name:定义名称并且分组,便于服务器获取

3.按钮

1.提交按钮,功能固定化,负责将数据提交给服务器

<input type="submit">

2.重置按钮,功能固定化,负责将表单控件恢复到初始化的状态

<input type="reset">

3.普通按钮,没有固定功能,由开发者通过js来设置。

<input type="button">

value:显示在按钮上的文本

name:名称(可写可不写)

4.非input标签的按钮

<button></button>

<button type="button">普通按钮</button>

属性:type

5.隐藏域和文件选择框

1。隐藏域,不想让用户看见,但是又要提交到服务器的数据,可以放在隐藏域中

例如:隐藏用户id

type="hidden"

<input tpe="hidden">

属性:

name

value

6.文件选择框

提供一个基础控件,允许用户选择本机的文件上传到服务器

type="file"

<input type="file">

属性:name value

注意:

表单的method(提交方式)属性值必须为post

表单的enctype编码必须为multipart/form-date

更多知识关注小编,或者百度网络营销师钟震,钟震讲网络营销。会有很多相关知识,公众号网络营销师钟震,以后每天都会分享web前端,淘宝运营,竞价,网站建设和优化,社媒方面的知识。与大家共同进步。希望对您有一点点帮助,喜欢记得关注公众号。