0%

【哈希+map】2404. 出现最频繁的偶数元素

Problem: 2404. 出现最频繁的偶数元素

思路

从数组中找出出现次数最多的偶数(如果这样的数有多个,选取较小的那个)

解题方法

原本的想法是使用map+set,map当作哈希表用来计数,set来记录出现次数最多的偶数,(看了大佬的代码)后来优化了只用map,使用int变量res记录出现次数最多的偶数,如果出现次数一样多,且这个数较小,则更新res。

顺便复习了下C++中map和set的用法,这两个都只能通过使用迭代器遍历,但是map可以通过map[key]的方式来访问和赋值,可使用的函数用begin()end()find()clear()等等。

复杂度

  • 时间复杂度:

    $O(n)$

  • 空间复杂度:

    $O(n)$

Code

原版:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

/***
原版
从数组中找出出现次数最多的偶数(如果这样的数有多个,选取较小的那个)
***/
class Solution {
public:
int mostFrequentEven(vector<int>& nums) {
//记录偶数出现的次数,存在mp中
unordered_map<int, int> mp;
for(int i = 0; i < nums.size(); i++){
int num = nums[i];
if(num%2==0){
if(mp.find(num)==mp.end()){//找不到
mp[num] = 1;
}else{
mp[num]++;
}
}
}
//找到mp中的最大值进行插入
int max = -1;
set<int> res;
for(unordered_map<int, int>::iterator it = mp.begin(); it != mp.end(); it++){
if(it->second > max){
max = it->second;//更新最大值
res.clear();
res.insert(it->first);
}else if(it->second == max){
res.insert(it->first);
}
}
if(max==-1) return -1;
else return *(res.begin());

}
};

简单优化后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/***
简单优化后
从数组中找出出现次数最多的偶数(如果这样的数有多个,选取较小的那个)
***/
class Solution {
public:
int mostFrequentEven(vector<int>& nums) {
//记录偶数出现的次数,存在mp中
unordered_map<int, int> mp;
for(int i = 0; i < nums.size(); i++){
int num = nums[i];
if(num%2==0){
if(mp.find(num)==mp.end()){//找不到
mp[num] = 1;
}else{
mp[num]++;
}
}
}
//找到mp中的最大值进行插入
int max = -1;
int res;
for(unordered_map<int, int>::iterator it = mp.begin(); it != mp.end(); it++){
if(it->second > max){
max = it->second;//更新最大值
res = it->first;
}else if(it->second == max && res > it->first){
res = it->first;
}
}
if(max==-1) return -1;
else return res;

}
};

【13】贪心+模拟 1147. 段式回文

Problem: 1147. 段式回文

思路

拆分字符串,使得拆分的字符串的前部分和后部分完全相同,返回能够拆分出的最大子串数

贪心:拆分时,能拆就拆=>拆分后的字符串尽可能的长=>能够拆分出尽可能多的子串

从小到大递归子串长度,模拟切割

解题方法

递归:
含义:当前字符串,能够拆分出的最大子串数
边界:不能拆=>空字符串=>长度为0

字符串的切片[(par1)..(par2)] =>[par1,par2) 左闭右开

复杂度

  • 时间复杂度: O(n^2)

  • 空间复杂度: O(n)

Code

s.substr(i,b): i表示从第i个位置开始选取长度为b的子串,b省略默认取到字符串末尾

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public:
int longestDecomposition(string text) {
int n = text.length();
if(n==0) return 0;//递归边界,长度为0不能拆,返回子串数为0
for(int i = 1; i <= n/2 ; i++){//枚举前后缀长度,从小到大递归前后缀长度可以保证每次分割都是按能拆就拆的思想分割的
if(text.substr(0,i)==text.substr(n-i)){
return 2 + longestDecomposition(text.substr(i,n-2*i));
}
}
return 1;
}
};

217.存在重复元素【简单】

题目

Problem: 217. 存在重复元素

给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 (appears at least twice),返回 true ;如果数组中每个元素互不相同(distinct),返回 false

示例 1:

1
2
输入:nums = [1,2,3,1]
输出:true

示例 2:

1
2
输入:nums = [1,2,3,4]
输出:false

示例 3:

1
2
输入:nums = [1,1,1,3,3,4,3,2,4,2]
输出:true

提示:

  • 1 <= nums.length <= 105
  • -109 <= nums[i] <= 109

解题思路与代码

思路一:

初始化标记为false,数组中任意值如果出现了2次,就可以标记为true

对数值中的每个值出现次数计数,如果某个值在某次计数后出现次数等于2就标记为true。

难点:不能用count[num]++来计数,因为nums[i]的取值是可以为负数的,但是数组不能有负索引号

**解决办法:**其实我上面的方法也是一种哈希表的方法,但我只用过C里面的map,对js中的map的用法不是很熟练,用map对象可以很好的解决负值的问题。暂时不写,还没理解map的用法。

思路二:

使用一个的新的数组,遍历nums数组,判断新数组n中是否存在nums[i],若不存在,则将nums[i]插入新数组n;若存在,则返回true;

判断数组中是否有某个值存在的方法为indexOf()

思路三:(官方题解思路)

在对数字从小到大排序之后,数组的重复元素一定出现在相邻位置中。因此,我们可以扫描已排序的数组,每次判断相邻的两个元素是否相等,如果相等则说明存在重复的元素。

复杂度

  • 时间复杂度:
    $O(n)$

  • 空间复杂度:
    $O(n)$

Code

解题思路一:

暂无

解题思路二:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 语言为JavaScript
* @param {number[]} nums
* @return {boolean}
*/
var containsDuplicate = function(nums) {
let n = [];
for(let k of nums){
if(n.indexOf(k)==-1){//不存在
n.push(k);
}else{
return true;
}
}
//上面for/of循环的遍历是js的写法,是ES6新增的
//下面的代码的for循环遍历方式是c中的惯用写法,是常规的for循环
// for(let i = 0; i < nums.length; i++){//遍历数组
// if(n.indexOf(nums[i])==-1){//不存在
// n.push(nums[i]);
// }else{
// return true;
// }
// }
return false;
};

《javaScript权威指南》读书笔记

本书笔记基于David Flanagan的《javaScript权威指南》原书第七版中文译本,也就是犀牛书。

词法结构

JavaScript程序的文本

  • 区分大小写
  • 忽略程序记号(token)之间的空格,很大程度上忽略换行符(也有例外)

不太理解什么叫程序记号

注释

1
2
3
4
5
6
7
8
//单行注释

/*单行注释*/

/*
*多行注释
*每行开头额外的*不是必需的,只是为了美观
*/

字面量

直接出现在程序中的数据值,如

1
2
3
4
5
null
false
1.2
1
'hello world'

标识符与保留字

标识符

用于命名常量、变量、属性、函数和类,就是一个名字,必需由字母,下划线,美元符号开头,可由字母、下划线、美元符号、数字组成。

保留字

一些不能作为标识符使用的单词,如for、if和while

当然还有一些比较复杂的情况,在一定情况下可以使用为标识符。不过最简单的做法就是不要使用这些单词作为标识符。

Unicode

JavaScript程序由Unicode字符集编写,意味标识符可以使用Unicode字母、数字和象形文字(不支持表情符号)。

Unicode转义序列

由于某些计算机硬件和软件无法识别、处理Unicode字符,故定义了转义字符,以\u开头,后跟4为十六进制数或包含在一对花括号内的1~6位十六进制数字。

花括号版本是ES6新增的

image-20230316020145144

Unicode归一化

由于不同编码方式的Unicode字符在js中是区分的,如下面的两个标识符

image-20230316021128685

image-20230316021145803

虽然看起来完全相同,但由于它们的二进制编码是不同的,所以js也会认为它们是不同的,这会导致看起来相同的两个标识符其实表示的是两个不同的标识符,在赋值等各个操作中会出现问题。

故在执行程序前,需要保证编辑器能够对源代码执行Unicode归一化。

可选的分号

分号用于分隔语句。

分号可省略的情况:

  • 两条语句分别写在两行(不是一定的)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    a = 3;//此时这个分号可以省略
    b = 4;

    a = 3;b = 4;//分号是必须的

    //也不是所有的换行符都会被当作为分号,只有在不添加符号就无法解析代码的情况下才会把换行符当作分号
    let a
    a
    =
    3
    console.log(a)
    //会被解释为
    let a; a = 3; console.log(a);

    //这种机制会引发一些问题,如下面的例子
    let y = x + f
    (a+b).toString()
    //会被解释为
    let y = x + f(a+b).toString();//不一定与作者的真实意图一致

    //另外一种情况,return、throw、yield、break、continue后面的换行符是一定会被解释为分号的
    return
    true;
    //一定会被解释为
    return;
    true;
    //故一定不能在这些保留字和他们后面的表达式之间加换行符

    另外,涉及到++、–操作符,必须与操作的表达式位于同一行。

    箭头函数中的=>也必须与参数列表在同一行

  • 在程序的末尾,接下来的加号是}

JavaScript基础语法-dom-bom-js-es6新语法-jQuery-数据可视化

该课程笔记基于b站pink老师的课程视频,视频链接:https://www.bilibili.com/video/BV1Sy4y1C7ha/?spm_id_from=333.337.search-card.all.click&vd_source=47b8ae38c6099b5bc1a761ca77b05155

JS基础语法

注释

  • 单行注释 快捷键ctrl + /
  • 多行注释快捷键shift + alt + a
  • vscode中修改多行注释的快捷键ctrl + shift + /

输入输出语句

输出:

  • 浏览器弹出警示框:alert(msg)
  • 浏览器控制台打印输出信息:console.log(msg)
  • 浏览器弹出输入框,用户可以输入:prompt(msg)

变量

变量声明与使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//age 为一个变量
var age;
//变量赋值
age = 18;
//变量初始化
var myname = '小明';//JS中用单引号,css和html中用双引号
//输出变量值
console.log(myname);
//多个变量一起申明
var age = 18,
address = 'sss',
gz = 1323;
//变量只声明但是不赋值,输出为undefined
//不声明直接赋值使用是可以的,但是会变成全局变量,不推荐
//不声明不赋值,使用时会直接报错

变量的命名规范

  • 严格区分大小写
  • 不能以数字开头
  • 由字母,下划线,数字,美元符号组成。
  • 不能使用关键字和保留字var for是错误写法
  • 变量名必须有意义
  • 遵循驼峰命名法:首字母小写,后面单词的首字母大写,例myFirstName
  • 不用使用name作为变量名

数据类型

JS是弱类型语言,变量数据类型是只有程序在运行过程中,根据等号右边的值确定的。

JS是动态语言,变量的数据类型是可以变化的

1
2
var a = 10;
a = 'Pink';

简单数据类型

  • 数字型:Number,包括整数和小数

    • 数字前面加0 表示八进制 010 = 8(10进制)
    • 数字面前加0x 表示十六进制 0xa = 10(10进制)
    • 数字的最大值:Number.MAX_VALUE;//1.79e+308
    • 数字的最小值:Number.MIN_VALUE;//5E-324
    • 无穷大:Infinity
    • 无穷小:-Infinity
    • 非数值:NaN
      • isNaN()这个方法用来判断一个变量是否是非数字,如果是数字返回的是false,反之返回true
  • 字符串型:加单(双)引号的内容,JS中推荐单引号。外双内单,外单内双

    • 字符串转义符:都是用\开头,写在字符串内部
      • 换行符\n
      • 斜杆\\
      • 单引号\'
      • 双引号\"
      • tab缩进\t
      • 空格\b
    • 获取字符串的长度:str.length
    • 字符串拼接:字符串+任意类型 = 拼接之后的字符串
  • 布尔型:true&false

  • 未定义数据类型:undefined

    未定义+数字 = NaN

  • 空值:null

    空值 + 数字= 数字

获取数据类型

typeof age: 检测数据类型

数据类型转换

  1. 转换为字符串

    • num.toString()

    • String(num)

    • num+’’()空字符

  2. 转换为数字型

    • parseInt(str)只能取整数部分
    • parseFloat(str)可以读取到小数部分
    • Number(str)强制转换
    • 隐式转换:'12'-0 ----> 12'123'-'120' = 3'123'*1--->123
  3. 转换为布尔型:Boolean(var)

运算符

算数运算符

+,-,*,/,%

浮点数不能直接进行运算,会有精度问题

比较运算符

image-20220814160547782

逻辑运算符

image-20220814160653602

逻辑中断逻辑与

表达式1 && 表达式2:表达式1为真返回表达式2,表达式1为假返回表达式1

逻辑中断逻辑或

表达式1 && 表达式2:表达式1为真返回表达式1,表达式1为假返回表达式2

赋值运算符

image-20220814161715893

运算符优先级

image-20220814205126091

流程控制

顺序流程控制

分支流程控制

分支流程控制

  • if-else语句

  • switch语句

  • 三元表达式:条件表达式 ? 表达式1 :表达式2

    条件表达式成立返回表达式1,反之返回2

循环结构

for

while

do-while

continue关键字:立刻跳出当前循环,进入下一次循环

break关键字:退出整个循环

数组

创建数组

1
2
3
4
5
1.
var arr = new Array();

2.
var arr = [];

遍历数组

1
2
3
4
var arr = [1,2,3,4,5,6];
for(var i = 0; i < arr.length; i++){
console.log(arr[i]);
}

新增数组元素

1
2
3
4
5
1.新增数组元素,改变数组长度
arr.length = 5;//手动增加数组长度

2.修改索引号
arr[arr.length] = 'shiff';

冒泡排序

1
2
3
4
5
6
7
8
9
10
11
let arr = [23, 43, 52, 3, 5, 45];

for (let i = 0; i < arr.length - 1; i++) {
for (let j = 0; j <= arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}

函数

声明函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1
function sayHI(){
console.log('hi');
}

function getSum(num1, num2){
console.log(num1 + num2);
}

2.
var 变量名 = function() {};

var getSum = function(num1, num2){
console.log(num1 + num2);
}

js函数申明中的形参可以不用申明变量类型

调用函数

1
sayHI();

arguments:函数中的伪参数,伪数组,拥有length属性,拥有索引号,不具有数组中的某些方法

1
2
3
4
5
function fn(){
console.log(arguments);
}

fn(1,2,3);

作用域

全局作用域:整个script标签,或者一个单独的js文件

局部作用域:函数作用域(函数内部),局部作用域内:局部覆盖全局

作用域链:就近原则

1
2
3
4
5
6
7
8
9
var num = 10;
function fn(){
var num = 11;
function fun(){
consolo.log(num);
}
fun();
}
fn();//---> num = 11;接近原则

JS的预解析

js引擎先预解析,在代码执行:

(1)预解析:js引擎会把js里面所有var 还有function提升到当前作用域的最前面

(2)代码执行:按照代码书写顺序从上往下执行

2.预解析 包括:

  • 变量预解析:把所有变量的声明提升到当前作用域的最前面,但是不提升赋值
  • 函数预解析:

对象

对象是一个具体的事物

对象的构成:

  • 属性:特征
  • 方法:行为

创建对象

利用字面量创建对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var obj = {};//创建了一个空的对象

var obj = {
uname : 'shiff',
age : 18,
gender: '女',
sayHi: function(){
console.log('hi~');
}
}
//对象里面的属性或者方法我们采取键值对的形式 键 属性名 : 值 属性值
//多个属性或者方法之间用逗号,最后一个属性或方法不用加逗号
//方法冒号后面跟的是一个匿名函数
//第二种调用方法:对象名[‘属性名’]
console.log(obj['gender']);
//调用对象的方法:对象名.方法()
obj.sayHi();

利用new Object创建对象

1
2
3
4
5
6
7
8
9
10
11
//利用new Object创建对象
let obj1 = new Object();//创建了一个空对象
obj1.uname = 'shiff';
obj1.age = 18;
obj1.gender = '女';
obj1.sayHi = function (){
console.log('Hi');
}
console.log(obj1.uname);
console.log(obj1['uname']);
obj1.sayHi();

利用构造函数创建对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function 构造函数名(){
this.属性 = 值;
this.方法 = function (){}
}
new 构造函数名();

//利用构造函数创造对象
function Star(uname, age, gender) {
this.name = uname;
this.age = age;
this.gender = gender;
this.sing = function(song){
console.log(song)
}
}
let ldh = new Star('刘德华',18,'男');//调用函数返回的是一个对象
//1.构造函数名字首字母要大写
//2.构造函数不需要return 就可以返回对象
//3.调用构造函数,必须要使用new
//4.属性和方法面前必须添加this
console.log(ldh.name);
console.log(ldh['gender'])
ldh.sing('冰雨');

构造函数,是抽象了对象的公共部分,封装到了函数里面

通过new关键字创建对象的过程称为对象实例化

new关键字执行过程

  1. new构造函数在内存中创建一个空的对象
  2. this就会指向刚才创建的空对象
  3. 执行构造函数里面的代码,给这个空对象添加属性和方法
  4. 返回这个对象

遍历对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let obj = {
name : 'shiff',
age : 18,
gender: '女',
fn: function(){
console.log('233');
}
}
// for(变量in对象){}
//也可以遍历方法

for(let k in obj){
console.log(k);//k变量输出 得到的是属性名
console.log(obj[k]);//obj[k]得到的是属性值
}

JS的内置对象

JS中的对象类型:

  • 自定义对象
  • 内置对象
  • 浏览器对象

Math对象

常用方法

1
2
3
4
5
6
7
Math.PI					//圆周率
Math.floor() //向下取整
Math.ceil() //向上取整
Math.round() //四舍五入 就近取整
Math.abs() //绝对值
Math.max()/Math.min() //最大/最小值
Math.random() //随机数

日期对象

Date()日期对象是一个构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//创建一个对象
let date = new Date();
//如果没有参数,返回系统的当前时间

console.log(date.valueof());
console.log(date.getTime());
valueof()
getTime()
//返回我们现在时间距离1970.1.1总的毫秒数(时间戳)
//也可以
date1 = +new Date();
console.log(date1);
//h5新增
console.log(Date.now());//不需要创建实例

倒计时:将来的时间戳-现在时间戳

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function repairZero(a){
return a > 10 ? a : '0' + a;
}
function countDown(time) {
let nowTime = +new Date();//返回的是当前时间总的毫秒数
let inputTime = +new Date(time);//返回的是用户输入时间总的毫秒数
let times = (inputTime - nowTime) / 1000; //除以1000得到秒数
let d = parseInt(times/60/60/24);//天
d = repairZero(d);
let h = parseInt(times/60/60%24);//时
h = repairZero(h);
let m = parseInt(times/60%60);//分
m = repairZero(m);
let s = parseInt(times%60);//当前的秒
s = repairZero(s);
return d + '天' + h + '时' + m + '分' + s +'秒';
}
console.log(countDown("2022-8-17 15:11:00"));

数组对象

创建数组

1
2
3
4
5
6
7
1.字面量
let arr = [];//空数组

2.构造函数
let arr1 = new Array(2);//创建数组长度为2的空数组

let arr2 = new Array(2,3);//等价于[2,3]有两个数组元素

检测是否为数组

1
2
3
4
5
6
7
8
9
1.instanceof 运算符

arr instanceof Array;//值为true或false判断arr是否为数组


2.Array.isArray([1,2,3]);//true

Array.isArray('shiff');//false
//返回true或者false,H5新增,ie9以上版本支持

添加删除数组的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//1.push()在数组末尾添加一个或多个元素
let arr = [1,2,3];
arr.push(4);//arr = [1,2,3,4]
arr.push(5,'pink');//arr = [1,2,3,4,5,'pink']
//push的返回值是新数组的长度,原素组也会发生变化
console.log(arr.push(6));//7
//2.unshift在数组前面添加一个或多个元素,基本特性与push想同
arr.unshift('red','green');
//3.pop()删除数组中的最后一个元素
arr.pop();
//返回是的删除的那个元素,原数组会发生变化
//4.shift()删除数组的第一个元素
//返回的是删除的那个元素,原数组会发生变化
arr.shift();

翻转数组:arr.reverse()

冒泡排序:arr.sort()

1
2
3
4
5
arr.sort(function(a,b){
return a - b;//升序
//return b - a;//降序
})
console.log(arr);

数组索引方法

1
2
3
4
5
6
let arr = ['red','blue','pink','blue'];
let a = arr.indexOf('blue');// a = 1;
//indexOf返回第一个满足条件bule的索引号
//如果找不到该元素,返回-1
//lastindexOf从后面往前查找第一个为blue的索引号
let b = arr.lastindexOf('blue');//b = 3

数组转换为字符串

1
2
3
4
5
6
7
8
1.toString()将我们的数组转换为字符串
let a = [1,2,3];
let string = a.toString();//1,2,3

2.join(分隔符)
let b = [1,2,3];
let s = b.join('-');//1-2-3
let s = b.join('&');//1&2&3
  • concat():连接两个或多个数组,返回值为一个新的数组
  • slice():数组截取slice(begin,end),返回被截取的新数组
  • splice():数组删除splice(第几个开始,要删除几个数),返回被删除的新数组,且会影响到原数组

基本包装类型:字符串

把简单数据类型包装为了复杂数据类型

  • String
  • Number
  • Boolean

image-20220817152010722

image-20220817153317139

image-20220817153821881

image-20220817154139984

Web APIs:DOM+BOM

API

应用程序编程接口,是一些预定义函数

Web API是浏览器提供的浏览器功能和页面元素的AIP

DOM

处理HTML和XML的接口

image-20220817185243063

  • 文档:一个页面
  • 元素:所有标签
  • 节点:所有内容(标签、属性、文本、注释)

获取元素

  • 通过ID获取:getElementById()

    1
    2
    3
    4
    5
    6
    7
    8
    <div id="time">2019-9-9</div>
    <script>
    //1.getElementById()通过获取元素id获得元素对象
    let timer = document.getElementById('time');
    console.log(timer);
    console.log(typeof timer);//返回的是对象
    console.dir(timer);//dir查看对象的属性和方法
    </script>
  • 通过标签获取:getElementsByTagName()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <ul>
    <li>你是大好人</li>
    <li>你是大好人</li>
    <li>你是大好人</li>
    <li>你是大好人</li>
    <li>你是大好人</li>
    </ul>
    <script>
    //返回的是 获取过来的元素对象的集合 以伪数组的形式存储
    let lis = document.getElementsByTagName('li');
    console.log(lis);
    console.log(lis[0]);
    //用for遍历
    for(let i = 0; i < lis.length; i++) {
    console.log(lis[0]);//得到的元素是动态的
    }
    //如果页面中只有一个li,返回的还是伪数组的形式
    //如果界面中没有元素,会返回一个空的伪数组
    </script>
    获取ul标签下的li标签
    element.getElementsByTagName(),获取的时候不包括父元素自己
    //获取文档中的所有ul,注意:伪数组不能作为父元素,一定要指明是哪一个
    let ul = document.getElementByTagName('ul');
    let li = ul[0].getElementByTagName('li');
  • 通过类名获取元素:document.getElementsByClassName(‘类名’)

  • 通过**querySelector()**获取元素,返回的是第一个元素对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //通过类名获取元素,返回一个伪数组
    let boxes = document.getElementsByClassName('box');
    //querySelctor返回指定选择器的第一个元素对象
    //通过类名.类名
    let firstbox = document.querySelector('.box');
    //通过id #id名
    let nav = document.querySelector('#nav');
    //通过标签名
    let li = document.querySelector('li');
  • 获取body元素:document.body

  • 获取html元素:document.documentElement

事件基础

事件:监控行为——————触发响应

事件三要素:事件源、事件类型、事件处理程序

1
2
3
4
5
6
7
8
9
10
11
12
<button id = "btn">唐伯虎</button>
<script>
//点击一个按钮,弹出对话框
//事件有三部分组成:事件源、事件类型、事件处理程序
//事件源:事件被触发的对象 按钮
let btn = document.getElementById('btn');
//事件类型: 如何触发 比如鼠标点击
//事件处理程序 通过一个函数赋值的方式完成
btn.onclick = function (){
alert('点秋香');
}
</script>

执行步骤三要素:

  1. 获取事件源
  2. 注册事件(绑定事件)
  3. 添加事件处理程序(采用函数赋值形式)

常见的鼠标事件

image-20220818003550188

操作元素

利用DOM操作元素来改变元素里面的内容、属性

改变元素内容

  • element.innerText

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <script>
    //当我们点击了按钮,div里面的文字会发生变化
    let btn = document.querySelector('button');
    let div = document.querySelector('div');
    btn.onclick = function () {
    div.innerText = getDate();
    }

    function getDate() {
    let date = new Date();//获得一个时间对象,里面不写内容就是当前时间,动态的
    let year = date.getFullYear();
    let month = date.getMonth() + 1;
    let dates = date.getDate();
    let arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
    let day = date.getDay();//获得星期几
    return '今天是:' + year + '年' + month + '月' + dates + '日' + arr[day];
    }

    //我们元素可以不用添加时间
    let p = document.querySelector('p');
    p.innerText = getDate();
    </script>
  • elemen.innerHTML

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <script>
    //innerText和innerHTML的区别
    //1.innerText 不识别html标签 非标准 去除空格和换行
    let div = document.querySelector('div');
    div.innerText = '<strong>今天是:2022<strong>'
    //1.innerText 识别html标签 W3C标准
    div.innerHTML = '<strong>今天是:2022<strong>'
    //这两个属性是可读写的 可以获取元素里面的内容 保留空格和换行
    p = document.querySelector('p');
    console.log(p.innerText);
    console.log(p.innerHTML);
    </script>

常见元素的属性操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
//修改元素属性 scr
//1.获取元素
let pic1 = document.getElementById('1');
let pic2 = document.getElementById('2');
let img = document.querySelector('img');
//2.注册事件
pic2.onclick = function (){
img.src = 'images/暂无考勤记录.png';
}
pic1.onclick = function (){
img.src = 'images/暂无回放.png';
}

</script>

表单元素的操作属性

常见表单属性:

  • type
  • value
  • checked
  • selected
  • disabled
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
//1.获取元素
let btn = document.querySelector('button');
let input = document.querySelector('input');
//2.注册事件 处理程序
btn.onclick = function (){
// input.innerHTML = '点击了'; 这个是普通盒子,比如div标签里面的内容
//表单里面的值 文字内容是通过value来修改的
input.value = '被点击了';
//如果想要某个表单被禁用 不能再点击 disabled
//btn.disabled = true;//禁用该表单
//也可以
this.disabled = true;//this指向的是时间函数的调用这,即btn
}
</script>

样式属性操作

  • element.style:行内样式操作

    1
    2
    3
    4
    test.onclick = function(){
    this.style.color = '#fff';
    this.style.fontSize = '25px';
    }
  • element.className:类名样式操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <div >
    文本
    </div>
    <script>
    const test = document.querySelector('div');
    test.onclick = function (){
    //点击后让div获取类名
    //让当前元素的类名改为change'
    this.className = 'change';

    //可以通过修改元素的classname更改元素的样式,适合于样式较多或者功能较复杂的情况
    //如果想要保留原先的类名,使用多类名选择器
    this.className = 'first change';
    }
    </script>

    image-20221023182746829

总结

image-20221024225404480

排他算法

image-20221024232758635
先排除其他人,在设置自己的样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
//1.获取所有按钮元素
const bts = document.getElementsByTagName('button');
//btns得到的是伪数组
for(let i = 0; i < bts.length; i++){
bts[i].onclick = function (){
//1.我们先把所有的按钮背景颜色去掉
for(let i = 0; i < bts.length; i++){
bts[i].style.backgroundColor = '';
}
//2.然后再让当前的颜色变为pink色
this.style.backgroundColor = 'pink';
}
}

数据库报错Incorrect string value: ‘\xE7\x94\xB7‘ for column ‘name‘ at row 1

image-20230312024828536

报错内容为在name列插入的第一条数据的字符串值是不正确的,主要原因是我插入的数据为汉字,为中文字符串,需要使用到utf-8字符集,而默认是使用的是latin1字符集。

解决方案:用这个命令更改表名,去覆盖它的原有字符集,就可以实现成功插入中文

1
ALTER TABLE interface_info(这里改成自己的表名) CONVERT TO CHARACTER SET utf8;

参考博文:https://blog.csdn.net/weixin_63639665/article/details/128206602

idea的全局搜索(替换)快捷键

可以鼠标选中想要搜索的内容在按快捷键或者按完快捷键后输入想要搜索的内容

  • ctrl+F 搜索范围为当前文件,不可替换

image

  • ctrl+R 搜索范围为当前文件,可替换

image-20230312034130905

  • ctrl+shift+R 搜索范围为整个项目,可替换

image-20230311230702057

利用idea和maven仓库下载依赖

以添加MyBatis Plus依赖为例

背景:用spring boot 初始化一个项目后,发现MyBatis Plus依赖没有添加

1.在maven仓库搜索mybaits-plus

仓库地址:https://mvnrepository.com(不同浏览器访问速度不一样,我用的火狐浏览器,感觉比用谷歌访问快很多,如果无法访问,可以换浏览器试试)

image-20230311053841423

点击选中使用最多的包

2.版本可以自行选择,尽量选择使用人数比较多的那个版本

image-20230311053955492

3.如果使用maven管理的包,直接复制框中的代码

image-20230311054228774

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>

4.将复制的代码黏贴到pom.xml文件的依赖标签<dependencies>下,同时点击右上角的M图标进行更新

image-20230311054522516

右上角没有图标的话,可以右边栏(或者在左边)的Maven标签打开配置栏

image-20230311054738541

点击刷新按钮进行更新下载依赖

image-20230311054938693