微尘的个人博客 - 学习笔记
type: channel
link: https://www.qaani.com/category/notes
description: 学习笔记
items: Redis
items: 内网穿透
items: Docker
items: 依赖注入
items: 排序
items: 树与二叉树
items: 栈和队列
items: Webpack
items: 实用方法(ajax、封装)
items: 操作DOM对象（重点）

Redis
type: item
date: 2023-06-05T17:04:00+08:00
description: 五种基本数据类型主要包括常见的5种数据类型，分别是：String、List、Set、Zset、Hash。结构类型结构存储的值结构的读写能力String 字符串可以是字符串、整数或浮点数对整个字符串或字符串的一部分进行操作；对整数或浮点数进行自增或自减操作；List 列表一个链表，链表上的每个节点都包含一个字符串对链表的两端进行push和pop操作，读取单个或多个元素；根据值查找或删除元素；Set 集合包含字符串的无序集合字符串的集合，包含基础的方法有看是否存在添加、获取、删除；还包含计算交集、并集、差集等Hash 散列包含键值对的无序散列表包含方法有添加、获取、删除单个元素Zset 有序集合和散列一样，用于存储键值对字符串成员与浮点数分数之间的有序映射；元素的排列顺序由分数的大小决定；包含方法有添加、获取、删除单个元素以及根据分值范围或成员来获取元素String字符串String是redis最基本的类型，一个key对应一个value。String类型是二进制安全的，意思是redis的string可以包含任何数据，比如jpg图片或者序列化的对象。String类型是redis最基本的数据类型，一个redis中字符串value最多可以是512Mset (key) (value) # 设置键值对 setnx (key) (value) # 防止覆盖，设置键值对， #如果key不存在就设置，返回1 #如果key已经存在就不设置，返回0 get(key) # 获取key对应的value getset (key) (value)# 先get再set，返回旧值，如果没有旧值返回nil append (key) (value)# 向指定的key的value后追加字符串 del (key) # 删除key strlen (key) # 获取key对应值的字符串长度数字value的加减incr (key) `：value + 1` decr (key) `：value - 1` incrby (key) (number)`：value + number` decrby (key) (number)`：value - number`获取或者设置指定范围内的值getrange (key) (begin) (end) # 获取[begin,end]下标范围内的值，如果是(0,1)就是获取所有值 setrange (key) (begin) (xxxx) # 从begin下标开始设置xxx值，将原有的替换掉设置键值过期时间setex (key) (seconds) expire # 设置键过期时间 ttl (key) # 查看key剩余存活时间https://blog.csdn.net/qq_50596778/article/details/124554777常见面试问题

内网穿透
type: item
date: 2022-11-21T16:26:03+08:00
description: 内网穿透概念内网穿透简单来说就是将你电脑访问和别人电脑访问通过natapp隧道打通，让内网的数据能在别人的电脑上可以获取。换个说法就是将原本只能在本机上访问的项目网站等，通过内网穿透使得你可以在其他人的网上进行访问。为什么要使用内网穿透？要想让你的项目可以实现在网络上进行访问和使用。要么将你的项目部署到云服务器上，要么通过内网穿透使得他人可以访问原本只在你的计算机上项目接口。但是如果使用第一种方法，如果项目出现问题后，就必须得将项目重新部署到云服务器上，而且还需要公网IP和服务器。但使用内网穿透可以直接实现本地调试，比较方便。那什么时候使用？公司交付 甲方！内网穿透工具花生壳、Sunny-Ngrok内网穿透服务

Docker
type: item
date: 2022-11-21T16:24:31+08:00
description: 如果对于容器和镜像还无法区分：https://blog.csdn.net/yao694899744/article/details/105307150?spm=1001.2014.3001.5502Docker底层原理Docker是怎么工作的？Docker 是一个 Client - Server（C/S） 结构的系统。Dokcer的守护进程运行在主机上。通过Socket从客户端访问！DockerServer 接受到 Docker-Client 的指令，就会执行这个命令！Dokcer 为什么比 VM 快？1、Dokcer 有着比虚拟机更少的抽象层2、Dokcer 利用的是宿主机的内核， VM 需要 Guest OS。所以说，新建一个容器的时候，docker不需要像虚拟机一样重新加载一个操作系统内核，避免引导。虚拟机是加载 Guest OS，分钟级别的，而docker 是利用宿主机的操作系统，省略了这个复杂的过程，秒级！Docker常用命令帮助命令docker version #显示docker的版本信息 docker info #显示docker的系统信息，包括镜像和容器的数量 docker 命令 --help #帮助命令帮助文档的地址：https://docs.docker.com/engine/reference/commandline/镜像命令C:\Users\lookchem>docker images REPOSITORY TAG IMAGE ID CREATED SIZE casimg dev 75fda16afbb3 6 weeks ago 186MB mcr.microsoft.com/dotnet/runtime 5.0 da195286baf8 4 months ago 186MB mcr.microsoft.com/dotnet/aspnet 5.0 99323686c908 5 months ago 205MB #解释 REPOSITORY 镜像的仓库源 TAG 镜像的标签 IMAGE ID 镜像的id CREATED 镜像的创建时间 SIZE 镜像的大小 #可选项 -a, --all Show all images (default hides intermediate images)#列出所有镜像 --digests Show digests -f, --filter filter Filter output based on conditions provided --format string Pretty-print images using a Go template --no-trunc Don't truncate output -q, --quiet Only show image IDs(只显示镜像的id) docker search 搜索镜像C:\Users\lookchem>docker search mysql NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 13234 [OK] mariadb MariaDB Server is a high performing open sou… 5062 [OK] #可选项 通过搜索来过滤 --filter=STARS=3000 #搜索出来的镜像就是STARS大于3000的 C:\Users\lookchem>docker search mysql --filter=stars=3000 NAME DESCRIPTION STARS OFFICIAL AUTOMATED mysql MySQL is a widely used, open-source relation… 13234 [OK] mariadb MariaDB Server is a high performing open sou… 5062 [OK] -f, --filter filter Filter output based on conditions provided --format string Pretty-print search using a Go template --limit int Max number of search results (default 25) --no-trunc Don't truncate output docker pull 下载镜像# 下载镜像 docker pull 镜像名[:tag] C:\Users\lookchem>docker pull mysql Using def…

依赖注入
type: item
date: 2022-11-21T16:21:48+08:00
description: 依赖注入基本类库最大的引用场景：项目的可拓展性、灵活性管理复杂的依赖关系消除new依赖注入（本身是一个核心对象）：IOC容器(控制反转)映射依赖、注册类型、注册服务实例解析.Net Core 是由 基础类库+拓展类库(依赖注入框架....).Net Core 原生DI（内置依赖注入框架）而依赖注入是基石Microsoft.Extesions.Dependencyinjection //具体实现 Microsoft.Extesions.Dependencyinjection.Abstractopms //抽象、基础类型、 ServiceProVider//根容器服务范围3中生命周期：单例、作用域、瞬时单例模式 —— 根容器（保存在根容器上，下次就可以直接获取）作用域模式 —— 当前容器（子容器）瞬时模式 —— 一次性不保存​ ASP.NET Core应用 —— 全局根容器(自带的)​ 只有子容器，没用孙子容器。不管有多少孙子都是和子容器同级。​ 子容器只关心根容器，不会在意谁是父容器，也不会知道父容器是谁。​ 每一个 作用域对象 都是有明确的边界，针对每个 HTTP请求上下文​ 一个请求上下文就是一个作用域 (绑定).NET Core 用于提供服务实例的容器有两种Application ServiceProvider（程序本身）Request SericeProvider（请求所创建）请求 —— 创建服务范围 —— 子容器(瞬时、作用域) —— 处理请求所需的服务容器可以提供构造函数所需的所有参数如果某个构造函数的参数类型集合能够成为所有合法构造函数参数类型的超集，那么这个构造函数就会被容器选择扩展类库Autofac: 扩展类库 第三方依赖注入框架（里面有非常丰富的注册功能。例如：属性注入、程序集注入）Scrutor: .Net内置DI的扩展包，弥补内置DI服务注册方式​

排序
type: item
date: 2022-03-02T19:56:00+08:00
description: 1、排序的概念及其运用1.1、排序的概念排序：所谓排序，就是使一串记录，按照其中的某个或某些关键字的大小，递增或递减的排列起来的操作。稳定性：假定在待排序的记录序列中，存在多个既有相同的关键字的记录。若经过排序，这些记录的相对次序保持不变，即在原序列中，r[i] = r[j] ,且r[i]在r[j]之前，而在排序后的序列中，r[i]仍在r[j]之前。则称这种排序算法是稳定的；否则称为不稳定。内部排序：数据元素全部放在内存中的排序。外部排序：数据元素太多不能同时放在一个内存中，根据排序过程的要求不能在内外存之间移动数据的排序。1.2、排序的运用1.3、常见的排序算法2、插入排序2.1、基本思想直接插入排序是一种简单的插入排序法，其基本思想是：把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中，直到所有的记录插入完为止，得到一个新的有序序列。实际中我们完扑克牌时，就是用了插入排序的思想2.2、直接插入排序当插入第i(i>=1)个元素时，前面的array[0]，array[1]，......array[i-1]已经排好序，此时用array[i]的排序码与array[i-1]，array[i-2]，.....的排序码顺序进行比较，找到插入位置即将array[i]插入，原来位置上的元素顺序后移。//插入排序 void InsertSort(int*a,int n) { // [0,end] 有序 end+1位置的值插入进去，让[0,end+1]有序 for (int i = 0; i < n-1; ++i) { int end= i; int tmp = a[end + 1]; while (end >= 0) { if (a[end] > tmp) { a[end + 1] = a[end]; --end; } else { break; } a[end + 1] = tmp; } } }直接插入排序的特性总结：元素集合越接近有序，直接插入排序算法的时间效率越高。时间复杂度：O(N^2^)空间复杂度：O(1)，它是一种稳定的排序算法稳定性：稳定2.3、希尔排序(缩小增量排序)希尔排序法又称缩小增量法。基本思想是：先选定一个整数，把待排序文件中的所有记录分成个组，所有距离为gap的记录分在同一组内，并对每一组内的记录进行排序。然后，取，重复上述分组和排序的工作。当到达gap=1时，所有记录在统一组内排好序。void ShellSort(int* a, int n) { //int gap = 1; //////把间隔为gap的多组数据同时排 //for (int i = 0; i < n - gap; ++i) //{ // int end = i; // int tmp = a[end + gap]; // while (end >= 0) // { // if (a[end] > tmp) // { // a[end + gap] = a[end]; // --end; // } // else { // break; // } // } // a[end + gap] = tmp; //} //那么问题来了 //gap 到底给多少呢？ int gap = n; while (gap > 1) { //gap = gap / 2; // logN gap = gap / 3 + 1; // log3N 以3为底数的对数 // gap > 1时都是预排序 接近有序 // gap == 1时就是直接插入排序 有序 // gap很大时，下面预排序时间复杂度O(N) // gap很小时，数组已经很接近有序了，这时差不多也是(N) // 把间隔为gap的多组数据同时排 for (int i = 0; i < n - gap; ++i) { int end = i; int tmp = a[end + gap]; while (end >= 0) { if (a[end] > tmp) { a[end + gap] = a[end]; end-=gap; } else { break; } } a[end + gap] = tmp; } } }希尔排序的特征总结 ：希尔排序是对直接插入排序的优化。当 gap > 1 时都是预排序，目的是为了让数组跟接近与有序。当 gap==1 时，数组已经接近有序，这样就会很快，这样整体而言，可以达到优化的效果。我们实现后可以进行性能测试和对比。希尔排序的时间复杂度不好计算，推导出来平均时间复杂度：O(N^1.3^至N^2^)稳定性：不稳定3、选择排序3.1、基本思想每一次从待排序的数据元素中选出最小（或最大）的一个元素，存放在序列的起始位置，直到全部待排序的数据元素排完。3.2、直接选择排序…

树与二叉树
type: item
date: 2022-03-02T16:41:00+08:00
description: 树与二叉树1.树的概念及结构（了解）2.二叉树概念及结构3.二叉树常见OJ题练习1.树的概念及结构（了解）1.1树的概念树是一种非线性的数据结构，它是由n（n>=0）个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像以可倒挂的树，也就是说它是根朝上，而叶朝下的。有一个特殊的结点，称为根节点，根节点没有前驱结点除根结点外，其余结点被分为M（M>0）个互不相交的集合T1、T2、T3、......、Tm，其中每一个集合Ti（1<=i<=M）又是一颗结构与树类似的子树。每棵子树的根结点有且只有一个前驱，可以有0个或多个后继因此，树是递归定义的。节点的度：一个节点含有的子树的个数称为该节点的度；如上图：A的为6叶节点或终端节点：度为0的节点称为叶节点；如上图：B、C、H、I...等节点为叶节点非终端节点或分支节点：度不为0的节点：如上图：D、E、F、G...等节点为分支节点双亲结点或父节点：若一个节点含有子节点，则这个节点称为其子节点的父节点；如上图：A是B的父节点孩子节点或子节点：一个节点含有的子树的根节点称为该节点的子节点；如上图B是A的孩子节点兄弟节点：具有相同父节点的节点互称为兄弟节点；如上图：B、C是兄弟节点树的度：一棵树中，最大的节点的度称为树的度；如上图：树的度为6节点的层次：从根开始定义起，根为第1层，根的子节点为第2层，以此类推；树的高度或深度：树中节点的最大层次；如上图：树的深度为4节点的祖先：从根到该节点所经分支上的所有节点；如上图：A是所有节点的祖先子孙：以某节点为根的子树中任一节点都称为该节点的子孙。如上图：所有节点都是A的子孙森林：由m（m>0）颗互不相交的多棵树的集合称为森林；（数据结构中的学习并查集本质就是一个森林）1.2树的表示树结构相对线性表就比较复杂了，要存储表示起来就非常麻烦了，实际中树有很多种表示方法，如：双亲表示法，孩子表示法，孩子兄弟表示法等等。我们这里就简单的了解其中最常用的孩子兄弟表示法一种表示方式： struct TreeNode { int data; vector<struct TreeNode*> childs;//C++ } 另一种发送：左孩子右兄弟 如下图所示typeof int DataType; struct Node { struct Node* _firstChilds; //第一个孩子结点 struct Node* _pNextBrother; //指向其下一个兄弟结点 DataType _data; //结点中的数据域 }第三种表示法：双亲表示法双亲表示法原理：就是存双亲的下标；例如上图：A-0,B-0,C-0、D-1(A)1.3树在实际中的运用（表示文件系统的目录树结构）2.二叉树概念及结构2.1概念一颗二叉树是结点的一个有限集合，该集合或者为空，或者是由一个根结点加上两颗别称为左子树和右子树的二叉树组成。二叉树的特点：每个结点最多有两颗子树，即二叉树不存在度大于2的结点。二叉树的子树有左右之分，其子树的次序不能颠倒。2.2现实中的二叉树2.3数据结构中的二叉树：2.4特殊的二叉树：满二叉树：一个二叉树，如果每一层的结点都达到最大值，则这个二叉树就是满二叉树。也就是说，如果一个二叉树的层数为K，目结点总数是(2^K^)-1=N，层数则等于log2^N+1^。则它就是满二叉树。完全二叉树：完全二叉树是效率很高的数据结构，完全二叉树是由满二叉树而引出来的。对于深度为K的，有n个结点的二叉树，当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点——对应时称之为完全二叉树。要注意的是满二叉树是一种特殊的完全二叉树。​ 目结点总数是(2^K^)-1-x=N。K=log2^N+1+x^​ 搜索二叉树(特别适合搜索)：任何一颗数，左子树都比根小，右子树都比根大；(这样的增删查改就有意义了)堆：堆的逻辑结构（想象出来的结构）是一个完全二叉树，而物理结构是一个数组。堆的两大特征结构性：用数组表示的完全二叉树。有序性：任一结点的关键字是其子树所有结点的最大值（或最小值）最大堆(MaxHeap)，也称大顶堆：最大值要求：树中所有的父亲都要大于等于孩子最小堆(MinHeap)，也称小顶堆：最小值要求：树中所有父亲都要小于等于孩子那么既然是用数组来表示怎么来确定左右孩子呢？​ 左孩子：LeftChild = Parent*2+1​ 右孩子：RightChild = Parent*2+2​ 父亲：Parent = (Child - 1) / 2 （Parent单数减一，双数减二，但在程序中减一即可） for (int i = (n-1-1)/2; i >= 0; --i) { AdjustDwon(); }2.5二叉树的存储结构二叉树一般可以使用两种结构存储，一种顺…

栈和队列
type: item
date: 2022-03-02T15:06:00+08:00
description: 栈1.栈的表示和实现1.1栈的概念及结构栈：一种特殊的线性表，其只允许在固定的一段进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶，另一端称为栈底。栈中的数据元素遵循后进先出LIFO（Last In First Out）的原则压栈：栈的插入操作叫做进栈/压栈/入栈，入数据在栈顶。出栈：栈的删除操作叫做出栈。入数据也在栈顶。栈有两种实现方式：数组、链表数组：相当于之前顺序表的尾插，尾插用尾去做了栈顶，非常合适。唯一缺陷就是：空间不够需要增容链表单链表：使用单链表就优点不合适了，除非将链表的链尾当作栈底、链头当栈顶。栈顶插入就等于链表头插入O(1)双链表：如果用尾做栈顶，那么就要用双向链表更好。效率O(1) **但一般栈的实现都会使用数组来实现**（数组的cpu缓存命中要略高一些(**预加载**)） 声名：#define _CRT_SECURE_NO_WARNINGS 1 #ifndef _TEST_H #define _TEST_H //栈的链式存储结构； typedef struct Node //创建一种类型的节点； { int data; struct Node * pnext; }NODE, *PNODE; typedef struct Stack //创建一个栈类型，里面含有两个指针，一个指向栈顶，一个指向栈底 { PNODE ptop; PNODE pBottom; }STACK, *PSTACK; void init(PSTACK ps);//初始化栈 void push(PSTACK ps, int val);//压栈 void traverse(PSTACK ps);//遍历栈 bool empty(PSTACK ps);//判断栈是否为空 bool pop(PSTACK ps, int * pval);//出栈 void clear(PSTACK ps);//清空栈 #endif //_TEST_H具体实现：#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <malloc.h> #include <stdlib.h> #include <stdbool.h> #include "test.h" int main() { //int val;//保存出栈的元素 STACK S;//定义一个栈变量 init(&S);//初始化这个栈 push(&S, 1);//压栈 push(&S, 2); push(&S, 3); push(&S, 4); push(&S, 5); push(&S, 6); traverse(&S);//遍历 /*if (pop(&S, &val))//出栈 { printf("出栈成功!出栈元素为%d \n", val); printf("-------------------------------------------------------\n"); } else { printf("出栈失败！\n"); }*/ //traverse(&S); clear(&S);//清空 printf("-------------------------------------------------------\n"); printf("清空后栈中元素为："); printf("栈中元素为：\n"); traverse(&S); //free（S）;//销毁栈 system("pause"); return 0; } void init(PSTACK ps) { ps->ptop = (PNODE)malloc(sizeof(NODE));//创建一个空栈 if (NULL == ps->ptop) { printf("success\n"); exit(-1); } else { ps->pBottom = ps->ptop;//栈底指针跟栈顶指针都指向这个新建的空节点 ps->ptop->pnext = NULL; } } void push(PSTACK ps, int val)//压栈 { PNODE pNew = (PNODE)malloc(sizeof(NODE));//新建一个节点 pNew->data = val;//新节点数据域等于val pNew->pnext = ps->ptop;//新节点指针域指向栈顶指针所指向的节点，就是前面栈底跟栈顶同时指向的空节点，这样就实现压栈了 ps->ptop = pNew;//然后栈顶元素上移，始终指向就是最后入栈的节点 } void traverse(PSTACK ps)//遍历 { PNODE p = ps->ptop;//遍历是从栈顶依次输出，所以创…

Webpack
type: item
date: 2021-10-15T13:33:00+08:00
description: 什么是Webpack​ 本质上，Webpack 是一个现代 JavaScript 应用程序的静态模块打包器（module bundler）。当webpack 处理应用程序是，它会递归地构建一个依赖关系图（dependency graph），其中包含应用程序需要的每个模块，然后将所有这些模块打包成一个或多个bundle。​ Webpack是当下最热门的前端资源模块化管理和打包工具，它可以将许多松散耦合的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分离，等到实际需要再异步加载。通过loader转换，任何形式的资源都可以当做模块，比如 CommonsJS、AMD、ES6、CSS、JSON、Coffeescript、LESS等；​ 伴随着移动互联网的大潮，当今越来越多的网站已经从网页模式进化到了 WebApp模式。它们运行在现代浏览器里，使用 HTML、CSS3、ES6 等新的技术来开发丰富的功能，网页已经不仅仅是完成浏览器的基本需求；WebApp 通常是一个 SPA（单页面应用），每一个视图通过异步的方式加载，这导致页面初始化和使用过程中会加载越来越多的 JS 代码，这给前端的开发流程和资源组织带来了巨大挑战。​ 前端开发和其他开发工作的主要区别，首先是前端基于多语言、多层次的编码和组织工作，其次前端产品的交付是基于浏览器的，这些资源是通过增量加载的方式运行到浏览器端，如何在开发环境组织好这些碎片化的代码和资源，并且保证他们在浏览器端快速、优雅的加载和更新，就需要一个模块化系统，这个理想中的模块化系统是前端工程师多年来一直探索的难题。模块化的演进Script 标签 ​ 这是最原始的 JavaScript 为文件加载方式，如果把每一个文件看做是一个模块，那么他们的接口通常是暴露在全局作用域下，也就是定义在 window 对象中，不同模块的条用都是一个作用域。​ 这种元素的加载方式暴露了一些显而易见的弊端：全局作用域下容易造成变量冲突文件只能按照 7. 在IDEA 控制台中直接执行webpack；如果失败的话，就使用管理员权限运行即可！8.运行 HTML 看效果 说明：webpack --w

实用方法(ajax、封装)
type: item
date: 2021-10-15T13:20:00+08:00
description: ajax H5 游客姓名 入境时间 出境时间 国籍名称 ajax主要使用XMLHttpRequest，也可以将ajax看做一个方法后台//首先需引用 using Newtonsoft.Json; public string GetTourists()//ajax调用GetTourists 返回一个json数组 在前端 进行数值绑定 { var tours = db.Tourists.Select(p => new { p.TouristID, p.TouristName, p.StartTime, p.EndTime, p.Nationality.NationalityName }); return JsonConvert.SerializeObject(tours); } 可实用的方法Model封装 数据库对象 用户姓名 证件号 入境时间 出境时间 头像 国籍 中国 美国 条件:前端name必须和数据库列名相同//数据封装 装箱 Tourist tourist = new Tourist(); tourist.TouristName = Request["TouristName"]; tourist.CardID = Request["CardID"]; tourist.StartTime = Convert.ToDateTime(Request["StartTime"]); tourist.EndTime = Convert.ToDateTime(Request["EndTime"]); tourist.HeadPic = Request["HeadPic"]; tourist.NationalityID = Convert.ToInt32(Request["NationalityID"]); Tourist tourist = RequesModel<Tourist>(); //和下面方法等同Tourist tourist = RequesModel<Tourist>(); public T RequesModel<T>() where T : new() //where T:new()表示泛型约束,T类型 { T model = new T(); //获取对象的所有属性 Type modelType = model.GetType(); //从类型对象中获取该对象的所有属性 PropertyInfo[] props = modelType.GetProperties(); //遍历所有的属性 foreach (var prop in props) { //取出属性的名称 string propName = prop.Name; //按属性名称获取表单数据 string propVal = Request[propName]; //判断获取的值是否存在 if (!string.IsNullOrEmpty(propVal)) { //值获取到 就可以给model赋值了 //获取属性的数据类型 Type propType = prop.PropertyType;//可能存在可空类型 所有需要判断 //获取可空类型的基础类型 Type underType = Nullable.GetUnderlyingType(propType); prop.SetValue(model,Convert.ChangeType(propVal,underType??propType));//给model对象的prop对应的属性赋值 //??的意思是如果前方为空就获取后方 前方不为空就获取前方 } } return model; }

操作DOM对象（重点）
type: item
date: 2021-10-15T11:08:00+08:00
description: 简介[scode type="blue"]DOM：文档对象模型[/scode][scode type="blue"]BOM：浏览器对象模型[/scode]核心浏览器网页就是一个DOM树形结构！更新：更新DOM节点遍历DOM节点：得到DOM节点删除：删除一个DOM节点添加：添加一个新的节点那么要操作一个DOM节点，就必须要先获得这个DOM节点获得DOM节点 java 陈捷 李泽群 链接1 链接2 链接3 链接4 链接5 123 这是原生代码，之后尽量都是用jQuery();1、更新节点var a = document.getElementById('id1') undefined a.innerText= 666 //插入修改节点 666 a.innerHTML = '666' "666"操作文本a.innerText= 666 修改文本值（但会覆盖节点）a.innerHTML = 666 可以解析HTML文本标签操作JS（JavaScript能让网页上变动）样式id1.style.color = 'red' //属性使用 字符串 包裹 id1.style.color = 'yellow' id1.style.fontSize = '200px' // - 转 驼峰命名问题2、删除节点删除节点的步骤：先获取父节点，再通过父节点删除自己。 java 傻逼陈捷 傻逼李泽群 注意：删除多个节点的时候，children是时刻在变化的，删除节点的时候一定要注意~3、插入节点先获得某个DOM节点，假设这个DOM节点是空的，我们通过innerHTML，就可以增加一个元素。但如果这个DOM节点本身存在元素，那么innerHTML会将原本的元素覆盖！ 那么最好是在后面追加元素appendappendChild() //追加到后面 JavaScript C# Java C++ 创建新标签，实现插入document.createElement('p')//通过js 创建一个新的节点 var newP = document.createElement('p');//创建一个p标签 newP.id = 'newP'; newP.innerText = '666我的宝贝'; salf.appendChild(newP); //将p标签追加在salf后面 包括也能添加Script、cssvar dd = document.getElementById('id2'); 'use strict' //创建一个标签节点 var myScript = document.createElement('script'); myScript.setAttribute('type','text/javascript')//非常多的玩法，只有你想不到，没有他做不到，所以为什么javascript这么随意 var body = document.getElementsByTagName('body') body[0].style.backgroundColor = '#000';//第一种增加方式 body[0].setAttribute('style','background-color: rgb(0, 0, 0);')//第二种方式，建议使用第二种，因为后端都是通过这种方式去增加 //需要注意的是像这种取值，取到的是一个集合第三种方式//可以创建一个Style标签 var myStyle = document.createElement('style');//创建一个空style标签 myStyle.setAttribute('type','text/css'); myStyle.innerHTML = 'boby{background-color:chartreuser}';//设置标签内容 document.getElementByTagName('head')[0].appendChild(myStyle);JavaScript方法方式许许多多，只要逻辑行的通都可以。insertinsertBefore方法可在已有的子节点前插入一个新的子节点 JavaScript C# Java C++ replaceChild(newNode,oldNode) 替换节点··removeChild(Node) 删除子节点