事件对象

  • 概念:当时事件发生的时候,所以跟事件相关的信息(事件类型,事件目标,鼠标位置等)都会存储在事件对象event中。
  • 获取方式:
    console.log(event); //ie chrome 火狐会报错
    console.log(window.event); //ie chrome 火狐不报错,没有值
    console.log(ev); //火狐专用(一定要在形参中传入ev)
  • 兼容处理
    var oEvent = window.event || ev
   事件对象属性oDiv.onclick = function (ev) {//事件对象兼容var oEvent = window.event || evconsole.log(oEvent);//事件类型console.log(oEvent.type);//事件目标console.log(oEvent.target || oEvent.srcElement);//鼠标位置,相对于屏幕console.log(oEvent.clientX, oEvent.clientY);//鼠标位置,相对于页面console.log(oEvent.pageX, oEvent.pageY);//是某按住了某些键,返回一个布尔值//altconsole.log(oEvent.altKey);//ctrlconsole.log(oEvent.ctrlKey);//shiftconsole.log(oEvent.shiftKey);}
  • 事件绑定

    • 标准浏览器: 元素.addEventListener(‘事件类型(不加on)’,事件处理函数,是否捕获)
      默认false冒泡 true捕获
    • IE浏览器
      元素.attachEvent(‘事件类型(加on)’,事件处理函数)
    • 区别:
      标准 addEventListener
      不加on
      是否捕获
      this——触发事件的对象
      IE attachEvent
      加on
      没有捕获
      this——window
      IE低版本浏览器,会倒序执行
    function fn1() {console.log(111);}function fn2() {console.log(222);}function fn3() {console.log(333);}//封装function on(ele, type, fun) {if (ele.addEventListener) { //有值,说明支持这个方法ele.addEventListener(type, fun)} else {ele.attachEvent('on' + type, fun)}}on(oDiv,'mouseover',fn1)on(oDiv,'mouseover',fn2)on(oDiv,'mouseover',fn3)
  • DOM事件流

    • 事件捕获阶段:当事件发生的时候,事件从window开始依次往子元素传递
    • 确定目标阶段:找到目标
    • 事件冒泡阶段:从事件目标开始处理事件,处理完以后依次往父元素传递,一直传到 window
      注意IE只有冒泡,没有捕获
   <div id="box1"><div id="box2"><div id="box3"></div></div></div>//冒泡      先触发自己,再依次触发父级oDiv[0].addEventListener('click', fn1) //111oDiv[1].addEventListener('click', fn2) //222  111oDiv[2].addEventListener('click', fn3) //333  222  111//捕获    从最顶层父级开始,依次往下传递,最后触发自己的oDiv[0].addEventListener('click', fn1, true) //111oDiv[1].addEventListener('click', fn2, true) //111  222oDiv[2].addEventListener('click', fn3, true) //111  222  333
  • stopPropagation

    • 概念:该方法将停止事件的传播阻止它被分派到其他document节点
    • 兼容:oEvent.stopPropagation ? oEvent.stopPropagation() : oEvent.cancelBubble = true
      //点击显示btn.onclick = function (ev) {oDiv.style.display = 'block'//事件对象兼容var oEvent = window.event || ev//该方法将阻止事件的传播,阻止它被分配到其他document节点//标准浏览器oEvent.stopPropagation()      ie低版本:oEvent.cancelBubble = trueoEvent.stopPropagation ? oEvent.stopPropagation() : oEvent.cancelBubble = true}document.onclick = function () {oDiv.style.display = 'none'}
  • 事件取消

    • 元素.事件—————————–元素.事件=null
    • 元素.addEventListener()————元素.removeEventListener(事件类型,事件处理函数)
    • 元素.attachEvent()——————元素.detachEvent(事件类型,事件处理函数)
        oDiv[0].onclick = function(){console.log(111)}oDiv[0].onclick = nulloDiv[0].addEventListener('click',fn1)oDiv[0].removeEventListener('click',fn1)oDiv[0].attachEvent('onclick',fn1)oDiv[0].detachEvent('onclick',fn1)
  • 取消默认行为 :浏览器给的行为

    • 元素.事件———————–return false
    • 元素.addEventListener()———————oEvent.preventDefault()
    • 元素.attachEvent()—————————oEvent.returnValue = false
    // 元素.事件oA.onclick = function () {return false}oA.addEventListener('click', function (ev) {//事件对象兼容var oEvent = window.event || evoEvent.preventDefault()})oA.attachEvent('onclick',function(ev){//事件对象兼容var oEvent = window.event || evoEvent.returnValue = false})
  • 鼠标右击事件

    • 元素.oncontextmenu
    /* 分析:1、获取元素2、给元素添加右击事件3、获取鼠标点击的位置     在这之前做事件对象兼容4、把这个位置赋值给div5、取消右击的默认事件*/var oDiv = document.getElementsByTagName('div')[0]document.oncontextmenu = function (ev) {//事件对象兼容var oEvent = window.event || evconsole.log(oEvent);//获取鼠标X轴位置var clientX = oEvent.clientX//获取鼠标Y轴位置var clientY = oEvent.clientY//赋值给divoDiv.style.left = clientX + 'px'oDiv.style.top = clientY + 'px'//取消默认事件(右键)return false}
  • 键盘事件

    • onkeydown 键盘按下
    • onkeypress 在键盘被按下并释放一个键时发生
    • onkeyup 键盘抬起
      document.onkeydown = function (ev) {//事件对象兼容var oEvent = window.event || evconsole.log(oEvent);console.log('我的按键是:' + oEvent.key);console.log('我的编码是:' + oEvent.keyCode);//是否按了altconsole.log(oEvent.altKey);//是否按了ctrlconsole.log(oEvent.ctrlKey);//是否按了shiftconsole.log(oEvent.shiftKey);//判断是否按了ctrl+shiftif (oEvent.ctrlKey == true && oEvent.shiftKey == true) {console.log('我按了ctrl+shift');}//判断是否按了ctrl+cif (oEvent.ctrlKey == true && oEvent.keyCode == 67) {console.log('我按了ctrl+c');}}

案例:控制div的移动(左上右下:37-38-39-40)

  <div></div><script src="./ujiuye.js"></script><script>var oDiv = document.getElementsByTagName('div')[0]document.onkeydown = function (ev) {// console.log(111);//事件对象兼容var oEvent = window.event || ev//获取可视区宽度var clientX = document.documentElement.clientWidthif (parseInt(getStyle(oDiv, 'left')) <= -100) {oDiv.style.left = clientX + 'px'}switch (oEvent.keyCode) {case 37:oDiv.style.left = parseInt(getStyle(oDiv, 'left')) - 10 + 'px';break;case 38:oDiv.style.top = parseInt(getStyle(oDiv, 'top')) - 10 + 'px';break;case 39:oDiv.style.left = parseInt(getStyle(oDiv, 'left')) + 10 + 'px';break;case 40:oDiv.style.top = parseInt(getStyle(oDiv, 'top')) + 10 + 'px';break;}}</script>
  • 滚轮事件

    • ie/chrome:元素.onmousewheel

      • 滚动方向:oEvent.wheelDelta 下:-120 上:120
    • 火狐:元素.addEventListener(‘DOMMouseScroll’,处理函数)
      • 滚动方向:oEvent.detail 下:3 上:-3
      封装滚轮方向:function scroll(ev) {//事件对象兼容var oEvent = window.event || evif (oEvent.wheelDelta) {//如果能走到这里,说明是谷歌浏览器if (oEvent.wheelDelta > 0) {console.log('向上滚动');} else {console.log('向下滚动');}} else {//如果能走到这里,说明是火狐浏览器if (oEvent.detail > 0) {console.log('向下滚动');} else {console.log('向上滚动');}}}//谷歌浏览器document.onmousewheel = function(){scroll()}//火狐浏览器document.addEventListener('DOMMouseScroll',scroll)

案例:滚轮改变div的高度

      function scroll(ev) {//事件对象兼容var oEvent = window.event || ev//定义一个变量用来保存当前是向上滚动还是向下滚动var tag = trueif (oEvent.wheelDelta) {//如果能走到这里,说明是谷歌浏览器tag = oEvent.wheelDelta > 0 ? true : false} else {//如果能走到这里,说明是火狐浏览器tag = oEvent.detail > 0 ? false : true}//向下滚动false,向上滚动是true//获取当前的高度var h = parseInt(getStyle(oDiv, 'height'))console.log(h);if (tag) {//向上滚动oDiv.style.height = h - 10 + 'px'} else {//向下滚动oDiv.style.height = h + 10 + 'px'}}oDiv.onmousewheel = function () {scroll()}oDiv.addEventListener('DOMMouseScroll', scroll)
  • 事件代理

    • 概念:事件代理(事件委托):找一个元素**(父元素)代理**,当事件发生时,由这个元素通知具体的元素去处理事件
    • 原理:将事件绑定在父元素身上,当事件发生的时候,通过事件目标获取到具体的子元素,去处理事件 (接收事件目标 oEvent.tagret || oEvent.srcElement)
    • 优点:提高性能,让后面所有子元素同样拥有效果
    oUl.onclick = function (ev) {//事件对象兼容var oEvent = window.event || ev//用来接收事件目标     oEvent.tagret||oEvent.srcElementvar tagret = oEvent.tagret || oEvent.srcElementtagret.style.background = 'pink'}oUl.innerHTML += '<li>999</li>'
        //多个输入框各自通过滚轮增减数字function scroll(ev) {//事件处理兼容var oEvent = window.event || ev//事件代理var target = oEvent.tagret || oEvent.srcElementvar tag = true//向上滑动,tag=true;向下滑动,tag=falseif (oEvent.detail) {tag = oEvent.detail > 0 ? false : true} else {tag = oEvent.wheelDelta > 0 ? true : false}//向上滑动,值++;向下滑动,值--if(tag){target.value++}else{target.value--}}document.body.onmousewheel = function(){scroll()}document.body.addEventListener('DOMMouseScroll',scroll)

拖拽

    <div></div><img src="../拖拽/img/123.jpg" alt=""><script>var oDiv = document.getElementsByTagName('div')[0]var oImg = document.getElementsByTagName('img')[0]drag(oDiv)drag(oImg)function drag(ele) {ele.onmousedown = function (ev) {// 事件处理兼容var oEvent = window.event || ev//当鼠标点下,获取鼠标到盒子的x,y(鼠标到屏幕的距离-盒子到屏幕的距离)var mouseToBoxL = oEvent.clientX - ele.offsetLeftvar mouseToBoxT = oEvent.clientY - ele.offsetTop//获取屏幕可视宽高var clientW = document.documentElement.clientWidthvar clientH = document.documentElement.clientHeight//盒子实际宽高var boxW = ele.offsetWidthvar boxH = ele.offsetHeight//ie低版本浏览器取消图片文字拖拽默认事件:设置捕获(一次性的,鼠标抬起后需要释放捕获才能重新设置捕获)if (ele.setCapture) {ele.setCapture()}document.onmousemove = function (ev) {//事件处理兼容var oEvent = window.event || ev//控制范围(当盒子到左屏幕的距离<0时,设置盒子到左屏幕的距离=0;当盒子到左屏幕的距离>(屏幕宽-盒子实际宽度)时,设置盒子到左屏幕的距离=屏幕宽-盒子实际宽度)// 控制范围(当盒子到上屏幕的距离<0时,设置盒子到上屏幕的距离=0;当盒子到上屏幕的距离>(屏幕高-盒子实际高度)时,设置盒子到上屏幕的距离=屏幕宽-盒子实际高度)//时刻获取鼠标位置来确定盒子位置var L = oEvent.clientX - mouseToBoxLvar T = oEvent.clientY - mouseToBoxTif (L < 0) {L = 0} else if (L > clientW - boxW) {L = clientW - boxW}if (T < 0) {T = 0} else if (T > clientH - boxH) {T = clientH - boxH}//当鼠标移动,盒子的位置随之改变(设置定位样式为:鼠标到屏幕的距离-鼠标到盒子的距离)ele.style.left = L + 'px'ele.style.top = T + 'px'}document.onmouseup = function () {document.onmousemove = nulldocument.onmouseup = null//释放捕获if (ele.releaseCapture) {ele.releaseCapture()}}//标准浏览器取消图片拖拽默认事件return false}}

碰撞检测

    <div></div><p></p><script>var oDiv = document.getElementsByTagName('div')[0]var oP = document.getElementsByTagName('p')[0]//获取大盒子各边的位置var bigL = oP.offsetLeftvar bigT = oP.offsetTopvar bigR = bigL + oP.offsetWidthvar bigB = bigT + oP.offsetHeightoDiv.onmousedown = function (ev) {// 事件处理兼容var oEvent = window.event || ev//当鼠标点下,获取鼠标到盒子的x,y(鼠标到屏幕的距离-盒子到屏幕的距离)var mouseToBoxL = oEvent.clientX - oDiv.offsetLeftvar mouseToBoxT = oEvent.clientY - oDiv.offsetTop//获取屏幕可视宽高var clientW = document.documentElement.clientWidthvar clientH = document.documentElement.clientHeight//盒子实际宽高var boxW = oDiv.offsetWidthvar boxH = oDiv.offsetHeight//ie低版本浏览器取消图片文字拖拽默认事件:设置捕获(一次性的,鼠标抬起后需要释放捕获才能重新设置捕获)if (oDiv.setCapture) {oDiv.setCapture()}document.onmousemove = function (ev) {//事件处理兼容var oEvent = window.event || ev//控制范围(当盒子到左屏幕的距离<0时,设置盒子到左屏幕的距离=0;当盒子到左屏幕的距离>(屏幕宽-盒子实际宽度)时,设置盒子到左屏幕的距离=屏幕宽-盒子实际宽度)//控制范围(当盒子到上屏幕的距离<0时,设置盒子到上屏幕的距离=0;当盒子到上屏幕的距离>(屏幕高-盒子实际高度)时,设置盒子到上屏幕的距离=屏幕宽-盒子实际高度)//时刻获取鼠标位置来确定盒子位置var L = oEvent.clientX - mouseToBoxLvar T = oEvent.clientY - mouseToBoxTif (L < 0) {L = 0} else if (L > clientW - boxW) {L = clientW - boxW}if (T < 0) {T = 0} else if (T > clientH - boxH) {T = clientH - boxH}//当鼠标移动,盒子的位置随之改变(设置定位样式为:鼠标到屏幕的距离-鼠标到盒子的距离)oDiv.style.left = L + 'px'oDiv.style.top = T + 'px'//在移动的时候,时刻获取小盒子各边的位置var divL = oDiv.offsetLeftvar divT = oDiv.offsetTopvar divR = divL + oDiv.offsetWidthvar divB = divT + oDiv.offsetHeight//判断安全区,小盒子右边<大盒子左边;小盒子下边<大盒子上边;小盒子左边>大盒子右边;小盒子上边>大盒子下边if (divR < bigL || divB < bigT || divL > bigR || divT > bigB){oP.style.background = 'green'}elseoP.style.background = 'yellow'}document.onmouseup = function () {document.onmousemove = nulldocument.onmouseup = null//释放捕获if (oDiv.releaseCapture) {oDiv.releaseCapture()}}//标准浏览器取消图片拖拽默认事件return false}</script>

缓冲运动

        // 封装调用测试缓冲运动var timerfunction bufferMove(ele,attr,target){clearInterval(timer)timer = setInterval(function () {//获取当前位置var localNow = parseInt(getStyle(ele, attr))//速度步长:(目标位置-当前位置)/固定系数var step = (target - localNow) / 10//判断运动的方向:正向运动向上取整,负向运动向下取整step = step > 0 ? Math.ceil(step) : Math.floor(step)if (localNow == target) {localNow = targetclearInterval(timer)}//设置div新的位置ele.style[attr] = localNow + step + 'px'}, 16)}oDiv.onclick = function(){bufferMove(oDiv,'top',300)}

多属性运动

    <div></div><div></div><script src="../运动函数封装/ujiuye.js"></script><script>//多属性运动,多个属性对应相对应的目标值,可以用对象var oDiv = document.getElementsByTagName('div')var oP = document.getElementsByTagName('p')[0]// 封装调用测试缓冲运动var timerfunction bufferMove(ele, json, fn) {//区分不同元素的定时器id(元素.timer)clearInterval(ele.timer)ele.timer = setInterval(function () {//假设所有的样式都已经执行完var tag = truefor (var attr in json) {//获取当前位置(如果样式为透明度,则其获取到的透明浮点值*100;如果获取到的为其他样式,则当前位置为样式取整)var localNow = attr == 'opacity' ? getStyle(ele, attr) * 100 : parseInt(getStyle(ele, attr))//速度步长:(目标位置-当前位置)/固定系数var step = (json[attr] - localNow) / 10//判断运动的方向:正向运动向上取整,负向运动向下取整step = step > 0 ? Math.ceil(step) : Math.floor(step)//如果当前位置还没到目标值,则状态为false        if (localNow != json[attr]) {tag = false}//设置div新的样式(如果样式为透明度,则设置透明值为(当前位置+步长)/100;如果为其他样式,则设置新样式为(当前位置+步长+'px')ele.style[attr] = attr == 'opacity' ? (localNow + step) / 100 : localNow + step + 'px'if (tag == true) {//当全部键值对完成后清除定时器clearInterval(ele.timer)//回调函数fn && fn(ele,{'height': 100,'width': 100,'opacity': 20})}}}, 30)}oDiv[0].onmouseover = function () {bufferMove(this,{'height': 300,'width': 300,'opacity': 100}, bufferMove)}oDiv[1].onmouseover = function () {bufferMove(this,{'height': 300,'width': 300,'opacity': 100}, bufferMove)}//此时两个盒子的定时器共用一个,相互影响,需要给当前元素设置独立的定时器,万物皆对象,元素.键名(ele.timer)</script>

回调函数

  • 某个动作或某个事件完成后调用的函数
    一般在封装函数中,都可以设置回调函数,但这个回调函数不是必传的参数,即使传了也可以选择不用(fn && fn())

轮播图

    <script>var oUl = document.getElementsByTagName('ul')[0]var oP = document.getElementsByTagName('p')[0]var oSpan = document.getElementsByTagName('span')var wrap = document.getElementById('wrap')//1、 91-102 设置静态页面并设置初始样式var imgArr = ['./img/1.jpg', './img/2.jpg', './img/3.jpg', './img/4.jpg']//定义接收图片的字符串var str1 = ''//定义接收span的字符串var str2 = ''for (var i = 0; i < imgArr.length; i++) {str1 += '<li><img src="' + imgArr[i] + '"></li>'str2 += '<span>' + (i + 1) + '</span>'}oUl.innerHTML = str1 + '<li><img src="' + imgArr[0] + '"></li>'oP.innerHTML = str2oSpan[0].className = 'active'//定义一个n来表示当前是第几张图片var n = 0//2、设置自动轮播var timer1 = setInterval(autoNext, 3000)function autoNext() {/* 第一次移动   -960*1第二次移动   -960*2第三次移动   -960*3*///3、执行n++n++//5、判断是否为最后一张if (n >= imgArr.length + 1) {oUl.style.left = '0px'n = 1}//4、每次移动ul -960*n的位置move(oUl, 'left', 30, -960 * n)//7、干掉小方块所有样式for (var i = 0; i < oSpan.length; i++) {oSpan[i].className = ''}//6、设置小方块的样式if (n == imgArr.length) {// 说明当前是那张假图oSpan[0].className = 'active'} else {// 说明当前是正常轮播oSpan[n].className = 'active'}}wrap.onmouseover = function () {clearInterval(timer1)}wrap.onmouseleave = function () {timer1 = setInterval(autoNext, 3000)}//点击小方块//1)循环遍历每一个小方块for (var i = 0; i < oSpan.length; i++) {//3)设置自定义索引oSpan[i].index = i//2)给每一个小方块添加点击事件oSpan[i].onclick = function () {//4)移动ul,每次移动-960*this.index的距离move(oUl, 'left', 30, -960 * this.index)//6)干掉所有for (var j = 0; j < oSpan.length; j++) {oSpan[j].className = ''}//5)给当前这个小方块添加样式this.className = 'active'//7)改变n的值n = this.index}}</script>

面向对象的概念

  • 面向过程:我们之前按照步骤写代码就是面向过程的编程思维
  • 面向对象:使用对象时,只关注对象提供的功能不关注其内部细节
    • 遇到问题就找对象,有对象就用对象,没有对象就造对象,使用对象来解决问题
  • 面向对象的特点
    • 封装:将大量的全局变量函数封装成对象的属性和方法,从而减少全局变量,防止全局作用域的污染
    • 继承:面向对象思想实现了js中的对象的继承
    • 多态:在同一操作中,不同环境下有不同的效果(譬如js中的+:运算/字符串拼接)
  • 对象的组成
    • 属性(态)————对象中的属性
    • 方法(态)————对象中值为函数的属性

对象的创建

  • 字面量创建

    • var obj = {属性名:属性值,……….}
    • 优点:写法方便
    • 缺点:不利于创建大量对象
  • 实例化创建
    • var obj = new Object()
    • 优点:创建出来的对象类型明确
    • 缺点:不利于创建大量对象
  • 工厂模式(工厂函数)创建
    • 创建方式:
      封装一个函数
      ②在函数建一个对象
      ③将属性和方法添加到封装的函数中
      返回创建出来的对象
    • 优点:可以创建大量对象
    • 缺点:this指向不明确,this值是window,而不是创建出来的对象
  • 构造函数创建
    • 创建方式:function Fn(name){ this.name=name }
    • 实例化方式:var obj = new Fn()
    • 在new的时候执行了四个步骤
      js隐式创建空对象
      js隐式将构造函数的this赋值给隐式创建的对象
      通过this给空对象绑定属性
      js隐式返回绑定好属性的对象
    • 注意:
      构造函数首字母必须大写
      不需要在构造函数内部new Object()
      属性和方法直接加在this上
      不需要return
      调用的时候必须加new(如果不加new就和普通调用函数一样)
    • 缺点:如果创建的对象有相同的属性,会浪费资源
  • 原型
    • 原型的获取方式
      ①构造函数.prototype
      ②子对象._ _ proto _ _
    • 作用
      ①可以给子对象继承自身的属性
      ②子对象可以使用原型的属性但不拥有
  • 原型创建
    • 创建方式:Fn.prototype.money = ‘5000W’
    • 实例化方式:var obj = new Fn()
    • 构造函数内不写任何属性(空构造函数),而是将所有属性写入原型中,继承给每一个子对象,最大程度节省内存空间
    • 缺点:不能传参
  • 混合创建(构造函数创建+原型创建)
    • 构造函数中定义可变的属性和方法(可以传参)
    • 原型中定义共享的属性和方法(节约内存)
  • 动态混合创建
        //字面量创建var stu = {'sno':1,'name':'张三','age':18}console.log(stu)console.log(stu.sno)//实例化创建var stu = new Object()stu.sno = 1stu.name = '张三'stu.age = 18console.log(stu)console.log(stu.sno)//工厂模式(工厂函数)创建function stu(sno,name,age){var person = new Object()person.sno = snoperson.name = nameperson.age = agereturn person}console.log(stu(1,'张三',18))console.log(stu(1,'张三',18).sno)//构造函数创建function Fn(sno,name,age){this.sno = snothis.name = namethis.age = age}var stu = new Fn(1,'张三',18)console.log(stu)console.log(stu.sno)//原型创建function Fn(){}Fn.prototype.sno = 1Fn.prototype.name = '张三'Fn.prototype.age = 18console.log(Fn.prototype)  //通过创建函数找原型var stu = new Fn()         //通过创建函数创建子对象console.log(stu.__proto__) //通过子对象找原型console.log(stu.sno)       //子对象继承原型的属性和方法//混合创建(构造函数+原型)function Fn(sno,name,age){this.sno = snothis.name = namethis.age = age}Fn.prototype.course = '信息安全'Fn.prototype.class = '03'var stu = new Fn(1,'张三',18)console.log(stu)console.log(stu.course)console.log(stu.__proto__.constructor)//子对象的原型对应的创建函数

案例:飞机大战:

    /* 静态: 图片路径、X、Y动态: 把路径转换成图片,设置X和Y*/var wrap = document.getElementsByTagName('div')[0]function Plane(src, x, y) {this.imgNode = nullthis.planeSrc = srcthis.planeX = xthis.planeY = ythis.init()}Plane.prototype.init = function () {this.imgNode = document.createElement('img')this.imgNode.src = this.planeSrcthis.imgNode.style.left = this.planeX + 'px'this.imgNode.style.top = this.planeY + 'px'wrap.appendChild(this.imgNode)}var obj1 = new Plane('./image/大飞机挨打.png', 100, 100)var obj2 = new Plane('./image/飞机爆炸.gif', 200, 400)new Plane('./image/我的飞机.gif', 200, 200)

案例:选项卡

    <button>按钮一</button><button>按钮二</button><button>按钮三</button><div class="active">11111</div><div>22222</div><div>33333</div><script>function ChooseCard() {this.btn = document.getElementsByTagName('button')this.oDiv = document.getElementsByTagName('div')var that = thisfor (var i = 0; i < this.btn.length; i++){this.btn[i].index = i//点击按钮后改变div的样式为公共的动态方法,放在原型里面this.btn[i].onclick = function(){//构造函数中的方法that.init(this.index)}}}ChooseCard.prototype.init = function(index){//原型里面的this指向构造函数,目前需要获取到构造函数中的div的个数,干掉所有for(var j=0;j<this.oDiv.length;j++){this.oDiv[j].className = ''}//此时索引因为此时点击的按钮的索引,可以传入一个参数this.oDiv[index].className = 'active'}new ChooseCard()</script>

命名空间

概念:当项目足够大,或者用了很多第三方框架,可能会出现命名不够用的情况,使用命名空间来解决这个问题

   var obj1 = {}var obj2 = {}obj1.name = 'zhangSan'obj2.name = 'liSi'console.log(obj1.name);console.log(obj2.name);

面向对象继承

  • 原型链继承

    • 原型链:从子对象开始Object.prototype为止中间由_ _proto _ _属性链接起来的一个链式结构就是原型链
    • 在原型链中每一个原型的属性最后都会继承给子对象
    • 原型链查找规则:当一个对象调用属性时,会先在当前对象中查找,有就用,没有 就向原型中查找,如果还没有就继续向上一级原型中查找,直到Object.prototype,如果有就用,没有就返回undefined
    • 缺点:由于继承的是原型链中的属性,因此属性的值无法修改
        //构造奶奶函数function GrandMother(name,age){this.name = namethis.age = age}//奶奶函数prototype找到爷爷原型GrandMother.prototype.money = '500w'//奶奶函数new了一个爸爸var father = new GrandMother('张三',24)//构造一个空的妈妈函数var mother = function(){}//妈妈函数prototype找到了爸爸原型mother.prototype = father//妈妈函数new了一个我var me = new mother()console.log(me)console.log(me.__proto__)console.log(me.__proto__.__proto__)//不能拥有属于我自己的名字和年龄
  • 对象冒充继承

    • call和apply:用来改变this指向
    • 用法:
      ①函数.call(要改变的this值,实参1,实参2,实参3………)
      ②函数.apply(要改变的this值,[实参1,实参2,实参3………])
    • 优势:可以随意改变属性的值
    • 缺点:不能继承原型链中的属性
    //一代构造函数function First(name, age) {this.name = namethis.age = age}//BadWomanfunction BadWoman() {console.log(this); //指向badwoman// First.call(this, '如花', 45)First.apply(this,['如花', 45])}var obj = new BadWoman()console.log(obj);
  • 组合(混合)式继承

    • 对象冒充+原型链继承
    • 小瑕疵:构造函数中的属性原型中也有,会有一个资源浪费的问题
    /* 混合(组合)继承对象冒充+原型链*///大构造函数Firstfunction First(name, age) {this.name = namethis.age = age}//大构造函数的原型First.prototype.money = '500W'//大构造函数的子对象var Second = new First('zhangSan', 18)//小构造函数function BadWoman() {First.apply(this, ['liSi', 6])}BadWoman.prototype = Second//实例化小构造函数的子对象var obj = new BadWoman()console.log(obj);console.log(obj.name);console.log(obj.age);console.log(obj.money);
  • 寄生混合式继承

    • 我们一般会创建一个空函数,然后这个空函数的原型指向父类的原型,再实例化这个空函数,赋给子的原型,再修改子对象constructor。将这个过程用一个函数包起来,这个函数接收两个参数,子类构造函数和父类构造函数。
     function fn(child, parent) {//child是badwoman子构造函数         parent是First父构造函数//1、创建空函数var F = function () {}//2、空函数的原型指向父类的原型F.prototype = parent.prototype//3、实例化这个空函数var obj = new F()//4、把实例化的空函数赋值给子原型child.prototype = obj//5、obj.constructor = child}//大构造函数Firstfunction First(name, age) {this.name = namethis.age = age}//大构造函数的原型First.prototype.money = '500W'//大构造函数的子对象var Second = new First('zhangSan', 18)//小构造函数function BadWoman() {First.apply(this, ['liSi', 6])}fn(BadWoman, First)//实例化小构造函数的子对象var obj = new BadWoman()console.log(obj);console.log(obj.name);console.log(obj.age);console.log(obj.money);
  • 原型中的this指向构造函数
  • 事件中的this指向触发事件的元素
  • 一般函数this指向window
  • 构造函数this指向构造函数
  • 轮播图插件:link
  • momentjs官方文档:link
  • animate.css动画:link
  • cubic-bezier速度曲线:link
  • 阿里巴巴图标库:link
  • Font-awesome图标库:link

正则表达式

  • 正则对象:RegExp
  • 概念:是对字符串操作的一种逻辑公式,就是用事先定义好的一些特殊字符,及这些特定字符的组合,组成一个‘规则字符串’,这个规则字符串用来表达对字符串的一种过滤逻辑。规定文本检索的内容,通常被用来检索、替换文本
  • 创建方式
    • 构造函数创建 :new RegExp(‘检索字符’,’修饰符’)
    • 字面量创建: /’检索字符’/’修饰符’
     //1、构造函数创建    new RegExp('检索字符','修饰符')var pat1 = new RegExp('hello')console.log(pat1);     //   /hello///2、字面量创建      /检索字符/修饰符var pat2 = /hello/console.log(pat2);     //   /hello/
  • 修饰符

    • g:global 执行一个全局匹配
    • i:ignore Case 执行一个不区分大小写的匹配
    //1、g  全局var str = 'hello java,hello web,hello ui'var reg1 = /hello/var reg2 = /hello/gconsole.log(str.replace(reg1, '你好')); //你好 java,hello web,hello uiconsole.log(str.replace(reg2, '你好')); //你好 java,你好 web,你好 ui//2、i  不区分大小写var str = 'abcdefg'var reg1 = /C/var reg2 = /C/iconsole.log(str.search(reg1)); //-1console.log(str.search(reg2)); //2
  • 检索方法

    • 正则方法

      • test:检索字符串中是否包含在正则要检索的内容 (返回布尔值) reg.test(str)
      • exec:进行具体检索,检索到正则规定的内容返回一个数组 reg.exec(str)
    //test:检索字符串中是否包含正则要检索的内容(返回布尔值)console.log(reg1.test(str)); //trueconsole.log(reg2.test(str)); //false//exec:进行具体检索,检索到正则规定的内容返回一个数组var reg3 = /e/console.log(reg3.exec(str)); //["e", index: 1, input: "hello world", groups: undefined]var reg4 = /m/console.log(reg4.exec(str)); //null
  • 字符串方法

    • replace:替换正则匹配的字符串str.replace(reg)
    • split:按正则规定的内容拆成数组str.split(reg)
    • match:返回正则匹配的内容,和exec一样str.match(reg)
    • search:返回正则匹配的第一个字符串的位置,如果没有就返回 -1 str.search(reg)
    var s = 'ujiuye java'//replacevar reg5 = /java/console.log(s.replace(reg5, 'web')); //ujiuye web//split//\s匹配空白字符、空格、制表符和换行符var reg6 = /\s/console.log(s.split(reg6)); //["ujiuye", "java"]//matchvar reg7 = /e/console.log(s.match(reg7)); //["e", index: 5, input: "ujiuye java", groups: undefined]//searchvar reg8 = /j/console.log(s.search(reg8));  //1
  • 元字符
    //1、. 除换行符以为的任意字符var str = '\nweb'var reg = /./console.log(reg.exec(str)); //["w", index: 1, input: "↵web", groups: undefined]var str = 'abcde1234'var reg = /ab.....34/igconsole.log(reg.exec(str)); //["abcde1234", index: 0, input: "abcde1234", groups: undefined]//2、 [ ]  匹配字符集中任意一个字符var str = 'm23'var reg = /[0-9]/igconsole.log(reg.exec(str)); //["2", index: 1, input: "m23", groups: undefined]//6位银行卡密码var str = '369h56'var reg = /[0-9][0-9][0-9][a-z][0-9][0-9]/igconsole.log(reg.exec(str)); //["369h56", index: 0, input: "369h56", groups: undefined]//3、 [^]匹配除字符集中的任意一个字符var str = "123"//匹配除0-9以外的任意字符var reg = /[^0-9]/igconsole.log(reg.exec(str)); //null    因为123都是数字,都是0-9之内的数字//4、 \d 匹配数字var str = 'ab5'var reg = /\d/igconsole.log(reg.exec(str)); //["5", index: 2, input: "ab5", groups: undefined]//5、 \D 匹配非数字var str = 'abc'var reg = /\D/igconsole.log(reg.exec(str)); //["a", index: 0, input: "abc", groups: undefined]//6、 \w  匹配数字字母下划线var str = '%%%_'var reg = /\w/igconsole.log(reg.exec(str)); //["_", index: 3, input: "%%%_", groups: undefined]//7、 \W  匹配非数字非字母非下划线var str = '%%%_'var reg = /\W/igconsole.log(reg.exec(str)); //["%", index: 0, input: "%%%_", groups: undefined]//8、 \s 匹配空格var str = 'hello world'var reg = /\s/igconsole.log(reg.exec(str)); //[" ", index: 5, input: "hello world", groups: undefined]//9、 \S 匹配非空格var str = 'hello world'var reg = /\S/igconsole.log(reg.exec(str)); //["h", index: 0, input: "hello world", groups: undefined]//10、 \b单词边界var str = 'he is boy heisboy'var reg = /\bis\b/console.log(reg.exec(str)); //["is", index: 3, input: "he is boy heisboy", groups: undefined]//11、 \B非单词边界var str = 'he is boy heisboy'var reg = /\Bis\B/console.log(reg.exec(str)); //["is", index: 12, input: "he is boy heisboy", groups: undefined]console.log(str.replace(reg, 'mm')); //he is boy hemmboyvar reg = /\bis\B/console.log(reg.exec(str)); //null//12、^以开头         ^a  以a开头var str = '123456'var reg = /^1\d\d\d\d\d/igconsole.log(reg.exec(str)); //["123456", index: 0, input: "123456", groups: undefined]//13、$以结尾         a$  以a结尾var str = '123456'var reg = /\d\d\d\d\d6$/igconsole.log(reg.exec(str)); //["123456", index: 0, input: "123456", groups: undefined]//以1开头,以6结尾var reg = /^1\d\d\d\d6$/igconsole.log(reg.exec(str)); //["123456", index: 0, input: "123456", groups: undefined]
  • 量词
    //1、   ?匹配0个或者1个           f?匹配0个f或者1个fvar str = 'abc'var reg = /a?/igconsole.log(reg.exec(str)); //["a", index: 0, input: "abc", groups: undefined]//2、   *匹配0个或者多个          f* 匹配0个f或者多个f    尽可能多匹配var str = 'aaaaaaaaaabcaaaaa'var reg = /a*/console.log(reg.exec(str)); //["aaaaaaaaaa", index: 0, input: "aaaaaaaaaabcaaaaa", groups: undefined]//3、   +匹配至少一个           f+匹配至少一个fvar str = 'abbbbbc'var reg = /b+/igconsole.log(reg.exec(str)); //["bbbbb", index: 1, input: "abbbbbc", groups: undefined]//以a开头,中间放数字(至少一个数字),以数字结尾var str = "a1234"var reg = /^a\d+$/igconsole.log(reg.exec(str)); //["a1234", index: 0, input: "a1234", groups: undefined]//4、   m{x,y}    匹配m,至少x次,最多y次        m{x}   匹配m,x次var str = '12345679'var reg = /^[0-9]\d{6,8}/igconsole.log(reg.exec(str)); //["1234569", index: 0, input: "1234569", groups: undefined]//密码 6位数字var str = "123456"var reg = /^\d{6}$/igconsole.log(reg.exec(str)); //["123456", index: 0, input: "123456", groups: undefined]
  • 其他
    //1、    |      或者var str = 'logo'var reg = /this|that|where|logo/igconsole.log(reg.exec(str)); //["logo", index: 0, input: "logo", groups: undefined]//2、   ()      分组var str = "hello world hahaha hehehe"var reg = /(\w+) (\w+) (\w+) (\w+)/igvar arr = reg.exec(str)console.log(arr); //["hello world", "hello", "world", index: 0, input: "hello world", groups: undefined]console.log(RegExp.$1); //helloconsole.log(RegExp.$2); //worldconsole.log(RegExp.$3); //hahahaconsole.log(RegExp.$4); //hehehe//需求:交换hello和world位置console.log(str.replace(reg, '$2 $1 $3 $4')); //world hello hahaha hehehe//3、  (?!^......)       预测不到后面不能是什么var str = '2222222'var reg = /(?!^\d+)/igconsole.log(str.search(reg)); //1        //0表示符合条件      1表示不符合条件var str = '******'console.log(str.search(reg)); //0/* ******      0  符合条件222222      1  不符合条件*/

匿名函数

  • 概念:定义时未直接指定名称的函数,如果函数只需要调用一次,就可以声明匿名函数
  • 优点:节省内存空间。匿名函数可以有效的保证在页面上写入JavaScript,而不会造成全局变量的污染
    //1、普通函数function fn(){}//2、表达式函数var fn1 = function(){}//3、构造函数function Fn2(name){this.name = name}var Fn3 = function(name){this.name = name}//4、事件函数document.onclick = function(){}//5、回调函数function fn4(f){f&&f()}//匿名函数自执行      (函数)()(function(){console.log(111);})()//匿名函数有参数(function (a) {console.log(a); //6})(6)//匿名函数有返回值var f = (function (a) {return a * a})(6)console.log(f); //36

闭包

  • 概念:闭包就是能够读取其他函数内部变量的函数(函数里面套函数内部函数可以访问外部函数变量),在本质上,闭包是将函数内部和外部链接起来的桥梁
  • 特点:在闭包中的变量,会一直存储在内存中,类似于全局变量,避免了全局污染
  • 非必要情况下不要使用闭包,因为会一直存储在内存中,容易造成内存泄漏
    function fn1() {var i = 10function fn2() {console.log(i++);}return fn2}var f = fn1()console.log(f); //fn2这个函数f() //10f() //11f() //12

案例:

        var oLi = document.getElementsByTagName('li')//点击li打印对应的索引值for(var i=0;i<oLi.length;i++){/* oLi[i].index = ioLi[i].onclick = function(){console.log(this.index)} *//* //匿名函数(function(x){oLi[x].onclick = function(){console.log(x)}})(i) *///闭包function f(x){oLi[x].onclick = function(){console.log(x)}}f(i)}

ajax

  • Async Javascript and XML 异步js和XML代码
  • 异步:浏览器在请求数据的时候可以同时进行,不用排队等候,不会造成代码阻塞
  • 同步:浏览器在请求数据的时候不可以同时进行,需要排队等候
  • 概念:指一种创建交互式网页的网页开发技术
  • 传统的网页(不是用Ajax)如果需要更新内容,必须重载整个网页页面。通过在后台与服务器进行少量数据交互,Ajax可以使网页实现异步更新。这意味着可以在不重新加载整个网页 的情况下,对网页的某部分进行更新
  • ajax创建步骤
    • 实例化ajax对象:var xhr = new XMLHttpRequest()
    • 建立连接:xhr.open(请求方式,url地址(必传),是否异步)
      请求方式:get/post。url地址:后台服务器地址。第三个参数:默认为true(异步)false(同 步),一般不传
    • 发送请求:xhr.send()
    • 接收响应数据:xhr.onreadystatechange = function(){}
  • 通信状态码(ajax生命周期) xhr.readyState
    • 0:ajax对象还没创建出来
    • 1:建立起了和后台数据库的连接 open
    • 2:请求已经发送出去 send
    • 3:后台数据库接收到请求,并开始处理
    • 4:后台数据库处理完毕,并将请求的数据响应给前端页面
      在本地请求数据,因为0和1持续时间过短,因此时间还没来得及触发状态码就直接变成2了
  • 网络状态码 xhr.status
    • 网络状态码整理:link
    • 200:请求响应成功,数据源是后台数据库
    • 304:请求响应成功,数据源是本地缓存
    • 403:没有权限访问
    • 404:服务器找不到请求的网页
    • 500及以上:后台代码逻辑有误
    • 503:服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态
  • 获取响应的数据:xhr.responseText
  • get请求
    • 四部曲

      • 创建ajax对象
      • 建立连接
      • 发送请求
      • 通过事件监听响应状态来获取数据
    • 优点:在网络传输上速度相对较快
    • 缺点:
      • ①在提交数据时会直接显示在url地址的后面,不安全
      • get请求提交的数据量比较小,大小只有4kb左右
  • Wamp
    • windows Apache MySQL PHP
    • 这是一个服务器集成软件,安装完之后,计算机就会成为一台本地服务器
    • wamp文件夹中的www文件夹是用来存放项目的目录,我们需要使用服务器环境打开html文件,所以项目都需要存放在www文件夹中
    • 启动方式:在浏览器地址栏中输入 127.0.0.1(本地服务器)
  • post
    • 五部曲

      • 创建ajax对象
      • 建立连接
      • 设置请求头
      • 发送请求
      • 通过事件监听响应状态来获取数据
    • 请求头
      • ajax对象.setRequestHeader(“Content-type”,“application/x-www-form-url encoded”)
    • 优点:
      • 提交的数据不会显示在地址栏后面,相对较安全
      • 传输数据要比get大很多
  • json文件创建
    • ①Json文件不能添加注释
    • ②Json多余逗号要删除
    • ③数据一定要键值对形式
    • ④不能使用单引号,一定要是用双引号
    • ⑤数据由逗号分隔
    • 最外层只能有一个
    • 花括号表示保存对象
    • 方括号表示保存数组
  • 类型转换
    • ①eval(str) 传入一个字符串转化具体js的数据类型
    • ②JSON.parse(str) 将json类型字符串转换为json类型
    • JSON.stringify(obj) 将json类型转换为json类型字符串

封装ajax:

  <div></div><script>var oDiv = document.getElementsByTagName('div')[0]function ajax(url, method, data, success) {//1、创建ajax对象var xhr = new XMLHttpRequest()//2、判断是get还是postif (method == 'get') {//判断data是否有值if (data) {url += '?' + data}xhr.open(method, url)xhr.send()} else {//建立连接xhr.open(method, url)//设置请求头xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")//判断data是否有值if (data) {xhr.send(data)} else {xhr.send()}}xhr.onreadystatechange = function () {if (xhr.readyState === 4) {if (xhr.status === 200 || xhr.status === 304) {success(xhr.responseText)}}}}ajax('get.txt', 'post', 'username=admin', function (res) {console.log(res);oDiv.innerHTML = res})</script>

弹入弹出轮播图

  <div class="wrap"><div class="center"><ul></ul><p></p></div></div><script src="./ujiuye.js"></script><script>var oUl = document.getElementsByTagName('ul')[0]var oP = document.getElementsByTagName('p')[0]var oLi = document.getElementsByTagName('li')var oSpan = document.getElementsByTagName('span')var wrap = document.getElementsByClassName('wrap')[0]ajax('banner.txt', 'get', '', function (res) {var arr = eval(res)console.log(arr);//定义一个字符串用来接收var str1 = ''var str2 = ''for (var i = 0; i < arr.length; i++) {str1 += '<li><img src="' + arr[i].bannerSrc + '"></li>'str2 += '<span></span>'}oUl.innerHTML = str1oP.innerHTML = str2//设置默认样式oLi[0].style.opacity = 1oSpan[0].className = 'active'wrap.style.background = arr[0].bannerBG//用来表示当前是第几张图片var bannerIndex = 0var timer1 = setInterval(bannerAuto, 3000)function bannerAuto() {bannerIndex++if (bannerIndex >= arr.length) {bannerIndex = 0}//上一张隐藏//1显示 0隐藏   2显示 1隐藏  3显示 2隐藏  4显示 3隐藏  5显示 4隐藏  0显示 0-1=-1 -1隐藏//bannerIndex - 1 > 0 ?  bannerIndex-1 : arr.length-1bufferMove(oLi[bannerIndex - 1 > 0 ? bannerIndex - 1 : arr.length - 1], {'opacity': 0})//下一张显示bufferMove(oLi[bannerIndex], {'opacity': 100})//改变背景wrap.style.background = arr[bannerIndex].bannerBG//改变spanfor (var i = 0; i < oSpan.length; i++) {oSpan[i].className = ''}oSpan[bannerIndex].className = 'active'}wrap.onmouseenter = function () {clearInterval(timer1)}wrap.onmouseleave = function () {timer1 = setInterval(bannerAuto, 3000)}//移入小spanfor (var i = 0; i < oSpan.length; i++) {oSpan[i].index = ioSpan[i].onmouseover = function () {//让之前的那一张隐藏bufferMove(oLi[bannerIndex], {'opacity': 0})//让对应的li显示bufferMove(oLi[this.index], {'opacity': 100})//改变小spanfor (var j = 0; j < oSpan.length; j++) {oSpan[j].className = ''}this.className = 'active'wrap.style.background = arr[this.index].bannerBGbannerIndex = this.index}}})</script>

js(event、拖拽、碰撞检测、缓冲运动、多属性运动、轮播图、Object、正则、闭包、ajax)相关推荐

  1. HTML5+CSS3+JS小实例:仿制网易云音乐网站的轮播图

    实例:仿制网易云音乐网站的轮播图 技术栈:HTML+CSS+JS 字体图标库:font-awesome 效果: 源码: <!DOCTYPE html> <html><he ...

  2. 原生JS仿造华为商城案例-实现了简单页面-两种轮播图思路的实现-动态展示数据

    文章目录 功能简介 项目准备 项目说明 方案一:源代码 CSS样式 HTML结构 JS逻辑 方案二:源代码 CSS样式 HTML结构 JS逻辑 功能简介 页面展示 该项目功能实现: 无限滚动轮播图 j ...

  3. 纯JS实现带小圆点缩略图及左右箭头的轮播图

    HTML部分 <body> <div id="container"><div id="list" class="pic& ...

  4. html 轮播图_JS拖拽专题(二)——「实战」滑动轮播图的那点事儿

    欢迎来到我的JS拖拽专题系列文章,更多精彩内容持续更新中,欢迎关注 :) 上一章节我们说到了在js中拖拽的基本原理,即我们在鼠标按下的时候计算出鼠标位置和物理的位置的差值,这个差值在移动的过程中不恒定 ...

  5. js + css 做出网易云音乐的轮播图

    先说一下思路,网易云轮播图是这样的,每隔一段时间(这里运用到了js的定时器)右边的图片会放大(css的transform)并切换(定位的z-index)上来(这里还运用了过渡transition),最 ...

  6. js实现拖拽+碰撞+重力

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...

  7. 李炎恢 js教程 拖拽上 思路解析

    李炎恢再讲js教程 拖拽上 讲到一个登录框,通过鼠标移动登录框到浏览器各个地方,我们现在对李炎恢的怎么想出进行分析: 问题期望是什么? 1.我们通过鼠标点击登录框,然后登录框被移动,松开鼠标,停止移动 ...

  8. 原生JS实现拖拽进度条、滚动鼠标显示相应的内容

    今天要分享的是运用原生JS实现拖拽进度条.滚动鼠标显示相应的内容,实现效果如下: 以下是代码实现,欢迎大家复制粘贴. <!DOCTYPE html> <html><hea ...

  9. 原生JS实现拖拽垂直进度条

    先看效果图 代码如下 <!DOCTYPE html> <html><head><meta http-equiv="Content-Type" ...

最新文章

  1. SQL assistant
  2. JavaScript 里,$ 代表什么?/JQuery是什么语言?/html中用link标签引入css时的中 rel=stylesheet属性?/EL表达式是什么?...
  3. 算法--------最长连续序列(Java版本)
  4. C# 学习笔记(11)蓝屏小工具
  5. js window.open()实现打印,如何在关闭打印窗口时刷新父窗口
  6. Java给定一个字符串数组,判断每个字符出现次数
  7. 幼儿园故事导入语案例_幼儿园小班安全教案
  8. mes选型与实施指南_六大类型MES企业大盘点告诉你如何选择正确选择MES
  9. Steam Roller UVALive - 4128
  10. 计算机应用基础第一章ppt,计算机应用基础第一章课件.ppt
  11. mysql 定时备份和远程备份脚本
  12. 人类的精神寄托和生命的终极关怀——宗教
  13. ReiBoot(iOS系统修复工具)v6.9.5.0官方版
  14. 关于Java事务原理的探讨
  15. 用 Python 实现资本资产定价模型
  16. MATLAB中 分数化简
  17. SQLServer LDF日志文件过大解决方案 2021-09-26
  18. 万兴剪刀手去水印教程_万兴神剪手怎么去水印教程,赶快收藏吧
  19. Gradle transitive = true
  20. MYSQL误删除DELETE数据找回

热门文章

  1. 网站静态化处理—缓存
  2. 自制美容面膜 简单实用方便让你大换肤 - 生活至上,美容至尚!
  3. 在微信的视频通话中将语音转成文字并显示在通话界面中,可以使用语音识别技术,将语音转换成文本,再通过编程技巧将文本显示在通话界面中。实现方法...
  4. html ie11兼容性问题,ie11浏览器兼容性的问题你肯定不知道可以这样解决
  5. flask vue 文件流的方式下载word
  6. xynuoj 2189 六度分离
  7. python shutil删除文件_Python学习笔记组织文件之shutil模块
  8. 有哪些入门级蓝牙耳机推荐?盘点2022高性价比蓝牙耳机
  9. 【Bzoj2748】音量调节
  10. AcWing 125. 耍杂技的牛