基础
一、简单介绍
js组成
- 核心ECMAScript
- 文档对象模型(DOM),如:点击
- 浏览器对象模型(BOM),如:滚动条到顶端的距离
js特点
- 弱类型语言
- 面向对象
- 无需编译
JS数据类型
JavaScript 的数据类型有数字、字符串、布尔型、对象类型、数组、null和undefined
十六进制:0x
科学技术法:2e3 2000
浏览器内核的作用
- 内容排版解析HEML、CSS
- 脚本解释引擎解析js
二、语法
基础
输出
- console.log()
- document.write();
- alert();
语法规范
- 大小写敏感
- 分号结束
- 英文符号
变量
var a = 2.5;
//省去var,则声明的是全局变量
命名规范
- 不允许使用JS的关键字和保留关键字
- 由字母、数字、下划线、$组成
- 不能以数字开头
- 驼峰命名法
变量异常
输出未赋值的值
undefined
输出未定义的值
not definded
三、数据类型
数据类型
number类型(可以表示32位的整数以及64位的浮点数):整数、浮点数
string类型:unicode下字符占2字节,\u4e000汉字开头,\u9fa5汉字结束
boolean类型:
null类型:未定义对象
undefined:声明变量未赋值,访问对象不存在的属性
object类型:
var obj = {
name:"ming",
id: 2
}
隐式转换
- 函数:typeof()或typeof; typeof num;
- NaN:isNaN(),返回boolean,是数字false,不是数字true
强制转换
toString()一般数字转字符串,
num.toString(16);输出num的16进制字符串
String(a)
强制类型转换,可以转换null和underfined
parseInt( , 原进制):
获取指定数据的整数部分,遇到非整数字符,停止转换,第一个字符就不是,返回NAN,not a number,
paresFloat()
Number():
包含非整数字符返回NaN,严格
Boolean():
Boolean(“js”);
0,null,underfined为false
四、运算符和表达式
算数运算符
除法:15/2 = 7.5
关系运算符
===全等
!==不全等
函数
Math.random()
五、数组
创建
var arr1 = [];
var arr2 = new Array();
arr1[0] = 1;
//数组长度
var length = arr1.length;
特殊
- 不限制数组元素个数
- 不限制下标越界,获取值:返回undefined,修改值,自动创建新元素
- 不限制元素的数据类型
插入
头部操作
添加
arr.unshift ()
arr.unshift(“lala”)
尾部添加元素并返回新的长度
删除
arr.shift()
删除头部第一个元素并返回
尾部操作
添加
arr[arr.length] = “??”;
arr.push(“??”);
返回新的数组长度
删除
arr.length = arr.length - 1;
delete 使元素为空,长度不变
delete arr[arr.lenght - 1];
arr.pop() 删除并返回该元素
关联数组
var useriInfo = [];
userInfo['myName'] = '孙悟空';
//循环,hash
for(var myname in userInfo){
document.write(userInfo['myname'] + "<br>")
}
//length属性失效
//不能使用字符串输出
查找元素位置
indexOf()
lastIndexOf()
indexOf(“a”, 2) 从下标2开始查找
lastIndexOf(“a”, -2) 倒数第二个元素开始
数组合并
arr1.concat(arr2); ab数组不变,a连接b
数组倒置
arr.reverse() 原数组也倒置
元素合并
arr.join(“+”);
数组排序
arr.sort(); 字典排序
带参数
arr.sort(function(a, b){ //a,要插进来的元素
return a-b; //升序排序
})
提取子数组
slice(start, end); //包头不包尾
arr.slice(0, -2) //0到倒数第2个元素
数组遍历
for
forEach()
参数:数组元素,当前索引,数组对象
特点:无法被break中断
var numArr = [10,11,12,13,14];
numArr.forEach(function(mem,i,arr) {
mem *= 10;
arr[i] = mem;
});
六、数组API函数
数组转字符串
- String(arr); //用逗号分割
- arr.join(“、”); //使用、拼接成字符串
拼接和选取
不直接修改原数组,返回新数组
concat(1, 2, arr1, arr2);
slice()返回现有数组的一个子数组,含头不含尾
var arr = oldArr(0, 99);
arr = [1, 2, 3, 4, 5];
arr.slice(2); //从下标2到最后
arr.slice(-4, -2); //倒序,原数组:-4, -3, -2, -1, 0
修改元素
删除:splice直接修改原数组
splice(start, n); 删除下标starti位置开始的n个元素
插入:splice(start, 0, 值1, 值2);
替换:splice(start, n, 值1, 值2, 值3)
颠倒数组
arr.reverse(); //不会进行排序
排序
arr.sort();
数组filter
<script>
let arr = [1,2,3,4,5,6,8];
let newArr = arr.filter(function(arr){
return arr < 3;
});
console.log(newArr);
</script>
数组map
<script>
let arr = [1,2,3,4,5,6,8];
let newArr = arr.map(function(arr){
return arr * 2;
});
console.log(newArr);
</script>
数组reduce
<script>
let arr = [1,2,3,4,5,6,8];
let sum = arr.reduce(function(preValue, value){
return preValue + value;
}, 0);// (函数, 初始值)
console.log(sum);
</script>
<script>
let total = nums.filter(n => n < 100).map(n => n * 2).reduce( (pre, n) => pre + n);
</script>
七、对象
创建方法
- 对象字面量(最常用),键值对的集合
var song = {
name : "ming",
time : 234,
display:function(){
console.log(this.name);
}
}
- 工厂方法,函数创建对象
function createPeople(name, age){
var people = new Object();
people.name = name;
people.age = age;
people.display = function(){
console.log("???");
};
return people;
}
- 构造函数创建对象
function People(name, age){
this.name = name;
this.age = age;
}
var myPeople = new People("?", 34);
- 使用原型(prototype 非自有属性)创建对象
//每个函数都自动拥有prototype属性,这个属性的值是一个对象
function Store(){};
Store.prototype.name = "mong";
Store.protytype.location = "Hong Kong";
Store.prototype.saleVolue = 234;
var myStore = new Store();
属性的增删改查
获取
- student.name
- student[“name”]
修改
student.name = “??”;
删除
- delete Student.name;
属性的检测和枚举
属性检测
- 检查对象是否有某个属性或者方法:”name” in student
- 检测对象自有属性(不是继承的)或方法:school.hasOwnProperty(“id”);
枚举获取属性
- for in 可以枚举所有可枚举的属性,包括继承的属性
for( var i in student){
// 获取下标
}
for( var value of student){
// 直接获取值
}
- Object.getOwnPropertyNames(); 返回对象的所有自有属性的名字
//定义一个school对象
var school = {
name:"SJTU",
location:"ShangHai",
studentNum:40000,
display:function() {
console.log(this.name);
}
};
//为school对象增加一个不可枚举的属性range
Object.defineProperty(school, "range", {
value: 4,//设置range属性的值
enumerable: false//设置range属性为不可枚举
});
//输出["name","location","studentNum","display","range"]
console.log(Object.getOwnPropertyNames(school));
- object.keys()返回可枚举的自有属性,以字符串数组的形式
var school = {
name:"SJTU",
location:"ShangHai",
studentNum:40000,
display:function() {
console.log(this.name);
}
};
//为school对象增加一个不可枚举的属性range
Object.defineProperty(school, "range", {
value: 4,//设置range属性的值
enumerable: false//设置range属性为不可枚举
});
//输出["name","location","studentNum","display"]
console.log(Object.keys(school));
- 对比
方法名 是否要求可枚举 是否要求自有 for…in… 是 否 Object.getOwnPropertyNames() 否 是 Object.keys() 是 是
判断是否为空
Object.keys(myObject).length == 0;
JSON.stringify(myObject) === '{}';
八、函数
函数的所有形参:arguments[]
函数也可以作为实参传入
九、字符串
JSON.stringify();
JSON.parse();
长度: str.length
位置
str.indexOf() ;
str.lastIndexOf();
str.charAt( index );
截取
- slice( first, last) 包头不包尾
- substring( first, last) 负数下标自动转化为0,自动调整大小
- substr(first ,length) 从左到右
大小写
str.toLowerCase();
str.toUpperCase()
分割
a.split(/[ ,]/);
十、正则
var reg = new RegExp(字符串, ‘方式gim’);
a.split(/[ ,]/);
十一、常用类
Math类
表示 | 意义 | 约等于 |
---|---|---|
Math.E | e | 2.718 |
Math.PI | 圆周率 | 3.14 |
Math.SQRT2 | 2的平方根 | 1.414 |
Math.LN2 | 2的自然对数 | 0.693 |
Math.ceil(x)
Math.floor(x)
Math.random()
Math.sqrt(4)
Math.round(1.5)
Math.max(1,2,34,100);
方法 | 作用 |
---|---|
Math.abs(x) | 求x的绝对值 |
Math.pow(x,y) | 计算x的y次幂 |
Math.exp(x) | e的x次方 |
Math.log(x) | x以e为底的对数 |
Math.sin(x) | x的正弦 |
Math.cos(x) | x的余弦 |
Math.tan(x) | x的正切 |
Math.asin(x) | x的反正弦 |
Math.acos(x) | x的反余弦 |
Math.atan(x) | x的反正切(-PI/2到PI/2之间) |
Math.atan2(y,x) | x轴到点(x,y)的角度 (-PI/2到PI/2之间) |
Date类
构造函数
Date(x)
的参数x
可以有四种情况:
new Date();//无参数,返回当前时间
new Date(millseconds);//参数为距离1970年1月1日8时0分0秒0毫秒的毫秒数,返回对应的时间
new Date(timeString);//参数为时间字符串,返回这个时间字符串对应的时间
new Date(year,month,day,hour,minute,second,millsecond);//参数为整数序列,分别表示年、月、日、时、分、秒、毫秒,返回这些时间参数对应的一个特定的时间
console.log(new Date());//输出Sat Apr 07 2018 18:56:00
console.log(new Date(1000));//输出Thu Jan 01 1970 08:00:01
console.log(new Date("April 7, 2018 18:00:00"));//输出Sat Apr 07 2018 18:00:00
console.log(new Date(2018,4,7,18,0,0,0));//输出Mon May 07 2018 18:00:00
获取和设置年月日
//1970年1月1日上午8点0分0秒
var date = new Date(0);
console.log(date.getFullYear());//输出1970
//用于设置年份,month和day可选;
date.setFullYear(2017);
console.log(date);//输出Sun Jan 01 2017 08:00:00
x.getMonth();
//返回x中的月份,结果在0(一月)到11(十二月)之间
console.log(date.getMonth());//输出0
date.setMonth(2);
//作用是设置月份,0表示一月。1表示二月,依次类推,day可选
console.log(date);//输出Sun Mar 01 1970 08:00:00
x.getDate()
//返回x对象在一个月的第几天(1到31),x.getDay()返回x对象在一个星期的第几天(0到6,0为周日);
console.log(date.getDate());//输出1
console.log(date.getDay());//输出4
date.setDate(31);
//设置日期对象在一个月的第几天(1到31);
console.log(date.getDate());//输出31
获取和设置时分秒
方法 | 作用 | 参数或者结果的范围 |
---|---|---|
getHours() | 获取小时 | 0~23 |
setHours(hour,min,sec,millsec) | 设置小时 | 0 |
getMinutes() | 获取分钟 | 0~59 |
setMinutes(min,sec,millsec) | 设置分钟 | 0 |
getSeconds() | 获取秒钟 | 0~59 |
setSeconds(sec,millsec) | 设置秒钟 | 0 |
getMillSeconds() | 获取毫秒数 | 0~999 |
setMillSeconds(millsec) | 设置毫秒数 | 0~999 |
getTime() | 获取距1970年1月1日8时0分0秒的毫秒数 | 大于等于0 |
setTime(millsec) | 设置距1970年1月1日8时0分0秒的毫秒数 |
日期转字符串
onsole.log(new Date().toString());//输出Sat Apr 07 2018 20:40:14 GMT+0800 (中国标准时间)
try-catch捕获和处理错误
//求开方的值
function mySqrt(a) {
try {
if(a < 0)
throw new Error("错误!负数不能开平方");
if(a > 10000)
throw new Error("错误!不支持大数开平方");
return Math.sqrt(a);
} catch(err) {
console.log("发生错误,错误信息:"+err.message);
}
return "error";
}
十二、ES6
var、const、let
let存在缺陷
ES5之前: if与for没有块级作用域,共用循环i, for,使用闭包,函数存在作用域
ES5:闭包
for(var i = 0; i < btns.length; i++){
(function(i){
btn[i].addEventListener('click', function(){
console.log("i");
})
})(i);
/*函数中有自己的i,作用域
(function(){})(i);
*/
}
ES6 : let / const let存在自己的作用域,const常量
const btns = documents.getElementsByTagName('button');
//如果是var,只会是5
for(let i = 0; i < btns.length ; i++){
btns[i].addEventListener('click', function(){
console.log("点击"+ i);
})
}
const的对象不能修改,但是属性可以修改
对象增强写法
//1.属性增强方法
let name = "myname";
//直接赋值
let obj = {
name
}
//2.方法增强
let obj = {
run(){
console("ES6");
}
}
//未增强
let obj = {
run: function(){
}
}
两空格
箭头函数
const sum = (num1, num2) => {
return num1 + num2;
}
const power = num => {
return num * num;
}
const mul = (num1, num2) => num1 + num2;
箭头函数中的this 引用最近作用域的this
字符串
str.startsWith("")
.endWith("")
.includes("");
字符串模板
var str = `${age}你好`
解构
var test = ( {name} ) => console.log("hello", name)
test( {name: "sdf"} );
对象优化
Object.keys(person) // array[]
Object.values(person) // arrays[]
Object.entries(person) /* [
[ "name", "mingyue" ],
]*/
Object.assign(origin, newObj1) // 赋值到origin中
let newObject = Object.assign({}, originObj);
promise
状态
1.初始化,状态:pending
2.当调用resolve(成功),状态:pengding=>fulfilled
3.当调用reject(失败),状态:pending=>rejected
promise是异步编程的一种解决方案,如多层ajax嵌套
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("data"); //将数据传入下一步
// 或者
reject("error message")
}, 1000)
}).then((data) => {
// 正式进行处理
// 1. 进行链式
return new Promise((resolve) => {
resolve("data1"); // 交给下一个处理
})
// 2. 简洁链式
return Promise.resolve("data2");
return Promise.reject()
throw "error";
// 3. 更简洁
return "data2";
}).catch((err) => {
// 错误处理
})
// then(success(), err())
async异步
sync同步
异步运行
// 两个异步运行,都获取结果才then
Promise.all([
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('result1');
}, 2000)
}),
new Promise((resolve, reject)) => {
setTimeout(() => {
resolve('result2');
}, 1000)
}
]).then(results => {
console.log(results);
})
实现
通过定义两个变量来保证都运行完成
async await
promise一旦创建就会执行,可以用来同时做多个网络请求,等待结束,获取结果用Promise.all
如果用async就会直接放回promise对象,简化了步骤
await是用来做同步操作的,后面的promise执行完(如果不是promise则直接resolve)才会继续
简化
function logFetch(url) {
return fetch(url)
.then(response => response.text())
.then(text => {
console.log(text);
}).catch(err => {
console.error('fetch failed', err);
});
}
async function logFetch(url) {
try {
const response = await fetch(url);
console.log(await response.text());
}
catch (err) {
console.log('fetch failed', err);
}
}
样例
// ps:由于js本身现在已经限制了await必须用在async函数中,否则会报错。所以请将下面的复制粘贴到浏览器控制台查看结果
function asyncFn () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
if (true) {
console.log('resolve console')
resolve('resolve return')
} else {
reject('reject return')
}
}, 2000)
})
}
var value1 = await asyncFn()
var value2 = await 'plain text'
console.log(value1)
console.log(value2)
//浏览器会依次打印 ‘resolve console’ ‘resolve return’ ‘plain text’
数组filter
Array.filter(function(currentValue, indedx, arr), thisValue)
<script>
let arr = [1,2,3,4,5,6,8];
let newArr = arr.filter(function(arr){
return arr < 3;
});
console.log(newArr);
</script>
数组map
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
<script>
let arr = [1,2,3,4,5,6,8];
let newArr = arr.map(function(arr){
return arr * 2;
});
console.log(newArr);
</script>
数组reduce
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
<script>
let arr = [1,2,3,4,5,6,8];
let sum = arr.reduce(function(preValue, value){
return preValue + value;
}, 0);// (函数, 初始值)
console.log(sum);
</script>
<script>
let total = nums.filter(n => n < 100).map(n => n * 2).reduce( (pre, n) => pre + n);
</script>
对象解构
var obj = {
name: "",
age: 12
};
var {age, name} = obj;
push合并数组
arr.push(…ar2);
find - some - every - foreach
every()是对数组中每一项运行给定函数,如果该函数对每一项返回true,则返回true。
some()是对数组中每一项运行给定函数,如果该函数对任一项返回true,则返回true。
arr.find(item => item.flag); //找到第一个
arr.foreach(item = > .......);
var arr = [ 1, 2, 3, 4, 5, 6 ];
console.log( arr.some( function( item, index, array ){
console.log( 'item=' + item + ',index='+index+',array='+array );
return item > 3;
}));
console.log( arr.every( function( item, index, array ){
console.log( 'item=' + item + ',index='+index+',array='+array );
return item > 3;
}));
十三、其他概念
闭包
闭包实际上是一种函数
闭包的作用:
1、读取函数内部的变量;
2、让这些变量始终保持在内存之中。
优点:
1、不污染全局空间;
2、内部所有的临时变量执行完毕都会释放不占内存;
3、可以保存全局数据;
4、更新复杂变量
// 当一个内部函数被其外部函数之外的变量引用时,就形成了一个闭包
function test1(){
var age = 19;
}
console.log(age);//Uncaught Reference: age is not defined
function test1(){
var age=19;
return function test2(){
console.log(age)
}
}
var func = test1();
console.log("func",func); //返回的是test2函数
func(); // 19 返回的是test2函数的结果
十四、其他积累
apply/call/bind
var person = {
fullName: function(city, country) {
return this.firstName + " " + this.lastName + "," + city + "," + country;
}
}
var person1 = {
firstName:"Bill",
lastName: "Gates"
}
person.fullName.apply(person1, ["Oslo", "Norway"]);
person.fullName.call(person1, "Oslo", "Norway");
// bind
this.x = 9;
var module = {
x: 81,
getX: function() { return this.x; }
};
module.getX(); // 81
var retrieveX = module.getX;
retrieveX(); // 9
var boundGetX = retrieveX.bind(module);
boundGetX(); // 81
prototype
var a = {}, b = Object.prototype;
[a.prototype === b, Object.getPrototypeOf(a) === b]
[false,true]
宏任务、微任务
事件循环:
异步事件并不会放到当前任务执行队列,而是会被挂起,放入另外一个回调队列。当前的任务队列执行结束以后,JavaScript引擎回去检查回调队列中是否有等待执行的任务,若有会把第一个任务加入执行队列,然后不断的重复这个过程。
js 是一种单线程语言,需要模拟多线程执行同步和异步任务
宏任务和微任务都是异步任务
微任务:Promise.then、Object.observe、MutationObserver、process.nextTick(Node.js 环境)
宏任务一般是:script、setTimeout、setInterval、postMessage、MessageChannel、setImmediate(Node.js 环境),IO
执行顺序:
- 先执行同步代码
- 遇到异步宏任务则将异步宏任务放入宏任务队列中
- 遇到异步微任务则将异步微任务放入微任务队列中
- 当所有同步代码执行完毕后
- 再将异步微任务从队列中调入主线程执行
- 微任务执行完毕后再将异步宏任务从队列中调入主线程执行
- 一直循环直至所有任务执行完毕
错误的认识:微任务先于宏任务执行。
实际上是先执行同步任务然后在执行异步任务,异步任务是分宏任务和微任务两种的。
同一个执行队列产生的微任务总是会在宏任务之前被执行
console.log('1')
setTimeout(() => {
console.log('2')
})
new Promise((resolve, rejects) => {
console.log('3')
resolve()
}).then(() => {
let i = 0
while(i < 1000000000) {
i++
}
console.log('4')
})
let i = 0
while(i < 1000000000) {
i++
}
console.log(5)
// 1 3 5 4 2
DOM
对网页节点增删改查
Document Object Module
,简称DOM
,中文名文档对象模型。在网页上,组成页面(又叫文档)的一个个对象被组织在树形结构中,用这种结构表示它们之间的层次关系,表示文档中对象的标准模型就称为DOM
。
一、DOM查找
按ID属性精确查找
var elem = document.getElementById("myId");
按标签查找
var elems = parent.getElementsByTagName("tag")[0];
查找指定parent节点下的所有标签为tag的子代节点,ul,li
- 用于任意父元素上
- 所有子节点
- 返回动态几何,集合[0],取出元素
通过name属性查找
document.getElementsByName('name属性值');
返回DOM树种具有name属性值的所有子元素集合,checkbox
通过class查找
parent.getElementsByClassName("class");
返回数组
限制:ie9+
通过CSS选择器查找
- 查找第一个元素:
parent.querySelector("selector");
- 查找多个:
parent.querySelectorAll("selector");
返回非动态集合
二、DOM修改
- 核心DOM:可操作一切结构化文档的API,包括HTML,XML,万能但繁琐
- HTMLDOM:专门操作HTML文档的简化版DOM API,简单不是万能的
1.读取属性值
//1.先获取属性节点对象,
var attrNode = elem.attributes[下标/属性名];
var attrNode = elem.getAttributeNode(属性名);
attrNode.value---属性值
//2.直接获取属性值
var value = elem.src;
var value = elem.getAttribute("属性名");
2.修改属性值
//1.修改
elem.setAttribute("属性名", value);
elem.src="";
var h = document.getElementById("id");
h.setAttributeNode("name", mingyue);
//2.判断是否包含指定属性
var bool = elem.hasAttribute("属性名");
3.删除属性
elem.removeAttribute("属性名");
4.修改样式
elem.style.属性名
/* 去横线变驼峰
background-color => backgroundColor
*/
三、DOM添加
步骤
- 创建空元素
- 设置关键属性
- 将元素添加到DOM树
详细
- 创建节点
//1.创建空元素
var elem = document.createElement("元素名");
var table = document.createElement("tr");
var td = document.createElement("td");
- 设置关键属性
//2.设置关键属性
elem.id = "id";
//3.设置关键样式
elem.style.opacity = "1";
elem.style.cssText = "width:100px;height:40px";
- 添加到DOM树中
- appendChild(),在末尾添加
var div = document.createElement("div");
var txt = document.createTextNode("版权声明");
div.appendChild(txt);
document.body.appendChild(div);
- insertBefore(),在指定子节点之前添加一个新的子节点
ul.insetBefore(newLi, ul.lastChild);
添加优化
创建片段
var frag = document.createDocumentFragment();
将子元素临时追加到fragment中
frag.appendChild(child);
将fragment追加到页面中
parent.appendChild(frag); //frag自动释放,不占用元素
四、DOM删除
//第一步:获取父节点,即ul节点:
var parentNode = document.getElementById("parent");
//第二步:获取待删除的子结点:
var childNode = document.getElementById("child3");
//第三步:父节点调用removeChild()方法删除子节点:
parentNode.removeChild(childNode);
五、节点树上的操作
概念
- 父节点:逆着箭头方向的第一个节点,即为该节点的父节点;
- 子节点:顺着箭头方向第一层的若干个结点,一般不唯一,即为该节点的的子节点;
- 兄弟节点:父节点相同的节点互为兄弟节点;
- 第一个子节点:子节点中最左边的节点;
- 最后一个子节点:子节点中最右侧的节点;
- 节点类型,值为
9
时表示Document
节点(整个文档);值为1
表示Element
节点,即前面反复提到的文档元素;值为3
表示Text
节点,即节点里面的内容为纯文本,如``节点。
操作
获取节点
<script>
var div1 = document.getElementById("div1");
//firstElementChild表示第一个子节点
var cl1 = div1.firstElementChild;
//lastElementChild表示最后一个子节点
var aElement = cl1.lastElementChild;
console.log(aElement.innerText);
//前一个兄弟节点
var left = aElement.previousElementSibling;
console.log(left.innerText);
//后一个兄弟节点
var right = left.nextElementSibling;
console.log(right.innerText);
//子节点列表: children
var selectTag = document.getElementById("se");
console.log(selectTag.children[0].innerText);
console.log(selectTag.children[1].innerText);
console.log(selectTag.children[2].innerText);
//子节点的个数;
children.length;
</script>
获取属性值
文档元素.属性名
会返回属性实际的值,可能返回数值
getAttribute()
getAttribute()
返回的值统一为字符串className
class
等文档元素的属性,不能直接用文档元素对象.class
来获取,因为class
是JavaScript
中的关键字,需要用className
来代替。
替换节点
<script> replaceChild(new,old);</script>
选择省份,地区
<html>
<head>
<title>myTitle</title>
<meta charset="utf-8" />
</head>
<body>
<select id="province" onChange="changeCity()">
<option value="BeiJing" id="bj">北京</option>
<option value="AnHui" id="ah">安徽</option>
</select>
<select id="city">
<option value="BeiJingCity">北京市</option>
</select>
<script>
function changeCity() {
var province = document.getElementById("province");
var city = document.getElementById("city");
var length = city.children.length;
for(var i = length-1;i >= 0;i--) {
city.removeChild(city.children[i]);
}
if(province.value == "BeiJing") {
var child1 = document.createElement("option");
child1.value="BeiJingCity";
child1.innerText="北京市"
city.appendChild(child1);
} else {
var child1 = document.createElement("option");
child1.value="HuangShanCity";
child1.innerText="黄山市";
city.appendChild(child1);
//请在此处编写代码
/*********Begin*********/
var child2 = document.createElement("option");
child2.value = "HeFeiCity",
child2.innerText = "合肥市";
city.appendChild(child2);
/*********End*********/
}
}
</script>
</body>
</html>
六、事件处理
表单提交:onsubmit 属性:submit
表单重置:onreset 属性:reset
事件添加
<form id="myForm"></form>
var myForm = document.getElementById("myForm");
//1.addEventListener(类型, 函数)函数
myForm.addEventListener("submit",function() {
console.log("表单提交中");
});
//2.直接添加 on...
myForm.onsubmit = myclick();
文档加载事件
当文档加载完成后,就会触发文档加载事件监听程序(即上一关所说的事件处理程序),一般我们会在这个时候监测用户浏览器的类型、版本,从而加载不同的脚本。
<body onload="detectBrowser()"></body>
function detectBrowser(){
var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
if (userAgent.indexOf("Opera") > -1) {//判断是否是Opera浏览器
console.log("Opera");
};
if (userAgent.indexOf("Firefox") > -1) { //判断是否是Firefox浏览器
console.log("Firefox");
}
if (userAgent.indexOf("Chrome") > -1) { //判断是否是Chrome浏览器
console.log("Chrome");
}
if (userAgent.indexOf("Safari") > -1) {//判断是否是Safari浏览器
console.log("Safari");
}
if (userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1) {
console.log("IE");
};
}
常见的鼠标事件
类型 | 事件处理函数 | 触发条件 |
---|---|---|
click | onclick | 按下并且释放鼠标 |
dbclick | ondbclick | 双击鼠标 |
mousedown | onmousedown | 按下鼠标按键 |
mouseup | onmouseup | 释放鼠标按键 |
mousemove | onmousemove | 移动鼠标 |
mouseover | onmouseover | 鼠标进入元素 |
mouseout | onmouseout | 鼠标离开元素 |
键盘事件
- 按键按下:
keydown
,用户按下键盘上的键; - 按键释放:
keyup
,用户释放按键; - 点击按键:
keypress
,用户按下并且释放了按键。
点击按键onkeypress(event)
event.which 返回点击按钮的编码
<body onkeypress="keyEvent(event)">
<p>
keypress event
</p>
</body>
<script>
function keyEvent(event) {
console.log("编码是:"+event.which);
}
</script>
释放按键keyup()
<body onkeyup="upEvent(event)">
</body>
<script>
function upEvent(event) {
console.log("编码是:"+event.which);
}
</script>
表单事件
change事件
change
事件表示当前元素失去焦点并且元素的内容发生了改变。失去焦点,指光标不在该元素上,比如光标本来在文本输入框里面,当用户在页面的其他地方点击了鼠标,文本框就会失去焦点。
select事件
select
事件:文本框中的文本被用户选中时发生。
submit事件
<body>
<form onsubmit="subEve()">
<input type="password" id="pw"/>
<input type="submit" value="提交" />
</form>
<script>
function subEve() {
var content = document.getElementById("pw").value;
if (content.length < 6) {
window.alert("密码不可以小于6位");
}
}
</script>
</body>
拖动事件
元素的拖放
draggable=”true”
鼠标指向元素,按下鼠标,然后移动鼠标到另一个地方释放,即拖动元素。
相比html4
以及之前的版本,html5
增加了一个全新的属性draggable
,表示元素是否支持拖动,默认的情况下,图片和超链接元素是支持拖动的,其他元素不支持。
将元素的draggable
属性设置为true
,即表示元素支持拖动。
ondrag
ondrag()
是元素正在拖动时触发的事件处理程序。如果元素一直在拖动的过程中,ondrag()
会每隔350ms
被触发一次
<body>
<div>
<p ondrag="dragging(event)" draggable="true">拖动我!</p>
</div>
<script>
function dragging(event) {
console.log("正在拖动");
}
</script>
</body>
ondragstart
用户开始拖动元素时触发,可以带有一个event
参数,其中的event.target
表示拖动的元素
<body>
<p ondragstart="dragStart(event)" draggable="true">拖动我!</p>
<script>
function dragStart(event) {
console.log(event.target);
console.log("你要拖动的文本的内容是:"+event.target.innerText);
}
</script>
</body>
事件冒泡
阻止父元素也触发
事件冒泡是指,某个事件触发了某个元素的事件处理程序,接下来,就会自动沿着节点树往根节点的方向依次触发经过的路径上的所有元素的某个事件的处理程序。
事件冒泡的控制
event.stopPropagation()
function clickChild() {
console.log("子");
window.event?window.event.cancelBubble=true:event.stopPropagation();
}
BOM
意义
browser Object Model,专门操作浏览器窗口的API,无标准,兼容性问题
包含
- window:代表整个窗口
- history:封装当前窗口打开后,成功刚问过的URL记录
- navigator:封装浏览器配置信息
- document:封装当前正在加载的网页内容
- location:封装当前窗口正在打开的URL地址
- screen:封装了屏幕的信息
- event:定义了网页中的事件机制
滚动条
document.body.scrollTop恒为0,需要用document.documentElement.scrollTop
window
窗口大小:window.outerWidth/outHeight
文档显示区大小:widow.innerWidth/innerHeight
定时器
周期性定时器
setInterval(执行语句, time)
//1.语法
setInterval(fucntion(){
console.log("hello");
},1000)
//2.停止定时器
var timer = setIntervale(function(){} ,1000);
clearInterval(timer);
一次性定时器
setTimeout(执行语句, time);
location对象
location
对象就是window.location
,记载了浏览器当前所在的窗口的URL
(统一资源定位符)信息,它常常被用来实现网页的跳转。
属性
属性名 | 解释 | 属性的值 |
---|---|---|
host | 主机名和端口号 | www.educoder.net:8080 |
hostname | 主机名 | www.educoder.net |
pathname | 路径部分 | /shixun.html |
port | 端口号 | 8080 |
protocal | 协议 | https |
search | 问号开始的查询部分 | ?tab=1 |
<body onload="printInfo()">
location attribute
<script>
function printInfo() {
var loc = window.location;
console.log("host:"+loc.host);
}
</script>
</body>
对话框
警告框
alert
确认框
confirm
msg
是需要用户确认的信息,用户在弹出的框里面选择确认或者取消后,会返回true
或者false
。
输入框
window.prompt(提示语 ,默认值);
直接点取消返回null。
窗口
打开浏览器的窗口
window.open(url,name,specs,replace)
用来打开一个浏览器的窗口,它有四个参数:
url
表示窗口里面的文档的地址;
name
有两种情况。
如果name
里面是窗口的名字。浏览器会先判断这个窗口是否已经打开。已经打开则用新的url
里面的文档替换这个窗口里面原来的文档,反映到浏览器上是不会有新的标签页打开,但是一个已存在的标签页会刷新。没有打开则打开一个新的窗口,并且载入url
里面的文档。
如果name
是_blank
、_self
里面中的任何一个,它的含义如下:
值 | 含义 |
---|---|
_blank | 打开新的窗口,载入地址为url的文档 |
_self | 不打开新的窗口,用地址为url的文档替换掉当前的文档 |
specs
是用来控制新窗口的尺寸等特征,比如值为width=200,height=100
时,表示新窗口宽度为200px
,高度为100px
。
replace
用来控制新的窗口在浏览器的浏览历史里面如何显示。为true
表示装载到窗口的url
替换掉浏览历史中的当前条目;为false
表示装载到窗口的url
创建一个新的条目。
关闭窗口
window.open()
会有一个返回值result
,result.close()
用来关闭打开的窗口
常用函数
替换url参数
```js
/*
* @param url 目前的url
* @param paramName 需要替换的参数属性名
* @param replaceVal 需要替换的参数的新属性值
* @param forceAdd 该参数是否可以重复查询(attrs=1_3G:4G:5G&attrs=2_骁龙845&attrs=4_高清屏)
* @returns {string} 替换或添加后的url
*/
function replaceParamVal(url, paramName, replaceVal,forceAdd) {
var oUrl = url.toString();
var nUrl;
// 有这个参数
if (oUrl.indexOf(paramName) != -1) {
// 参数的值不一样
if( forceAdd && oUrl.indexOf(paramName+”=”+replaceVal)==-1) {
if (oUrl.indexOf(“?”) != -1) {
nUrl = oUrl + “&” + paramName + “=” + replaceVal;
} else {
nUrl = oUrl + “?” + paramName + “=” + replaceVal;
}
// 参数的值一样
} else {
var re = eval(‘/(‘ + paramName + ‘=)([^&])/gi’);
nUrl = oUrl.replace(re, paramName + ‘=’ + replaceVal);
}
// 原来没有这个参数
} else {
// 有参数,?xxx=yyy &zzz
if (oUrl.indexOf(“?”) != -1) {
nUrl = oUrl + “&” + paramName + “=” + replaceVal;
} else {
nUrl = oUrl + “?” + paramName + “=” + replaceVal;
}
}
return nUrl;
};
# JQuery
## 一、jQuery概述
### 为何使用它
1、Jquery对DOM终极简化
2、屏蔽了浏览器的兼容性问题
### 如何使用
1、下载jQuery.js下载到服务器本地,引入
2、使用CDN网络上共享的JQuery.js生产环境中用的最多
```html
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
工厂函数
使用选择符:$( ),所有选择符都能放入
//DOM:
document.getElementById("myId");
//JQuery
$("#myId");
初见
var box = $("#box");
box.html("hello,jquery");
//html(): ()里有内容,表示往该元素添加内容,没有内容,表示获取内容。
二、增删改查
查找
选择器
基本选择器
- 标签、类、id
层级选择器、
$(".container p:first span")
show()和hide(),原理相当于
css
中的display:block;
兄弟关系
$(“ “).next/prev( ) 紧邻的前后元素
$(“ “).nextAll/prevAll( ) 之前或之后的所有元素
$(“ “).siblings( ) 除了自己以外的所有兄弟
过滤选择器(重点)
获取第一个
li
标签,添加背景色(background)orange
:li:first
添加背景色:$("li:first").css("background","orange")
;获取最后一个
li
标签 li:last
添加背景色:$("li:last").css("background","green")
;获取下标为偶数even的
li
标签 li:even
添加背景色:$("li:even").css("background","#eee")
;获取下标为奇数odd的
li
标签 li:odd
添加背景色:$("li:odd").css("background","#ccc")
。下标是从
0
开始的
过滤选择器(重点)
获取指定序号的元素li:eq(0)
也可以 $("li").eq(0).css("background","red")
:not 选择器
//选择最后一个 $("li:not(:last)"). css("margin-right","20px") $(".item").not(":last"). css("border-bottom", "1px dashed #ccc");
获取内容和属性
获取内容
$("p").text();
$("p").html();
text()
是获取所选元素的文本内容,html
标签的内容已经转化;html()
是获取所选元素的内容,包括html
标签。
获取属性
var val = $("input").val(); //获取表单的 value 值
$(".box").attr("class")
修改
访问元素的属性
- 获取 $(“…”).attr(“属性名”);
- 修改 $(“…”).attr(“属性名”, “值”);
HTML操作
html( ):读取或修改节点的HTML内容
获取html代码:
$(" ").html();
设置HTML代码:
$(" ").html("<strong> lalal </strong>")
修改元素的属性
$(".first").text("<h3>我是第一个</h3>"); 会转义
$(".second").html("<h3>我是第二个</h3>");
$(".third").val("我是第三个");
//修改属性
$("div").attr("attr", "newvalue");
$("div").attr({
"class": "alterClass",
"id": "alterId",
"name": "alterName",
"data-count": "alterDataCount"
});
文本操作
text():读取或修改节点的文本内容
值操作
val():读取或修改节点的value属性值
获取:$(“input:eq(5)”).val();
修改:$(“input”).val(“???”);
CSS样式
直接修改:
获取:$(“ “).css(“CSS属性名”);
修改:$(“ “).css(“CSS属性名”, 值);
$(“ “).css({
“background”:”#ccc”,
“text-align”:”center”,
“line-height”:”40px”
})
通过CLASS批量修改样式
判断是否含有指定class
$(“ “).hasClass(“ “)
添加class
$(“ “).addClass(“ “)
移除class
$(" ").removeClass(" ");
类的添加和删除
$("#box").addClass("active btn");
$("#box").removeClass("btn");
添加
append() 元素内尾部添加html
prepend() 元素内头部添加
before() 元素上添加
after() 元素下添加
//1.创建新元素,新节点
var $newElem = $("HTML代码片段");
//2.将新元素结尾添加到DOM树
$(parent).append($newElem);
var $li = $("<li title='香蕉'>香蕉</li>");
var $parent = $("ul");
$parent.append($li);
删除
- remove() 移除该元素
- empty() 删除元素里的内容
$(" ").remove();
//获取ul下第2个li节点,并删除
$("ul li:eq(1)").remove();
$("ul li").last().remove();
//把li元素中属性title不等于菠萝的li节点删除
$("ul li").remove("li[title!=菠萝]");
tab选项卡
$(".head li").on('click', function(){ // index是点击的li的索引 var index = $(this).index(); //-----------begin----------- $(".head li").removeClass("active").eq(index).addClass("active"); $(".content div").hide().eq(index).show();
//------------end------------
})
```html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
</head>
<body>
<div class="container">
<ul class="head">
<li>全部实训</li>
<li>实训路径</li>
<li>在线课堂</li>
<li>讨论区</li>
</ul>
<div class="content">
<div>我是全部实训的内容</div>
<div>我是实训路径的内容</div>
<div>我是在线课堂的内容</div>
<div>我是讨论区的内容</div>
</div>
</div>
<script>
$(function(){
//tab的初始化
$(".head li").removeClass('active').eq(0).addClass('active');
$(".content div").hide().eq(0).show();
$(".head li").on('click', function(){
// index是点击的li的索引
var index = $(this).index();
//-----------begin-----------
$(".head li").removeClass("active").eq(index).addClass("active");
$(".content div").hide().eq(index).show();
//------------end------------
})
})
</script>
<style>
.container{
width: 500px;
margin: 40px auto;
}
ul,li{
list-style-type: none;
}
.container ul{
overflow: hidden;
background: #000;
color: #fff;
}
.container li{
width: 100px;
float: left;
text-align: center;
line-height: 60px;
font-size: 18px;
cursor: pointer;
}
.container li.active{
color: orange;
}
.container .content{
width: 460px;
height: 200px;
padding: 20px;
background: #ccc;
font-size: 18px;
}
</style>
</body>
</html>
函数
each遍历
$(".sort_a").each(function () {
let text = $(this).text().replace("↓", "").replace("↑", "");
$(this).text(text);
})
toggleClass
移除或添加class
三、JQuery事件
方法 | 描述 |
---|---|
bind() | 向匹配元素附加一个或更多事件处理器 |
blur() | 触发、或将函数绑定到指定元素的 blur 事件 |
change() | 触发、或将函数绑定到指定元素的 change 事件 |
click() | 触发、或将函数绑定到指定元素的 click 事件 |
dblclick() | 触发、或将函数绑定到指定元素的 double click 事件 |
delegate() | 向匹配元素的当前或未来的子元素附加一个或多个事件处理器 |
die() | 移除所有通过 live() 函数添加的事件处理程序。 |
error() | 触发、或将函数绑定到指定元素的 error 事件 |
event.isDefaultPrevented() | 返回 event 对象上是否调用了 event.preventDefault()。 |
event.pageX | 相对于文档左边缘的鼠标位置。 |
event.pageY | 相对于文档上边缘的鼠标位置。 |
event.preventDefault() | 阻止事件的默认动作。 |
event.result | 包含由被指定事件触发的事件处理器返回的最后一个值。 |
event.target | 触发该事件的 DOM 元素。 |
event.timeStamp | 该属性返回从 1970 年 1 月 1 日到事件发生时的毫秒数。 |
event.type | 描述事件的类型。 |
event.which | 指示按了哪个键或按钮。 |
focus() | 触发、或将函数绑定到指定元素的 focus 事件 |
keydown() | 触发、或将函数绑定到指定元素的 key down 事件 |
keypress() | 触发、或将函数绑定到指定元素的 key press 事件 |
keyup() | 触发、或将函数绑定到指定元素的 key up 事件 |
live() | 为当前或未来的匹配元素添加一个或多个事件处理器 |
load() | 触发、或将函数绑定到指定元素的 load 事件 |
mousedown() | 触发、或将函数绑定到指定元素的 mouse down 事件 |
mouseenter() | 触发、或将函数绑定到指定元素的 mouse enter 事件 |
mouseleave() | 触发、或将函数绑定到指定元素的 mouse leave 事件 |
mousemove() | 触发、或将函数绑定到指定元素的 mouse move 事件 |
mouseout() | 触发、或将函数绑定到指定元素的 mouse out 事件 |
mouseover() | 触发、或将函数绑定到指定元素的 mouse over 事件 |
mouseup() | 触发、或将函数绑定到指定元素的 mouse up 事件 |
one() | 向匹配元素添加事件处理器。每个元素只能触发一次该处理器。 |
ready() | 文档就绪事件(当 HTML 文档就绪可用时) |
resize() | 触发、或将函数绑定到指定元素的 resize 事件 |
scroll() | 触发、或将函数绑定到指定元素的 scroll 事件 |
select() | 触发、或将函数绑定到指定元素的 select 事件 |
submit() | 触发、或将函数绑定到指定元素的 submit 事件 |
toggle() | 绑定两个或多个事件处理器函数,当发生轮流的 click 事件时执行。 |
trigger() | 所有匹配元素的指定事件 |
triggerHandler() | 第一个被匹配元素的指定事件 |
unbind() | 从匹配元素移除一个被添加的事件处理器 |
undelegate() | 从匹配元素移除一个被添加的事件处理器,现在或将来 |
unload() | 触发、或将函数绑定到指定元素的 unload 事件 |
事件绑定
语法:$(" ").bind("事件类型", function(e){ ... });
//e中包含与事件相关的信息,也提供了可以影响事件在DOM中传递进程的一些方法
1、$(" ").bind("click", function(e){ ... });
2、$("#button").click(function(e){ ... });
3. $(" ").on("click", function(){
})
4.错误
music.play()方法属于DOM对象方法,$('#audio1')为jquery对象,jquery对象调用DOM对象的方法导致了上述错误,只需将jquery对象转换为DOM对象即可:
事件对象
内容:记录事件发生时鼠标位置、键盘按键状态和触发对象等信息
clientX/offsetX/pageX/screenX/x:事件发生的X坐标(Y)
keyCode:键盘事件中按下的按键的值
s是
四、遍历
祖先元素
节点树
parent()
$("span").parents().css("background","orange");
parents()
后代元素
- children() 会返回被选元素的所有直接子元素
- find(“span”) 查找子元素
兄弟元素
$(“ “).next/prev( ) 紧邻的前后元素
$(“ “).nextAll/prevAll( ) 之前或之后的所有元素
$(“ “).siblings( ) 除了自己以外的所有兄弟
过滤
first()
给第一个p $("div p").first().css("background","orange");
last()
$("div p:last").css("background","orange");
eq()
$("div p").eq(0).css("background","orange");
filter()
$("div p").filter(".active").css("background","orange"); //过滤选择器 $("div p.active").css("background","orange");
not()
$("div p").not(".active").css("background","orange"); $("div p:not(.active)").css("background","orange");
五、动画
$(selector).method(speed, callback);
selector
是要操作的元素;method
是jQuery
自带的动画名,比如show
,hide
,toggle
;speed
是动画运动的速度,参数可选,可有可无;callback
是这个动画完成后需要执行的动作,参数可选,可有可无。
隐藏/显示
show()、hide()、toggle()
hide(time/“fast”, function)
$(".box").hide(2000);
"slow"
,表示慢速度;"fast"
,表示快速度;- 毫秒,可自定义,上面的是
2s
。
toggle()(“time”, function)
淡入淡出
透明度的切换,透明的变为不透明,不透明的变为透明。
fadeIn()
fadeOut()
fadeToggle()
fadeTo()
$(".item").fadeTo("slow",0.8 ,function);
delay()
$(".item").delay(2000).fadeTo("slow",0.8 ,function);
滑动
元素的高度从0
变为已有的高度;
slideDown()
$(".menu").mouseenter(function(){ $(".list").slideDown(1000); })
slideUp()
slideToggle()
stop()
- 停止被选元素当前的动画。
自定义动画
width,height,opacity,font-size,left
平移动画
$(".item").animate({left: '500px', width:'200px', fontSize:'50px'} ,2000) .animate({left: '100px', width: '10px', fontSize: '24px'}, 2000)
移动改变的是
left
值和top
值 ,所以在样式中一定要有定位position
,父元素relative,子元素absolute。否则,没有定位,也就没有了left
属性和top
属性,也就不能移动了;在动画中使用驼峰命名法
相对值
stop()
- 第一个参数:是否清除动画队列,
true
表示是,false
表示否,默认是false
; - 第二个参数:是否立即完成当前动画,
true
表示是,false
表示否,默认是false
。
- 第一个参数:是否清除动画队列,
$(function(){
$(".btn").click(function(){
//向contianer里插入DOM元素 img 标签,每点击一次,插入一张图片。
var dom = '<img class="love" src="https://www.educoder.net/attachments/download/206509" alt="爱心">';
$(".container").append(dom);
//--------- Begin ----------
$(".love").show().animate({top: "-=120px", opacity: "0", "z-index": "999", zIndex: "999"}, 1500);
//--------- End ------------
})
})
响应式布局
布局方式
- 固定宽度布局:主流宽度960px/==980px==/1190px/1210px,手机
- 流式布局:百分比设置相对宽度,混乱错误
- 响应式布局:检测设备信息,设备宽度不同
- 混合使用
响应式布局
CSS3:media Query媒体查询
框架:Bootstrap
viewport视口
视口规定:布局视口(电脑) = 设备视觉视口(手机)、不可缩放
==meta:vp== 扩展
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
媒体查询
检查设备宽度,根据宽度设置CSS样式
设备屏幕 | 尺寸px |
---|---|
超小屏 | <768 |
小屏 | >=768 |
中等 | >=992 |
大屏 | >=1200 |
body{
background-color: black;
}
@media screen and (min-width: 768px){/*大于768px*/
body{
background-color:red;
}
}
@media screen and (min-width:992px){
body{
background-color:green;
}
}
属性:min-height、min-width、max-height、max-width
Boostrap
一、Boostrap概述
- 开源、移动优先的前端框架
- 基于HTML、CSS、JavaScript、JQuery
- 写很少的代码,实现多终端的页面适配
- 栅格系统
下载它
$ composer require twbs/bootstrap
使用它
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- 可选的 Bootstrap 主题文件(一般不用引入) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
例如
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<div class="row">
<div class="col-sm-12 col-md-8">? 1 ?</div>
<div class="col-sm-6 col-md-4">?? 2 ??</div>
</div>
</body>
</html>