原生JS实现FlappyBird游戏 超详细解析 快来做一个自己玩吧

news2024/11/18 7:52:10

目录

1.适配设备🐾

2.背景滚动💐

3.管道的创建与移动🌸

4.小鸟操作🌷

5.碰撞检测🍀

6.触屏事件🌹

7.制作开始与结束面板🌻

8.得分统计🌺


我们先来看看接下来我们要做的效果:🙋🙋🙋

有需要源码和素材的同学,在文章末尾有链接。 

1.适配设备💨

PC端下背景320px*568px(游戏背景图片大小),移动端下占满窗口

新建一个public.js文件,这个文件放一些我们公共的方法,下面我们先定义一个isPhone方法来判断是否是移动端设备

function isPhone() {
    var arr = ["iPhone","iPad","Android"]
    var is = false;
    for(var i = 0;i<arr.length;i++) {
        if(navigator.userAgent.indexOf(arr[i])!=-1) {
            is = true;
        }
    }
    return is;
}

在isPhone方法里我们定义了一个数组arr用来存储移动端的设备名,UserAgent是HTTP请求中的用户标识,一般发送一个能够代表客户端类型的字符串,indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置,如果要检索的字符串值没有出现,则该方法返回 -1

我们默认是PC端,如果indexOf不返回-1说明与数组中的元素匹配,代表是移动端设备,那么我们的isPhone方法就返回true。

这个判断移动端的方法大家可以保存下来,以后很多的项目我们也用的到

因为我们规定移动端下背景图片要占满屏幕,所以需要一个if语句进行判断,如果isPhone返回的是true,说明当前在移动端,我们需要修改背景图片的宽高:

sw和sh是在在外面定义的全局变量,默认情况下sw=320,sh=568,因为在后面我们还会用到sw,sh,所以如果设备是移动端的话,需要对它们进行重新赋值。

if (isPhone()) {
        var bg = document.querySelector('.contain');
        sw = document.documentElement.clientWidth + 'px';
        sh = document.documentElement.clientHeight + 'px';
        bg.style.width = sw;
        bg.style.height = sh;
}

document.documentElement.clientWidth 就是当前设备的屏幕宽度,注意加符号

我们可以在chrome浏览器下模拟移动端不同设备下是否占满全屏,每次换完设备时要刷新页面: 

这样的话我们适配设备的效果就完成了,成功做到了可以在移动端下占满全屏,下面就开始制作我们的flappybird游戏吧!

2.背景滚动💨

在下面的代码中bg是我们获取的最外层装背景图片的盒子,背景图片是在x轴平铺的,所以我们只需要一个定时器不断调用背景移动函数就行,背景移动函数里我们每次调用背景的位置就向左移动5像素

var timer = setInterval(function(){
        bgMove();
},30)
function bgMove() {
      var bg = document.querySelector('.contain');
      bgDis -= 5;
      bg.style.backgroundPosition = `${bgDis}px 0`;
}

在我们制作的这个游戏中,不论是背景移动还是待会要做的管道的移动,小鸟的移动,最后封装的函数都需要在这个定时器里调用,这样才会有我们看到的那种动画一样的效果。 

3.管道的创建与移动💨

在实现管道的移动之前我们先需要创建管道,因为我们要让生成的管道高度不一致,所以需要先写一个随机数函数,我们就在public.js里完成:

function rand(min, max) {
    return Math.round(Math.random() * (max-min) + min);
}

我们先整理一下创建管道的思路:

  1. 先写管道的样式,html与css部分的代码在文章最后都有,大家在看解析的时候要先看一眼html结构和css样式。 
  2. 规定上下管道间隔120px,通过定义好的rand随机函数实现上管道高度随机,背景图片高度减去间隔减去上管道高度就是下管道高度,这里下管道高度不要给随机。
  3. 通过insertAdjacentHTML将生成管道的代码添加到ul里

 因为管道也是不断生成的,我们需要在timer定时器里调用管道移动函数pipeMove():

var timer = setInterval(function(){
        bgMove();
        pipeMove();
},30)
我们在外面定义这个pipeMove方法,在pipeMove里完成管道的创建与移动
function pipeMove() {
       //1.创建管道
       createPipe();
       //2.管道移动
}

下面先来根据在开头写的思路来完善管道创建函数createPipe: 

function createPipe() {
        var pipeheight = rand(100,300);
        var ul = document.querySelector('ul');
        var str = `<li class="top" style="height:${pipeheight+'px'};left:${sw+'px'}"><div></div></li><li class="bottom" style="height:${sh-pipeheight-120+'px'};left:${sw+'px'}"><div></div></li>`;
        ul.insertAdjacentHTML('beforeend',str);
}

运行代码看一看管道有没有被创建出来:

很明显管道数量太多了啊,因为定时器每隔三十毫秒就会调用管道创建函数,所以管道生成的就非常多,我们定义一些全局变量进行限制:

var space = 100;  //创建管道的间隔
var count = 0;  //管道的计数

修改一下createPipe函数,当计数达到创建管道的间隔100时才执行下面创建管道的代码,否则不执行,这样就对生成管道的数量进行了限制

function createPipe() {
       count ++;
       if (count != space) {
            return ;
       }
       count = 0;
       var pipeheight = rand(100,300);
       var ul = document.querySelector('ul');
       var str = `<li class="top" able="0" style="height:${pipeheight+'px'};left:${sw+'px'}"><div></div></li><li class="bottom" style="height:${sh-pipeheight-120+'px'};left:${sw+'px'}"><div></div></li>`;
       ul.insertAdjacentHTML('beforeend',str);
}

现在管道可以在背景的右面不断的生成,这样管道的创建就全部完成了,下面在pipeMove方法里继续完善管道移动的部分:

function pipeMove() {
            //1.创建管道
            createPipe();
            //2.管道移动
            var li = document.querySelectorAll('li');
            li.forEach(function(value,index,arr){
                arr[index].style.left = arr[index].offsetLeft-2+'px';
            })
        }

我们先获取创建的所有管道,然后通过foreach循环每次调用都让管道左移两像素,管道就能成功移动起来了。

注意:直接通过obj.style.left和obj.style.top可以获取位置,但是有局限性,这种获取的方法只能获取到行内样式的left和top的属性值,不能获取到style标签和link 外部引用的left和top属性值。所以这里用offsetleft获取

然后我们再给管道加一个边界,让他超出背景时就在ul里删除这个元素:

li.forEach(function(value,index,arr){
        arr[index].style.left = arr[index].offsetLeft-5+'px';
        if(arr[index].offsetLeft<=-62) {
             ul.removeChild(arr[index]);
        }
})

我们运行代码看一看效果:

 

这样管道的创建与运动就基本上完成了,下面我们开始小鸟的操作。

4.小鸟操作💨

首先我们先把小鸟的html结构和css样式搭建好,下一步就是让小鸟“动起来”。

同样我们需要在定时器中调用小鸟移动函数birdMov

var timer = setInterval(function(){
             bgMove();
             pipeMove();
             birdMove();
        },30)

因为游戏开始的时候小鸟要向下掉落所以先写一个小鸟的移动函数:

function birdMove() {
       var bird = document.querySelector('#bird');
       bird.style.top = bird.offsetTop +5 + 'px';
}

这样的话,小鸟就实现了一直匀速下落的效果,但是游戏中我们的小鸟并不是匀速的所以我们还需要定义一个全局变量speed,初始化它的值为0,来控制小鸟的速度。

因为我们在游戏中单击屏幕时小鸟会向上飞而且向上飞的速度和向下的速度不相同,所以我们在全局声明一个isDown变量,来判断小鸟是否向下飞。默认isDown = true,因为小鸟不操作的话一定是向下飞的。

function birdMove() {
            if(isDown) {
                speed += 0.4;
                speed = speed > 8 ? 8 : speed;
            }
            else{
                speed += 0.7;
            }
            var bird = document.querySelector('.bird');
            bird.style.top = bird.offsetTop +speed + 'px';
}

如果不点击屏幕每隔三十毫秒小鸟的速度就增加0.4,然后用一个三元表达式,如果速度达到8那么就是小鸟的极限速度就不再增加了,最后我们把原来的5这个固定值换成speed就实现了小鸟速度的动态变化

接下来我们要实现的是在单击背景的任一处时小鸟能够向上移动,所以我们需要给背景图片一个点击事件:

var contain = document.querySelector('.contain');
        contain.addEventListener('click',function() {
        isDown = false;
        speed = -8;
})

当我们点击屏幕时,小鸟要向上飞,所以isDown被赋为false,然后立刻给一个向上的位移距离为8

我们运行一下代码看看效果: 

是不是已经有那么点感觉了,但是小鸟点击屏幕的时候头会向上抬,所以还得在点击屏幕的时候改小鸟的背景图片

我们创建两个类,一个birddown类里面是小鸟头向下的图片,一个birdup类里面是小鸟头向上的。

.birddown {
      background: url(./img/down_bird0.png);
}
.bird_up {
      background: url(./img/up_bird0.png);
}

然后给bird添加默认样式类birddown,这样当我们点击屏幕时,就修改bird的类为birdup:

contain.addEventListener('click',function() {
       isDown = false;
       speed = -8;
       var bird = document.querySelector('#bird');
       bird.className = 'birdup';
})

这样的话我们在点击屏幕的时候小鸟就从头向下变成头向上了,但是如果不点击屏幕的时候小鸟还是应该回到默认向下的样式,因为不点击屏幕小鸟就会向下飞,那我们想想这个怎么实现呢?

那小鸟什么时候向下飞呢,就是speed为0的时候,我们每次点击屏幕的时候小鸟的速度都是-8,但是我们一直在调用birdmove,每次speed都加0.7,这样向上的速度总会越来越小然后当大于0 的时候小鸟就向下飞。

这样我们就在birdmove里补全代码实现点击屏幕小鸟就抬头向上飞,下降就低头向下飞:

function birdMove() {
            var bird = document.querySelector('#bird');
            if(isDown) {
                speed += 0.4;
                speed = speed > 8 ? 8 : speed;
            }
            else{
                speed += 0.7;
                if(speed>=0) {
                    speed = 0;
                    isDown = true;
                    bird.className = 'birddown';
                }
            }
            var bird = document.querySelector('#bird');
            bird.style.top = bird.offsetTop +speed + 'px';
        }

我们看一下效果: 

这样我们小鸟的动作就基本写完了,现在需要当小鸟触顶和触底的时候应该让游戏gameover。

把下面判断边界的代码放在birdmove里,这样每次先判断一下是否超出边界,如果超出的话就直接gameover并清除定时器然后执行again函数重新开始游戏。

if(bird.offsetTop<0||bird.offsetTop>sh-30) {
            alert('gameover');
            clearInterval(timer);
            again();
            return;
}

再外面创建这个again函数来实现重新开始游戏:

function again() {
        bgDis = 0;//bg的移动距离
        count = 0;  //管道的计数
        isDown = true;//判断是否向下飞
        speed = 0;//控制小鸟的速度
        var ul = document.querySelector('ul');
        ul.innerHTML = '';//清空管道
        var bird = document.querySelector('#bird');
        bird.style.top = 100+'px';
        start()
}

我们在again函数里要重新初始化一些变量,这里有些变量如管道间隔或者背景宽高是不需要再次初始化的。并且不用带var,因为如果带var了就是局部变量,但这里我们要改变的是全局变量。

然后我们需要清空所有画面中的管道,也就是ul里的内容。然后把小鸟的高度恢复到最开始的距离顶端20像素的位置。

最后调用了一个start函数,这个start函数就是把最开始的计时器给封装了:

function start() {
      timer = setInterval(function(){
           bgMove();
           pipeMove();
           birdMove();
      },30)
}

因为在游戏结束的时候我们清空了计时器,所以重新开始的时候我们得再次调用这个计时器。

注意:计时器变量timer不应该加var,因为封装后加了var的在函数里就不是全局变量了

这样当我们的小鸟在触顶或者触底的时候就会弹出gameover对话框点击确定然后就重新开始游戏

然后我们把原来写的birddown类和birdup类修改为动画

@keyframes birddown {
            from {
                background-image: url(img/down_bird0.png);
            }
            to {
                background-image: url(img/down_bird1.png);
            }
        }
        @keyframes birdup {
            from {
                background-image: url(img/up_bird0.png);
            }
            to {
                background-image: url(img/up_bird1.png);
            }
        }

从bird0到bird1就是小鸟的翅膀有个变化,这样加上动画后小鸟就像在飞动翅膀。 

.birddown {
       animation: birddown 0.05s linear infinite;
}
.birdup {
       animation: birdup 0.05s linear infinite;
}

5.碰撞检测💨

如何判断触顶或者触底对我们来说并不难,但是如何判断小鸟和管道相撞呢?

下面我们回到public.js文件里写一下这个碰撞检测函数isCrash,这个函数同样是复用性很高的。

function isCrash(a,b) {
    var l1 = a.offsetLeft;
    var t1 = a.offsetTop;
    var r1 = l1 + a.offsetWidth;
    var b1 = t1 + a.offsetHeight;

    var l2 = b.offsetLeft;
    var t2 = b.offsetTop;
    var r2 = l2 + b.offsetWidth;
    var b2 = t2 + b.offsetHeight;
    if (r2<l1 || b2<t1 || r1<l2 || b1<t2) {
        // 不碰撞
        return false;
    } else {
        // 碰撞
        return true;
    }
}

在if语句里只要有一个条件不满足就说明不会碰撞,这个很好理解,这里我们就分析一下为什么r2<l1就说明不会碰撞呢?如果这里a代表管道,b代表小鸟,那么l1就是管道到左侧背景的距离,l2代表小鸟到背景左侧的距离,那么r2<l1的意思就是小鸟本身的宽度再加上小鸟到背景左侧的距离比管道到背景左侧的距离还小,这样二者肯定不会碰上,所以其他方向同理。

然后我们在开始函数里再调用一下check()函数:

function start() {
            timer = setInterval(function(){
                 bgMove();
                 pipeMove();
                 birdMove();
                 check();
            },30)
        }

check()函数通过调用isCrash来看所有的管道和小鸟有没有碰撞,如果有的话就gameover那一套

function check() {
            var bird = document.querySelector('#bird');
            var li = document.querySelectorAll('li');
            li.forEach(function(value,index,arr){
                if(isCrash(arr[index],bird)){
                    alert('gameover');
                    clearInterval(timer);
                    again();
                    return;
                }
            })
        }

我们来看一看效果,看看碰撞检测有没有实现:

这样我们所有的碰撞检测都完成了

6.触屏事件💨

因为小鸟只添加了点击事件,所以如果移动端下的话我们还得添加触屏事件:

contain.touchstart = function(e) {
        e.preventDefault();
        isDown = false;
        speed = -8;
        var bird = document.querySelector('#bird');
        bird.className = 'birdup';
}

我们把点击事件里的代码复制到触屏事件里就可以啦,因为在移动端下我们双击屏幕时屏幕会放大,所以我们要阻止默认事件

值得注意的是我们在最开始定义管道的样式时管道的left值是320px,是我们在pc端下的背景宽度,但是在移动端下屏幕宽度不一,所以我们要把默认的320px删掉,在管道生成的函数里定义管道的left值为sw,因为我们在移动端下sw的值就是屏幕的宽度。

7.制作开始与结束面板💨

下面我们先开始制作开始面板,先写完开始面板的样式,然后要做的就是这种上下动的效果,这里还需要我们再用到css的动画效果

定义两个动画,给开始面板的盒子一个move动画这样就实现了上下动的效果,再给小鸟的盒子添加bird动画,这样小鸟就可以扑哧翅膀了

@keyframes bird {
       from {
           background-image: url(img/bird0.png);
       }
       to {
           background-image: url(img/bird1.png);
       }
}
@keyframes move {
       from {
           transform: translateY(-2rem);
       }
       to {
           transform: translateY(2rem);
       }
}

现在我们需要给开始面板的ok按钮一个点击事件,当我们点击开始按钮时要不显示开始面板,然后再显示小鸟,再调用start函数来开始游戏

下面是开始面板的ok点击事件,因为btn按钮有两个一个是开始面板的一个是结束面板的所以btn[0]就是开始面板的按钮

var btn = document.querySelectorAll('.but');
btn[0].addEventListener('click',function() {
        var start1 = document.querySelector('#start');
        var bird = document.querySelector('#bird');
        start1.style.display = 'none';
        bird.style.display = 'block';
        start();
})

结束面板没有什么动画效果,所以我们写完css样式后,就给ok按钮添加点击事件就行,当点击结束面板的ok键时,结束面板隐藏起来,开始面板显示出来,而且最重要的是还要初始化所有全局变量,而我们之前写过一个类似的方法again,所以我们把原来的again方法直接拿过来,把其他的语句放进去直接调用again就行。

btn[1].addEventListener('click',function() {
        again();
})
function again() {
            bgDis = 0;//bg的移动距离
            count = 0;  //管道的计数
            isDown = true;//判断是否向下飞
            speed = 0;//控制小鸟的速度
            var ul = document.querySelector('ul');
            ul.innerHTML = '';//清空管道
            var bird = document.querySelector('#bird');
            bird.style.top = 100+'px';
            var start1 = document.querySelector('#start');
            var bird = document.querySelector('#bird');
            var end = document.querySelector('#end');
            start1.style.display = 'block';
            bird.style.display = 'none';
            end.style.display = 'none';
        }

当小鸟碰到管道或者触顶触底时,先弹出gameover对话框再调用again函数来重新开始游戏。但是现在我们有了结束面板,我们想实现的是把原来的alert换成现在的结束面板,那么我们再封装一个gameover函数,在这个方法里面我们显示结束面板并且游戏结束的时候我们还得统计得分显示在结束面板上(这个部分在下一节统计得分)

if(bird.offsetTop<0||bird.offsetTop>sh-30) {
        clearInterval(timer);
        gameOver();
        return;
}
function gameOver() {
        var end = document.querySelector('#end');
        end.style.display = 'block';
}

我们看一下实现效果:

这样开始面板和结束面板的制作就都完成了。是不是非常丝滑呀

8.得分统计💨

得分我们应该是动态添加的,因为只有当小鸟越过管道的时候才会得分,而小鸟的left值是20px,所以只需要管道的left值加上管道的宽度比小鸟的left值小,那么就代表小鸟越过了管道。

我们定义一个全局变量score,每当小鸟越过一个管道score就加一,我们先简单制作一下样式重点看看这个效果能不能实现

这里的scorex就是上图的粉色框,代码写在管道移动函数里当管道的left值加上管道的宽度比小鸟的left值小时我们让score++,然后把得分赋给盒子让他显示出来:

if(arr[index].offsetLeft+arr[index].offsetWidth<20) {
            score++;
            var scorex = document.querySelector('#score');
            scorex.innerHTML = score;
}

我们看看实现的效果:

 

每次飞过一个管道得分却加了二十,这是为什么呢,不应该每次都加一么?

因为我们把代码放在了管道移动函数里,而管道移动函数每三十毫秒就会被调用一次,所以小鸟只要飞过了管道,就会一直执行score++直到管道被销毁。所以我们需要加一定的限制条件,比如我们可以给管道都加一个自定义属性,设置它的值为0,如果小鸟飞过管道后就让这个属性值为1,这样就不会出现刚才的清空了

我们给上管道设置自定义属性able为0,我们不需要给下管道也设置这个属性,要不然每经过一个管道score就会加2了

if(arr[index].offsetLeft+arr[index].offsetWidth<20) {
         if(arr[index].getAttribute("able") == 0) {
               score++;
               var scorex = document.querySelector('#score');
               scorex.innerHTML = score;
               arr[index].setAttribute("able",'1');
         }
}

修改之后,每次小鸟经过管道分数就会加一,现在我们要做的就是把数字换成对应的图片就行

我们声明一个setScore函数:

function setScore() {
        var arr = (score + "").split("");
        var str = "";
        for (var i=0; i<arr.length; i++) {
            str += `<img src="img/${arr[i]}.png">`;
        }
        var scorex = document.querySelector('#score');
        scorex.innerHTML = str;
}

这里很多同学可能对setScore函数里的第一行不太理解,我们看这段代码:

var score = 110;
console.log(typeof score); //number
arr = (score+'');
console.log(typeof arr);//string

数值型变量后面加一个引号就是字符串型,这样我们就能用字符串方法split把我们的得分变成数组。比如得了12分的话,arr[0]就是1,arr[1]就是2。数组长度就是2,因为我们的数字是一张张图片,图片名就是1.png,2.png,3.png以此类推。所以现在str字符串里存储的就是

<img src="img/${arr[0]}.png">  <img src="img/${arr[1]}.png">,这样对应分数的图片就能显示出来。

注意:在again函数里要加上score=0;setScore()来初始化得分

因为我们需要把得分最高的记录保存到本地,所以需要用到本地存储,把相应的功能加在gameOver方法中:

function gameOver() {
        var end = document.querySelector('#end');
        end.style.display = 'block';
        var socrer = document.querySelector('.score');
        socrer.innerHTML = score;
        if (localStorage.best/1 < score) {
            localStorage.best = score;
        }
        var best = document.querySelector('.best');
        best.innerHTML = localStorage.best;
}

注意:这里localStorage.best/1是因为localStorage.best是字符串类型,需要/1来转化为数值型

下面就是我们的最终成果啦: 

看到这里的同学麻烦点个赞谢谢啦! 🙏  🙏  🙏 

源码地址:

flappybird游戏源码及素材

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/409583.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue 路由报错

在进行如下路由跳转时 const edit (index: number) > { let row: any categoryData.value[index]; router.push({ name: “commodityedit”, query: { id: row.id, name: row.name } }); }; 遇到问题如下 TypeError: Failed to fetch dynamically imported module: http…

【uni-app】第三方ui组件推荐引入的方法

ui组件推荐 1. Muse-UI Muse UI 是一套 Material Design 风格开源组件库&#xff0c;旨在快速搭建页面。它基于 Vue 2.0 开发&#xff0c;并提供了自定义主题&#xff0c;充分满足可定制化的需求。material-design-icons 是谷歌定义的一套icontypeface 是谷歌定义的一套字体…

html+css+js制作LOL官网,web前端大作业(3个页面+模拟登录+链接)

文章目录一、效果图1.1首页1.2 模拟登录1.3 游戏资料页面1.4 商城页面二、代码2.1 首页2.2 资料页面2.3 商城页面三、链接一、效果图 1.1首页 1.2 模拟登录 1.3 游戏资料页面 1.4 商城页面 二、代码 2.1 首页 index.html <!doctype html> <html><head>&l…

JavaScript高级 |如何玩转箭头函数?

本文已收录于专栏⭐️ 《JavaScript》⭐️ 学习指南&#xff1a;箭头函数语法规则简写规则常见应用mapfilterreduce箭头函数中的this使用concatthis的查找规则完结散花参考文献箭头函数 在ES6中新增了函数的简写方式----箭头函数&#xff0c;箭头函数的出现不仅简化了大量代码…

Vue3自动引入组件,组件库

在做vue3项目中时&#xff0c;每次使用都需要先进行引入&#xff0c;用ts的还好&#xff0c;会有爆红提示&#xff0c;如果是使用js开发的很多时候都会等到编译的时候才发现哪里哪里又没有引入&#xff0c;就会很浪费时间&#xff0c;偶然发现一款好用的组件可以帮助我们很好的…

【你不知道的 CSS】你写的 CSS 太过冗余,以至于我对它下手了

:is() 你是否曾经写过下方这样冗余的CSS选择器: .active a, .active button, .active label {color: steelblue; }其实上面这段代码可以这样写&#xff1a; .active :is(a, button, label) {color: steelblue; }看~是不是简洁了很多&#xff01; 是的&#xff0c;你可以使用…

详细分析解决Uncaught SyntaxError: Cannot use import statement outside a module (at ...)的错误

文章目录1. 复现错误2. 分析错误3. 解决错误1. 复现错误 今天在学习es6时&#xff0c;启动页面后&#xff0c;却报出如下图错误&#xff1a; 即Uncaught SyntaxError: Cannot use import statement outside a module (at module.html?_ijtvfvtohb23jt1tj3r4ad3a0t82v:19:5)。 …

解决CitSpace分析新版本web of science文献报错“the timing slicing setting is outside the range of your data”

1.问题新版web of science于2021年7月7日上线&#xff0c;旧版 Web of Science 将同步运行到2021年底。现在旧版web of science入口早已关闭&#xff0c;新本web of science的残产品中也不在提供旧页面入口。近来在使用web of science文献制作CiteSpace图谱时发现&#xff0c;w…

【轻松解决el-dialog关闭后数据缓存 没清空】

问题描述 在使用el-dialog的时候&#xff0c;关闭弹窗之后&#xff0c;发现数据还是保存在上面&#xff0c;查资料试了那些方法&#xff0c;都不太行&#xff0c;最后发现以下方法&#xff0c;泪目。 解决方案&#xff1a; 方案一、使用this.resetForm("form")重置…

vue把el-dialog提取出来作为子组件,并实现父组件和子组件相互传值

最近做项目遇到了一个需求是&#xff0c;为了防止组件中代码冗长&#xff0c;需要将el-dialog对话弹出框单独封装成子组件&#xff0c;并将父组件中的id传递给子组件&#xff0c;子组件再根据id刷新父组件。具体项目代码太长&#xff0c;这里仅记录一下实现思路。 01 把el-dial…

vue 基于el-table实现多页多选、翻页回显过程

近半年时间在接触vue写pc页面&#xff0c;文中内容即在实际的开发过程中遇到的实际问题。 1、问题交代&#xff1a; 在pc版的列表页面中&#xff0c;假设当前在列表的第一页&#xff0c;想要在当前页面选择几行数据&#xff0c;跳转到其他页面选择几行数据&#xff0c;选择后…

【微信小程序】-- 全局数据共享 - MobX(四十三)

&#x1f48c; 所属专栏&#xff1a;【微信小程序开发教程】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &…

利用CSS在图片中添加文字

前端项目中想要在图片中添加文字&#xff0c;方法有两种&#xff1a;1、js&#xff1b;2、css。第一种方法比较复杂&#xff0c;主要是写将图片与文字组合成新的图片的js代码&#xff0c;第二种方法简单粗暴&#xff0c;这里只讲第二种方法。 利用css在图片中添加文字&#xff…

关于npm i 的那点事

在我们开发中会经常用到npm i 这个命令&#xff0c;有npm i -S&#xff0c;npm i -g , npm i -D&#xff0c;npm install --save-dev, npm i -save&#xff0c;那么这几种命令到底有什么区别呢&#xff1f; 要先知道这几种命令的区别&#xff0c;我们首先要认识两个单词&#…

vue3的tsx写法(v-show、v-if、v-for、v-bind、v-on),父子组件传值

1、如下就是vue3的tsx写法&#xff0c;tsx写法中支持使用v-show&#xff0c;如下&#xff1a; import {ref} from vuelet appData ref<string>(); let flag false; const renderDom () > {return (<div><input type"text" v-model{appData.val…

详细教会你在vue中写jsx

目录 前言&#xff1a; 一、用render函数写一个页面&#xff1a; 二、在render函数注册事件 三、vue指令在render函数是怎么代替的&#xff1a; 1、v-if 2、v-show 3、v-for: 4、v-model&#xff1a; 5、.sync 四、render中插槽的使用 1、默认插槽 2、具名插槽 3、作…

Less预处理——初识Less

系列文章目录 文章目录系列文章目录一、Less 简介二、安装 Easy LESS三、第一个小例子一、Less 简介 Less 是一门 CSS 预处理语言&#xff0c;它扩充了 CSS 语言&#xff0c;增加了诸如 变量、混合&#xff08;mixin&#xff09;、函数 等功能&#xff0c;让 CSS 更易维护、方…

react-router-dom V6

目录 1. 前言 2. 变更概览 将 Switch 升级为 Routes 路由匹配组件参数 由 component 改为 element 相对路径识别&#xff08;子路由不需要补全父路由的path&#xff0c;react会自动补全&#xff09; 用 useNavigate 替代 useHistory 废弃 Redirect 标签&#xff0c;使…

Vue基础笔记

创建一个Vue应用 1.应用实例 每个Vue应用都是通过createApp函数创建一个新的应用实例 import { createApp } from vue const app createApp({ //根组件选项}) 2.根组件 若使用的是单文件组件&#xff0c;可直接从另一个文件中导入根组件 import {createApp } from vue import …

Vue3通透教程【十】跨级组件通讯—依赖注入

文章目录&#x1f31f; 写在前面&#x1f31f; provide函数&#x1f31f; inject 函数&#x1f31f; 跨组件通讯&#x1f31f; 写在最后&#x1f31f; 写在前面 专栏介绍&#xff1a; 凉哥作为 Vue 的忠实 粉丝输出过大量的 Vue 文章&#xff0c;应粉丝要求开始更新 Vue3 的相…