零碎知识14 (重点:正则)

116 阅读6分钟

vue的style有scoped时想要设置全局样式的方法

  • :deep(选择器) 会把属性选择器加到该选择器的上一层,若为了摆脱scoped带来的自动附加的属性选择器,若再写一个<style>标签太累赘
  • 可以通过 :global() 来实现全局选择
.info { 
//外面这层选择器实际上是无效的,编译成css时 会以:global里的选择器作为第一层
  :global(.el-dropdown-menu__item) {
    line-height: 36px !important;
    padding: 6px 22px;
  }
}

图片懒加载的两种方案

  • 目标:1.懒加载 2.图片加载成功前展示的图片可自定义

方案1(vue-lazyload)

  1. pnpm add vue-lazyload
main.js
import VueLazyLoad from "vue-lazyload";
Vue.use(VueLazyLoad, {
  preLoad: 1,
  error: require("./assets/person.png"),//加载失败的图片
  loading: require("./assets/loading.gif"),//加载中的图片
  attempt: 2,
});

3.

<img v-lazy="item.imgUrl"
                   alt=""
                   class="customer-img" />

方案2 (element-plus)

          <el-image :src="headerImg"
                    fit="cover"
                    lazy
                    class="img">
            <!-- 空白时期用图片占位(可以用) 图片加载慢/加载出错图片-->
            <template #placeholder>
              <img src="@/assets/loading.gif"
                   alt="" />
            </template>
            <template #error>
              <img src="@/assets/profile.png"
                   alt="" />
            </template>
          </el-image>
  • 用element就是代码有点长,可以在有占位图/出错图的前提下不懒加载,个别图片(登录用户头像这种)要用时可以用该方案
  • vue-lazyload会简约很多,如果长列表这种,推荐用

flex布局练习游戏

flexboxfroggy.com/#zh-cn

各种语言入门网站

learnxinyminutes.com/

混合开发通信(web视角)

web发给exe

  • chrome.webview?.postMessage(JSON.stringify(params))

exe操作web

  • 暴露方法给window。function setVal(val){...} window.setVal=setVal

正则里容易疏忽的地方

转义

  • 元字符:([ { \ ^ $ |) ? * + . (若匹配元字符本身需要转义)
    • ^ $ . * + ? | \ / ( ) [ ] { } - 无脑一律转义,总之不会出错
    • 通过new RegExp创建正则时 / 转不转义都行,若直接写成字面量是需要转移的 \/
    • const prefixRgx1 = new RegExp("<span.+?</span>")
    • const prefixRgx2 = /<span.+?<\/span>/
  • [ ]内部不需要转义
    • 跟字符组相关的元字符有[]、^、-。 在会引起歧义的地方进行转义
    • var reg=/[() +\]/; //匹配'(',')',' ','+','\'其中之一, []内部不需要转义
    • 若要在中括号表达式中包括连字符-,请采用下列方法之一:
      • 用反斜杠将它转义:[\-]
      • 将连字符放在中括号列表的开始或结尾 [-a-z] [a-z-]
  • \w:[A-Za-z0-9_]
  • ?:{0,1} // 当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的,尽可能少地匹配所搜索的字符串

参考:blog.csdn.net/weixin_4410…

断言

慎用,苹果设备不支持,写完还得改

  • x(?=y):匹配'x' 仅仅当'x'后面跟着'y'.这种叫做先行断言。
    • x(?!y):仅仅当'x'后面不跟着'y'时匹配'x',这被称为正向否定查找。
  • (?<=y)x:匹配'x' 仅当'x'前面是'y'.这种叫做后行断言。
    • (?<!y)x:仅仅当'x'前面不是'y'时匹配'x',这被称为反向否定查找。
  • (?:) 匹配组, ?:标记该匹配组不应被捕获

(?:pattern) 非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分时很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。

image.png

实现关键字匹配高亮

function checkWordsList(wordList,originText) {
      // 创建一个正则表达式,用于匹配所有关键字
      const regex = new RegExp(
      // repalce是要对正则特殊字符进行转义,防止匹配时被当成正则关键字 而不是要被匹配的字符
        wordList.map((kw) => kw.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|'),
        'gi'
      )
      // 使用正则表达式替换关键字
      return  originText.replace(regex, (match) => {
        return '<span class="key-words">' + match + '</span>'
      })
  }

分析构成:

arr=['+aa','(12','*bc']
rawStr=arr.map((kw) => kw.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|') // '\\+aa|\\(12|\\*bc'
let reg=new RegExp(rawStr,'gi')   //  /\+aa|\(12|\*bc/gi
'..+aa...*bc...(12...'.replace(reg,(val)=>`-${val}-`)  //  '..-+aa-...-*bc-...-(12-...'
  • 有两种方法可以创建一个 RegExp 对象:一种是字面量,另一种是构造函数。
  • 如果要通过变量来生成正则,就要用new RegExp
    • 当使用构造函数创造正则对象时,需要常规的字符转义规则(在前面加反斜杠 \
    •      //这俩等价 一个反斜杠,new完就没了
          var re = new RegExp("\\w+");
          var re = /\w+/;
      
  • kw.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))等价于下面,目的是把正则关键字转义一下
    • kw.replace(/[.*+?^${}()|[\]\\]/g,val=>`\\${val}`)

正则捕获组

'http://dev.baidu.com/gqq/?code=JSynfueD4d5WBCy6sADMGQXYk&state=STATE#/home'.replace(/(.*?)/?(.*)#(.*)/,"$1/#$3?$2")
'http://dev.baidu.com/gqq/#/home?code=JSynfueD4d5WBCy6sADMGQXYk&state=STATE'

[非]贪婪匹配最常用的方式

  • 贪婪匹配下,.* 会匹配尽可能多的字符
  • 非贪婪匹配的写法是.*? //它会尽可能少地匹配

'hellohellohello'.match(/h.*?o/) 结果是伪数组,相当于["hello"]

正则带g和不带g影响match里组的结果

  • 不带g时,match出来的,会把正则 (捕获分组) 里匹配到的也放数组里
  • 带g时就不放了
'123abcd'.match(/([1-9])([a-z]+)/)
//(3['3abcd', '3', 'abcd', index: 2, input: '123abcd', groups: undefined]

'123abcd'.match(/([1-9])([a-z]+)/g)
['3abcd']

匹配任意字符

  • . 匹配除“\n”和"\r"之外的任何单个字符
  • [\s\S] 这种是匹配所有字符

匹配url链接

/(?:http|https):\/\/(?:[a-z0-9-]+\.)+[a-z]{2,20}(?:\/[\w\d#_%@/]+)+(?:\?[\w\d#_%@=&.\u4e00-\u9fa5]+)?/g

  • (?:) 非捕获组,减少性能消耗

分析:

  • /(http|https):\/\/([a-z0-9-]+\.)+[a-z]{2,20}(\/[\w\d#_%@/]+)+(\?[\w\d#_%@=&.\u4e00-\u9fa5]+)?/g
    • (http|https)://([a-z0-9-]+.)+[a-z]{2,20} 是匹配 xxx.xxx.xx
    • (/[\w\d#_%@/]+)+ 是匹配 /xxx/yyy
    • (?[\w\d#_%@=&.\u4e00-\u9fa5]+)? 是匹配 ?id=13&content=12

文档(js使用正则的各种方法): developer.mozilla.org/zh-CN/docs/…

字符串中目标内容的位置生成数组

RegExp.exec()虽然能找到匹配项的位置,但执行一次只能得到一个,通过Sting.matchAll(/正则/g) 能拉到所有匹配项和它们的起始坐标

developer.mozilla.org/zh-CN/docs/…

let testMessage="提取字符串位置 https://pinia.web3doc.top/introduction.html 开始啦 https://c.runoob.com/front-end/854  目标正则标定"
const urlRgx =
  /(?:http|https):\/\/(?:[a-z0-9-]+\.)+[a-z]{2,20}(?:\/[\w\d#_%@]+)+(?:\?[\w\d#_%@=&.\u4e00-\u9fa5]+)?/g;
  
const matchUrlList=Array.from(testMessage.matchAll(urlRgx),(x)=>x)

const stopList=matchUrlList.map(el=>{
        const s=el.index
        const e=el.index+el[0].length
        return {s,e}
      })
//matchUrlList
[['https://pinia.web3doc.top/introduction', index: 8, input: '提取字符串位置 https://pinia.web3doc.top/introduction.html 开始啦 https://c.runoob.com/front-end/854  目标正则标定', groups: undefined]
['https://c.runoob.com/front', index: 56, input: '提取字符串位置 https://pinia.web3doc.top/introduction.html 开始啦 https://c.runoob.com/front-end/854  目标正则标定', groups: undefined]]

//stopList  
0: {s: 8, e: 46}
1: {s: 56, e: 82}

match时正则g对捕获组的影响

  • 当有捕获组时,若正则是全局匹配,则match方法不会把捕获组结果也放数组里
  • 当有捕获组时,若是单次匹配,match会把捕获组匹配的结果也放到数组里
'23132134run12415465run'.match(/([1-9])([a-z]+)/g)
// 结果: ['4run', '5run']

'23132134run12415465run'.match(/([1-9])([a-z]+)/)
// 结果:伪数组的内容
 ['4run', '4', 'run', index: 7, input: '23132134run12415465run', groups: undefined]

// 圆括号会有一个副作用,使相关的匹配会被缓存,此时可用 ?: 放在第一个选项前来消除这种副作用。
'23132134run12415465run'.match(/(?:[1-9])(?:[a-z]+)/)
// 结果:['4run', index: 7, input: '23132134run12415465run', groups: undefined]

菜鸟教程正则学习

正则一些技巧

摘自:juejin.cn/post/684490…

  • 善于用[^]排除字符来凑
// var regex = /id=".*?"/
var regex = /id="[^"]*"/ 
var string = '<div id="container" class="main"></div>'; 
console.log(string.match(regex)[0]); // => id="container"
  • 开头和结尾可以替换
var result = "hello".replace(/^|$/g, '#');
console.log(result); 
// => "#hello#"
  • 数字加,
var string1 = "12345678",
string2 = "123456789";
reg = /(?!^)(?=(\d{3})+$)/g;

var result = string1.replace(reg, ',')
console.log(result); 
// => "12,345,678"

result = string2.replace(reg, ',');
console.log(result); 
// => "123,456,789"
  • 匹配,整块挪位
var regex = /(\d{4})-(\d{2})-(\d{2})/;
var string = "2017-06-12";
var result = string.replace(regex, "$2/$3/$1");
console.log(result); 
// => "06/12/2017"
/*等价于*/
var regex = /(\d{4})-(\d{2})-(\d{2})/;
var string = "2017-06-12";
var result = string.replace(regex, function(match, year, month, day) {
	return month + "/" + day + "/" + year;
});
console.log(result); 
// => "06/12/2017"
  • 反向引用

里面的\1,表示的引用之前的那个分组(-|/|.)。不管它匹配到什么(比如-),\1都匹配那个同样的具体某个字符。

我们知道了\1的含义后,那么\2\3的概念也就理解了,即分别指代第二个和第三个分组。

var regex = /\d{4}(-|\/|\.)\d{2}\1\d{2}/;
var string1 = "2017-06-12";
var string2 = "2017/06/12";
var string3 = "2017.06.12";
var string4 = "2016-06/12";
console.log( regex.test(string1) ); // true
console.log( regex.test(string2) ); // true
console.log( regex.test(string3) ); // true
console.log( regex.test(string4) ); // false
  • 匹配成对的标签
var regex = /<([^>]+)>[\d\D]*<\/\1>/;
var string1 = "<title>regular expression</title>";
var string2 = "<p>laoyao bye bye</p>";
var string3 = "<title>wrong!</p>";
console.log( regex.test(string1) ); // true
console.log( regex.test(string2) ); // true
console.log( regex.test(string3) ); // false

正则容易忽略的bug

全局匹配的正则表达式匹配错位问题

  • /xx/g 当使用它时,它会有个隐藏属性是lastIndex,使用test时会往后挪一下 导致后面方法开始位置有误,无法全部匹配
  • 不影响 str.match(Reg),好像在执行前会把正则的lastIndex重置为0
let str='ab------ab--------ab'
const Reg=/ab/g
Reg.test(str) //true
Array.from(str.matchAll(Reg))
// [['ab', index: 8, input: 'ab------ab--------ab'groups: undefined]
// ['ab', index: 18, input: 'ab------ab--------ab'groups: undefined]]
  • RegExp.exec(String) 就是执行一次 会把正则后移一位,其它正则方法底层都用的它
const myRe = /ab*/g;
const str = "abbcdefabh";
let myArray;
while ((myArray = myRe.exec(str)) !== null) {
  let msg = `Found ${myArray[0]}. `;
  msg += `Next match starts at ${myRe.lastIndex}`;
  console.log(msg);
}

exec mdn教程 在设置了 global 或 sticky 标志位的情况下(如 /foo/g 或 /foo/y),JavaScript RegExp 对象是有状态的。它们会将上次成功匹配后的位置记录在 lastIndex 属性中。

vue2里导入的函数要在template里用

image.png