JS实践(乾坤未定,你我皆是黑马4-3)

上一篇后半部分写的不好,就是浅显的罗列语法。排序,下周补充其余6种…
这篇讲了几个js案例:开关灯汉字自动播放轮播图
看完之后你能学会dom操作以及成就感。

javascript 原生方法对dom节点的操作包括:
访问(查找)、创建、添加、删除、替换、插入、复制、移动等。

唉,等等等等??? 什么是dom???

js分为ECMAScript、DOM、BOM三部分,第一部分是语法,就是变量啊函数啊,操作符啊等等等等的,DOM是操作文档对象,BOM是浏览器对象

今天只看DOM,也就是咱们写的HTML文档对象,整个html都归DOM管,
就是说可以通过dom来任意修改html文档

文档乖乖躺好,咱们做点什么呐?
理论没意思,直接上案例,“开关灯”

在这里插入图片描述html里面有两个button元素,所谓元素就是用标签和它肚子里的一坨代码,标签就是尖括号加单词,这两个元素都有id,就是唯一识别,跟身份证一样,id的属性值不可以与其它元素一样。
我们用id来唯一识别这个元素,在做css时可以用 # 也就是id选择器来选这个元素,修改样式,那么js也有相应的方法-------document.getElementById("*****");
为什么前面要加上document???前面学了对象,我们把一类的方法,封装到一个对象里…而document就是大名鼎鼎的DOM对象(如果对面向对象不理解,后面还会讲)
总之我们通过id来拿一个元素的时候(一般做功能时用id拿),语法这样写:document.getElementById(“一个id”);

那么同理,通过class拿元素时是document.getElementsByClassName(“类名”);
只不过类名可以重复,所以我们拿到的是一个伪数组 [元素1,元素2,元素3]
伪数组用起来和和数组没什么不同,取值arr[i],遍历for循环,只不过它不是Array,所以不能直接用Array的方法。
为什么要加一个直接呐?

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <p></p>
    <p></p>
    <p></p>
    <p></p>
    <p></p>
    <p></p>
    <p></p>
    <script>
        var ps = document.getElementsByTagName("p");
        Array.prototype.forEach.call(ps, function(value, index) {
            console.log(index + "_" + value);
        });
    </script>
</body>

</html>

在这里插入图片描述

就像上面所使用的的代码一样,我们在js里面有改变指针方向的方法,如果你不清楚什么是call,什么是bind什么是apply,那么只能说我写的上一篇偷懒了,后面会和面向对象编程一样,单独写一篇来讲清楚,这里仅仅介绍,js还有这么一个玩意。

至此我们使用document.getElementById("")拿到on和off两个按钮元素,使用document.getElementsByClassName("")[0]拿到页面里的第一个类名为box的元素
(由此可见,做功能时用id比较靠谱,数第几个,万一再来几个box,就容易乱了)

拿到之后绑定事件,我们在硬件上操作,敲键盘,这都被浏览器所监听,只要我们在js上写了事件对应的函数,浏览器就会在这个事件发生时,调用这个函数。
用到的事件名叫点击事件,有两种写法,我们用的是简单的写法,给onclick属性赋值,其中click这个单词是点击的意思,常见的属性还有onmouseleave,mouseleave是鼠标移开的意思,还有onfocus等等
精讲讲的是概念,就不会罗列了,罗列的话,其实也没要讲,讲了不一定记住,更不一定会用,而精讲就是为了让大家会用。
off.οnclick=function(){ 巴拉巴拉 }
元素的这个属性赋值为一个函数,剩下的都归浏览器管,事件触发时,调用这个函数

接下来我们来写事件所绑定的函数
box.style.backgroundColor="#9e9e9e";
里面就写了一行代码,元素的一个叫做style的属性的一个backgroundColor属性,赋值为"#9e9e9e",看上去就是改颜色的
元素的style属性是一个对象,其实元素在内存中就是一个对象,对象是什么?是一种以键值对存储数据的数据类型,也是类的实例,类是对一类现实事物的抽象,对象代表其中一个
style里面存着很多信息,它们都跟样式有关
style对象都有啥属性?
它的属性就是css样式的属性啊,只不过写法不太一样,当一个属性有连接符时需要,需要用大写来表示,意思就是css的margin-left在style对象的属性里面是marginLeft
所以我们想要修改元素的样式时,只需要 元素.style.属性名=“属性值”;
#9e9e9e是颜色的一种表示方法,之前的博客有讲过,那篇比较长,讲了全部css,这里重新说一下。

在这里插入图片描述好了现在可以自己动手敲这么一个超级小的开关灯案例了
当然,这篇进度条告诉我们,这篇文章还有很…很长…

//查找节点
document.getElementById(“id”);// 通过id查找,返回唯一的节点
document.getElementsByClassName(“class”);// 通过class查找,返回值为nodeList类型
document.getElementsByTagName(“div”);// 通过标签名查找,返回值为nodeList类型

//创建节点
document.createDocumentFragment();//创建内存文档碎片
document.createElement();//创建元素
document.createTextNode();//创建文本节点

//添加节点
var ele = document.getElementById(“my_div”);
var oldEle = document.createElement(“p”);
var newEle=document.createElement(“div”);
ele.appendChild(oldEle);

//删除节点
ele.removeChild(oldEle);

//替换节点
ele.replaceChild(newEle,oldEle);

//插入节点
ele.insertBefore(oldEle,newEle);//在newEle之前插入 oldEle节点

//复制节点
var cEle = oldEle.cloneNode(true);//深度复制,复制节点下面所有的子节点
cEle = oldEle.cloneNode(false);//只复制当前节点,不复制子节点

//移动节点
var cloneEle = oldEle.cloneNode(true);//被移动的节点
document.removeChild(oldEle);//删除原节点
document.insertBefore(cloneEle,newEle);//插入到目标节点之前

上面是知识的罗列,放在这里供你复习
我们只讲案例,不讲罗列的到底是什么

<script>
        var str = "今天是7月4日,哈哈哈哈,再过一个月,就要找乐子了,啦啦啦啦";
        var len = str.length;
        var length = len;
        var 爱了爱了 = document.createElement("p");
        爱了爱了.addClassName = "爱了爱了";
        爱了爱了.innerText = "开始: ";
        document.getElementsByTagName("body")[0].appendChild(爱了爱了);
        var timer = setInterval(() => {
            var span = document.createElement("span");
            span.innerText = str.charAt(length - len);
            爱了爱了.appendChild(span);
            len--;
            if (len <= 0) {
                clearInterval(timer);
            }
        }, 200);
    </script>

在这里插入图片描述然后我们给他稍微加点特效,看不明白的可以去翻阅我之前的博客,有讲css
赋值粘贴就可以运行,这里文字一出来是模糊的,后来好了,这就是为什么要把每个字当做一个元素处理。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        span {
            text-shadow: 0 0 60px transparent;
            transition: text-shadow 1.5s;
            color: transparent;
            font-size: 30px;
            font-weight: 900;
            opacity: 0;
        }
    </style>
</head>

<body>
    <script>
        var str = "今天是7月4日,哈哈哈哈,再过一个月,就要找乐子了,啦啦啦啦";
        var len = str.length;
        var length = len;
        var 爱了爱了 = document.createElement("p");
        爱了爱了.addClassName = "爱了爱了";
        爱了爱了.innerText = "开始: ";
        document.getElementsByTagName("body")[0].appendChild(爱了爱了);
        var timer = setInterval(() => {
            let span = document.createElement("span");
            span.innerText = str.charAt(length - len);
            爱了爱了.appendChild(span);
            lala(span)
            len--;
            if (len <= 0) {
                clearInterval(timer);
            }
        }, 200);

        function lala(span) {
            setTimeout(() => {
                span.style.textShadow = "0 0 0 black";
                span.style.opacity = "1";
            }, 300);
        }
    </script>
</body>

</html>

我们创建了p元素,并把它添加到body元素肚子里,
我们创建了一个一个的字,然后加到p元素里,
当然,这里我们练习了定时器的使用,定时循环!

创建元素操作就是createElement("");
添加元素是appendChild()
或者给innerHTML重新赋值(顾名思义,这是在修改里面的html代码)
innerText则是修改里面的文字信息,修改TEXT_NODE节点信息
类操作就是操作class的属性

/**
             * obj:制定元素
             * cn:对应类名
             **/
            //定义一个函数,来向一个元素添加类
            function addClass(obj,cn){
                
                if(!hasClass(obj,cn))
                {
                    obj.className+=" "+cn;
                }
            }
            //定义一个函数判断一个元素有没有这个类
            function hasClass(obj,cn){
                //创建一个正则表达式
                var reg=new RegExp("\\b"+cn+"\\b");
                return reg.test(obj.className)
            }
            //定义一个函数来删除对应元素中的类
            function removeClass(obj,cn){
                //创建一个正则表达式
                var reg=new RegExp("\\b "+cn+"\\b");
                //删除Class
                obj.className=obj.className.replace(reg,"");
            }
            //定义一个函数来切换一个类
            function toggleClass(obj,cn){
                //判断是否有这个类
                if(hasClass(obj,cn))
                {
                    //如果有则删除
                    removeClass(obj,cn);
                }
                else
                {
                    //没有则添加
                    addClass(obj,cn);
                }
            }

这里正则的\b是单词边界,类名为a,不能把aa也算上
正则的test()方法很简单,匹配到符合规则的就返回true

定时器就是开的时候返回值保存一下,清空的时候传进去

再写一个js原生轮播图的案例,下午来写…

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        ul,
        ol,
        li {
            margin: 0;
            padding: 0;
            list-style: none;
        }
        
        .container {
            width: 900px;
            height: 500px;
            margin: 100px auto;
        }
        
        .slider {
            position: relative;
            min-width: 300px;
            width: 500px;
            height: 400px;
            margin: 0 auto;
            border: 5px solid black;
            border-radius: 20px;
            overflow: hidden;
        }
        
        ul {
            width: 600%;
            height: 100%;
            display: flex;
            position: absolute;
        }
        
        ul>li {
            flex: 1;
            height: 100%;
            border-radius: 10px;
        }
        
        ol {
            position: absolute;
            left: 50%;
            transform: translateX(-50%);
            top: 80%;
            width: 270px;
            height: 30px;
        }
        
        ol>li {
            width: 30px;
            height: 100%;
            float: left;
            position: relative;
            ;
        }
        
        ol>li:not(:last-child) {
            margin-right: 30px;
        }
        
        .heart:hover {
            animation-name: shake;
            animation-duration: .5s;
            animation-iteration-count: infinite;
        }
        
        .heart div {
            width: 100%;
            height: 100%;
            position: absolute;
            background: rgba(238, 23, 23, 0.449);
        }
        
        .heart:hover div {
            animation-name: shadow;
            animation-duration: .5s;
            animation-iteration-count: infinite;
        }
        
        .topLeft,
        .topRight {
            border-radius: 50% 50% 0 0;
        }
        
        .topLeft {
            transform: translate(-50%, 0) rotate(-45deg)scale(.8, .9);
        }
        
        .topRight {
            transform: translate(51%, 0) rotate(45deg)scale(.8, .9);
        }
        
        .bottom {
            transform: translate(5%, 55%) rotate(45deg) scale(.7, .8);
        }
        /* 定义动画 */
        
        @keyframes shake {
            from {
                transform: scale(.9, .9);
            }
            to {
                transform: scale(1.1, 1.1);
            }
        }
        
        @keyframes shadow {
            from {}
            to {
                box-shadow: 0px 0px 50px red;
            }
        }
        
        .controls {
            position: absolute;
            left: 0;
            top: 50%;
            transform: translateY(-50%);
            width: 100%;
            height: 50px;
            display: none;
        }
        
        .left,
        .right {
            position: absolute;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            top: -25px;
        }
        
        .right {
            right: 0;
        }
        
        ul>li:nth-child(1) {
            background-color: indigo;
        }
        
        ul>li:nth-child(2) {
            background-color: pink;
        }
        
        ul>li:nth-child(3) {
            background-color: yellow;
        }
        
        ul>li:nth-child(4) {
            background-color: green;
        }
        
        ul>li:nth-child(5) {
            background-color: blue;
        }
        
        ul>li:nth-child(6) {
            background-color: indigo;
        }
    </style>
</head>

<body>
    <div class="container">
        <div class="slider">
            <ul id="罪魁祸首">
                <li>

                </li>
                <li>

                </li>
                <li>

                </li>
                <li>

                </li>
                <li>

                </li>
                <li>

                </li>
            </ul>
            <ol>
                <li class="heart d">
                    <div class="topLeft"></div>
                    <div class="topRight"></div>
                    <div class="bottom"></div>
                </li>
                <li class="heart d">
                    <div class="topLeft"></div>
                    <div class="topRight"></div>
                    <div class="bottom"></div>
                </li>
                <li class="heart d">
                    <div class="topLeft"></div>
                    <div class="topRight"></div>
                    <div class="bottom"></div>
                </li>
                <li class="heart d">
                    <div class="topLeft"></div>
                    <div class="topRight"></div>
                    <div class="bottom"></div>
                </li>
                <li class="heart d">
                    <div class="topLeft"></div>
                    <div class="topRight"></div>
                    <div class="bottom"></div>
                </li>
            </ol>
            <div class="controls">
                <li class="heart left">
                    <div class="topLeft"></div>
                    <div class="topRight"></div>
                    <div class="bottom"></div>
                </li>
                <li class="heart right">
                    <div class="topLeft"></div>
                    <div class="topRight"></div>
                    <div class="bottom"></div>
                </li>
            </div>
        </div>
    </div>
    <script>
        var con = document.getElementsByClassName("controls")[0];
        var slider = document.getElementsByClassName("slider")[0];
        var 罪魁祸首 = document.getElementById("罪魁祸首");
        var ol_lis = document.getElementsByClassName("d");
        var left = document.getElementsByClassName("left")[0];
        var right = document.getElementsByClassName("right")[0];

        var index = 0;
        var timer;

        function 垃圾函数(index) {
            let target = -parseInt(index * (1 / 6) * (罪魁祸首.offsetWidth));
            let current = parseInt(罪魁祸首.offsetLeft);
            clearInterval(timer);
            timer = setInterval(() => {
                current += target > current ? Math.ceil((target - current) / 10) : Math.floor((target - current) / 10);
                // 一行很丑的代码
                罪魁祸首.style.left = current + "px";
                if (target === current) {
                    clearInterval(timer);
                }
            }, 30);
        }
        slider.onmouseenter = function() {
            con.style.display = "block";
        }
        slider.onmouseleave = function() {
            con.style.display = "none";
        }
        Array.prototype.forEach.call(ol_lis, function(value, i) {
            value.onclick = function() {
                ! function(i) {
                    index = i;
                    垃圾函数(index);
                }(i);
            }
        });
        left.onclick = function() {
            if (index === 0) {
                罪魁祸首.style.left = -(5 / 6) * (罪魁祸首.offsetWidth) + "px";
                index = 5;
            }
            index--;
            垃圾函数(index);
        }
        right.onclick = function() {
            if (index === 5) {
                罪魁祸首.style.left = 0;
                index = 0;
            }
            index++;
            垃圾函数(index);
        }
    </script>
</body>

</html>

轮播图嘛,似乎我又忘了做自动轮播了,,,希望好心的客人能在评论区补充上,自动轮播。
这里面的小特效就是鼠标移到按钮上,播放css动画,心变大变小,阴影模糊程度时高时低。
讲一讲那行很丑的代码吧:
current += target > current ? Math.ceil((target - current) / 10) : Math.floor((target - current) / 10);
这行应该拆开写的,不好看,所以我说他丑。
current是没有单位的当前的定位的left的值
+=就是加一点,有可能是往左走,也有可能是往右走,所以右面用三元表达式分了两种情况
target>current?:
如果目标在现在右边,那么目标大(left值),那么所以:左边表达式的值就被+上去了
目标大,那么加的这一步是正数,取天花板(Math.ceil()),这样一来最小也是1px,另外px也不用小数,发光点一定大于1,除以10是为了一小步一小步的走
这样一来,每次走1/10,最小走1px;

这里有防抖处理,就是开启定时器之前先clearInterval(),把上一个定时器去除
如果不去除,那么两个一起跑,结果你自己试试就知道了。
节流、防抖这两个操作,回头还有机会再讲一遍。现在没有实际的场景,扯犊子没什么意思。
节流就是搞一个东西记录时间,判断两次点击之间时间差,太短了的话就return
某些网站的搜索功能是10s一次,不知道你有没有看过~~~~

下一篇会讲js开发一个小游戏

猜你喜欢

转载自blog.csdn.net/jvhbi/article/details/107119867
4-3