服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服务器之家 - 编程语言 - JavaScript - vue.js - VUE+Canvas 实现桌面弹球消砖块小游戏的示例代码

VUE+Canvas 实现桌面弹球消砖块小游戏的示例代码

2022-02-28 16:37登楼痕 vue.js

这篇文章主要介绍了VUE+Canvas 实现桌面弹球消砖块小游戏,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

大家都玩过弹球消砖块游戏,左右键控制最底端的一个小木板平移,接住掉落的小球,将球弹起后消除画面上方的一堆砖块。

那么用VUE+Canvas如何来实现呢?实现思路很简单,首先来拆分一下要画在画布上的内容:

(1)用键盘左右按键控制平移的木板;

(2)在画布内四处弹跳的小球;

(3)固定在画面上方,并且被球碰撞后就消失的一堆砖块。

将上述三种对象,用requestAnimationFrame()函数平移运动起来,再结合各种碰撞检查,就可以得到最终的结果。

先看看最终的效果:

VUE+Canvas 实现桌面弹球消砖块小游戏的示例代码

一、左右平移的木板

最底部的木板是最简单的一部分,因为木板的y坐标是固定的,我们设置木板的初始参数,包括其宽度,高度,平移速度等,然后实现画木板的函数:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
pannel: {
        x: 0,
        y: 0,
        height: 8,
        width: 100,
        speed: 8,
        dx: 0
},
 
....
 
drawPannel() {
      this.drawRoundRect(
        this.pannel.x,
        this.pannel.y,
        this.pannel.width,
        this.pannel.height,
        5
      );
},
drawRoundRect(x, y, width, height, radius) { // 画圆角矩形
      this.ctx.beginPath();
      this.ctx.arc(x + radius, y + radius, radius, Math.PI, (Math.PI * 3) / 2);
      this.ctx.lineTo(width - radius + x, y);
      this.ctx.arc(
        width - radius + x,
        radius + y,
        radius,
        (Math.PI * 3) / 2,
        Math.PI * 2
      );
      this.ctx.lineTo(width + x, height + y - radius);
      this.ctx.arc(
        width - radius + x,
        height - radius + y,
        radius,
        0,
        (Math.PI * 1) / 2
      );
      this.ctx.lineTo(radius + x, height + y);
      this.ctx.arc(
        radius + x,
        height - radius + y,
        radius,
        (Math.PI * 1) / 2,
        Math.PI
      );
      this.ctx.fillStyle = "#008b8b";
      this.ctx.fill();
      this.ctx.closePath();
}

程序初始化的时候,监听键盘的左右方向键,来移动木板,通过长度判断是否移动到了左右边界使其不能继续移出画面:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
document.onkeydown = function(e) {
      let key = window.event.keyCode;
      if (key === 37) {
        // 左键
        _this.pannel.dx = -_this.pannel.speed;
      } else if (key === 39) {
        // 右键
        _this.pannel.dx = _this.pannel.speed;
      }
};
document.onkeyup = function(e) {
      _this.pannel.dx = 0;
};
....
 
 movePannel() {
      this.pannel.x += this.pannel.dx;
      if (this.pannel.x > this.clientWidth - this.pannel.width) {
        this.pannel.x = this.clientWidth - this.pannel.width;
      } else if (this.pannel.x < 0) {
        this.pannel.x = 0;
      }
},

二、弹跳的小球和碰撞检测

小球的运动和木板类似,只是不仅有dx的偏移,还有dy的偏移。

而且还要有碰撞检测:

(1)当碰撞的是上、右、左墙壁以及木板上的时候则反弹;

(2)当碰撞到是木板以外的下边界的时候,则输掉游戏;

(3)当碰撞的是砖块的时候,被碰的砖块消失,分数+1,小球反弹。

于是和木板一样,将小球部分分为画小球函数drawBall()和小球运动函数moveBall():

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
drawBall() {
      this.ctx.beginPath();
      this.ctx.arc(this.ball.x, this.ball.y, this.ball.r, 0, 2 * Math.PI);
      this.ctx.fillStyle = "#008b8b";
      this.ctx.fill();
      this.ctx.closePath();
},
moveBall() {
      this.ball.x += this.ball.dx;
      this.ball.y += this.ball.dy;
      this.breaksHandle();
      this.edgeHandle();
},
breaksHandle() {
      // 触碰砖块检测
      this.breaks.forEach(item => {
        if (item.show) {
          if (
            this.ball.x + this.ball.r > item.x &&
            this.ball.x - this.ball.r < item.x + this.breaksConfig.width &&
            this.ball.y + this.ball.r > item.y &&
            this.ball.y - this.ball.r < item.y + this.breaksConfig.height
          ) {
            item.show = false;
            this.ball.dy *= -1;
            this.score ++ ;
            if(this.showBreaksCount === 0){
              this.gameOver = true;
            }
          }
        }
      });
},
edgeHandle() {
      // 边缘检测
      // 碰到顶部反弹
      if (this.ball.y - this.ball.r < 0) {
        this.ball.dy = -this.ball.dy;
      }
      if (
        // 碰到左右墙壁
        this.ball.x - this.ball.r < 0 ||
        this.ball.x + this.ball.r > this.clientWidth
      ) {
        this.ball.dx = -this.ball.dx;
      }
      if (
        this.ball.x >= this.pannel.x &&
        this.ball.x <= this.pannel.x + this.pannel.width &&
        this.ball.y + this.ball.r >= this.clientHeight - this.pannel.height
      ) {
        // 球的x在板子范围内并触碰到了板子
        this.ball.dy *= -1;
      } else if (
        (this.ball.x < this.pannel.x ||
          this.ball.x > this.pannel.x + this.pannel.width) &&
        this.ball.y + this.ball.r >= this.clientHeight
      ) {
        // 球碰到了底边缘了
        this.gameOver = true;
        this.getCurshBreaks();
      }
}

三、砖块的生成

砖块的生成也比较简单,这里我们初始了一些数据:

?
1
2
3
4
5
6
7
8
breaksConfig: {
        row: 6, // 排数
        height: 25, // 砖块高度
        width: 130, // 砖块宽度
        radius: 5, // 矩形圆角
        space: 0, // 间距
        colunm: 6 // 列数
}

根据这些配置项以及画布宽度,我们可以计算出每个砖块的横向间隙是多少:

?
1
2
3
4
5
6
// 计算得出砖块缝隙宽度
      this.breaksConfig.space = Math.floor(
        (this.clientWidth -
          this.breaksConfig.width * this.breaksConfig.colunm) /
          (this.breaksConfig.colunm + 1)
      );

于是我们可以得到每个砖块在画布中的x,y坐标(指的砖块左上角的坐标)

?
1
2
3
4
5
6
7
8
9
for (let i = 0; i < _this.breaksConfig.row; i++) {
        for (let j = 0; j < _this.breaksConfig.colunm; j++) {
          _this.breaks.push({
            x: this.breaksConfig.space * (j + 1) + this.breaksConfig.width * j,
            y: 10 * (i + 1) + this.breaksConfig.height * i,
            show: true
          });
        }
      }

再加上绘制砖块的函数:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
drawBreaks() {
      let _this = this;
      _this.breaks.forEach(item => {
        if (item.show) {
          _this.drawRoundRect(
            item.x,
            item.y,
            _this.breaksConfig.width,
            _this.breaksConfig.height,
            _this.breaksConfig.radius
          );
        }
      });
}

四、让上面三个部分动起来

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(function animloop() {
      if (!_this.gameOver) {
        _this.movePannel();
        _this.moveBall();
        _this.drawAll();
      } else {
        _this.drawCrushBreaks();
      }
      window.requestAnimationFrame(animloop);
})();
....
 drawAll() {
      this.ctx.clearRect(0, 0, this.clientWidth, this.clientHeight);
      this.drawPannel();
      this.drawBall();
      this.drawScore();
      this.drawBreaks();
}

五、游戏结束后的效果

在最开始的动图里可以看到,游戏结束后,砖块粉碎成了若干的小球掉落,这个其实和画单独的小球类似,思路就是把剩余的砖块中心坐标处生产若干大小不等,运动轨迹不等,颜色不等的小球,然后继续动画。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
getCurshBreaks() {
      let _this = this;
      this.breaks.forEach(item => {
        if (item.show) {
          item.show = false;
          for (let i = 0; i < 8; i++) { // 每个砖块粉碎为8个小球
            this.crushBalls.push({
              x: item.x + this.breaksConfig.width / 2,
              y: item.y + this.breaksConfig.height / 2,
              dx: _this.getRandomArbitrary(-6, 6),
              dy: _this.getRandomArbitrary(-6, 6),
              r: _this.getRandomArbitrary(1, 4),
              color: _this.getRandomColor()
            });
          }
        }
      });
},
drawCrushBreaks() {
      this.ctx.clearRect(0, 0, this.clientWidth, this.clientHeight);
      this.crushBalls.forEach(item => {
        this.ctx.beginPath();
        this.ctx.arc(item.x, item.y, item.r, 0, 2 * Math.PI);
        this.ctx.fillStyle = item.color;
        this.ctx.fill();
        this.ctx.closePath();
        item.x += item.dx;
        item.y += item.dy;
        if (
          // 碰到左右墙壁
          item.x - item.r < 0 ||
          item.x + item.r > this.clientWidth
        ) {
          item.dx = -item.dx;
        }
        if (
          // 碰到上下墙壁
          item.y - item.r < 0 ||
          item.y + item.r > this.clientHeight
        ) {
          item.dy = -item.dy;
        }
      });
},

以上就是桌面弹球消砖块小游戏的实现思路和部分代码,实现起来很简单,两三百行代码就可以实现这个小游戏。在小球的运动上可以进行持续优化,并且也可以增加难度选项操作。

最后附上全部的vue文件代码,供大家参考学习:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
<template>
  <div class="break-ball">
    <canvas id="breakBall" width="900" height="600"></canvas>
    <div class="container" v-if="gameOver">
      <div class="dialog">
        <p class="once-again">本轮分数:{{score}}分</p>
        <p class="once-again">真好玩!</p>
        <p class="once-again">再来一次~~</p>
        <el-button class="once-again-btn" @click="init">开始</el-button>
      </div>
    </div>
  </div>
</template>
 
<script>
const randomColor = [
  "#FF95CA",
  "#00E3E3",
  "#00E3E3",
  "#6F00D2",
  "#6F00D2",
  "#C2C287",
  "#ECFFFF",
  "#FFDC35",
  "#93FF93",
  "#d0d0d0"
];
export default {
  name: "BreakBall",
  data() {
    return {
      clientWidth: 0,
      clientHeight: 0,
      ctx: null,
      crushBalls: [],
      pannel: {
        x: 0,
        y: 0,
        height: 8,
        width: 100,
        speed: 8,
        dx: 0
      },
      ball: {
        x: 0,
        y: 0,
        r: 8,
        dx: -4,
        dy: -4
      },
      score: 0,
      gameOver: false,
      breaks: [],
      breaksConfig: {
        row: 6, // 排数
        height: 25, // 砖块高度
        width: 130, // 砖块宽度
        radius: 5, // 矩形圆角
        space: 0, // 间距
        colunm: 6 // 列数
      }
    };
  },
  mounted() {
    let _this = this;
    let container = document.getElementById("breakBall");
    this.ctx = container.getContext("2d");
    this.clientHeight = container.height;
    this.clientWidth = container.width;
    _this.init();
    document.onkeydown = function(e) {
      let key = window.event.keyCode;
      if (key === 37) {
        // 左键
        _this.pannel.dx = -_this.pannel.speed;
      } else if (key === 39) {
        // 右键
        _this.pannel.dx = _this.pannel.speed;
      }
    };
    document.onkeyup = function(e) {
      _this.pannel.dx = 0;
    };
    (function animloop() {
      if (!_this.gameOver) {
        _this.movePannel();
        _this.moveBall();
        _this.drawAll();
      } else {
        _this.drawCrushBreaks();
      }
      window.requestAnimationFrame(animloop);
    })();
  },
  computed:{
    showBreaksCount(){
      return this.breaks.filter(item=>{
        return item.show;
      }).length;
    }
  },
  methods: {
    init() {
      let _this = this;
      _this.gameOver = false;
      this.pannel.y = this.clientHeight - this.pannel.height;
      this.pannel.x = this.clientWidth / 2 - this.pannel.width / 2;
      this.ball.y = this.clientHeight / 2;
      this.ball.x = this.clientWidth / 2;
      this.score = 0;
      this.ball.dx = [-1,1][Math.floor(Math.random() * 2)]*4;
      this.ball.dy = [-1,1][Math.floor(Math.random() * 2)]*4;
      this.crushBalls = [];
      this.breaks = [];
      // 计算得出砖块缝隙宽度
      this.breaksConfig.space = Math.floor(
        (this.clientWidth -
          this.breaksConfig.width * this.breaksConfig.colunm) /
          (this.breaksConfig.colunm + 1)
      );
 
      for (let i = 0; i < _this.breaksConfig.row; i++) {
        for (let j = 0; j < _this.breaksConfig.colunm; j++) {
          _this.breaks.push({
            x: this.breaksConfig.space * (j + 1) + this.breaksConfig.width * j,
            y: 10 * (i + 1) + this.breaksConfig.height * i,
            show: true
          });
        }
      }
    },
    drawAll() {
      this.ctx.clearRect(0, 0, this.clientWidth, this.clientHeight);
      this.drawPannel();
      this.drawBall();
      this.drawScore();
      this.drawBreaks();
    },
    movePannel() {
      this.pannel.x += this.pannel.dx;
      if (this.pannel.x > this.clientWidth - this.pannel.width) {
        this.pannel.x = this.clientWidth - this.pannel.width;
      } else if (this.pannel.x < 0) {
        this.pannel.x = 0;
      }
    },
    moveBall() {
      this.ball.x += this.ball.dx;
      this.ball.y += this.ball.dy;
      this.breaksHandle();
      this.edgeHandle();
    },
    breaksHandle() {
      // 触碰砖块检测
      this.breaks.forEach(item => {
        if (item.show) {
          if (
            this.ball.x + this.ball.r > item.x &&
            this.ball.x - this.ball.r < item.x + this.breaksConfig.width &&
            this.ball.y + this.ball.r > item.y &&
            this.ball.y - this.ball.r < item.y + this.breaksConfig.height
          ) {
            item.show = false;
            this.ball.dy *= -1;
            this.score ++ ;
            if(this.showBreaksCount === 0){
              this.gameOver = true;
            }
          }
        }
      });
    },
    edgeHandle() {
      // 边缘检测
      // 碰到顶部反弹
      if (this.ball.y - this.ball.r < 0) {
        this.ball.dy = -this.ball.dy;
      }
      if (
        // 碰到左右墙壁
        this.ball.x - this.ball.r < 0 ||
        this.ball.x + this.ball.r > this.clientWidth
      ) {
        this.ball.dx = -this.ball.dx;
      }
      if (
        this.ball.x >= this.pannel.x &&
        this.ball.x <= this.pannel.x + this.pannel.width &&
        this.ball.y + this.ball.r >= this.clientHeight - this.pannel.height
      ) {
        // 球的x在板子范围内并触碰到了板子
        this.ball.dy *= -1;
      } else if (
        (this.ball.x < this.pannel.x ||
          this.ball.x > this.pannel.x + this.pannel.width) &&
        this.ball.y + this.ball.r >= this.clientHeight
      ) {
        // 球碰到了底边缘了
        this.gameOver = true;
        this.getCurshBreaks();
      }
    },
    drawScore(){
      this.ctx.beginPath();
      this.ctx.font="14px Arial";
      this.ctx.fillStyle = "#FFF";
      this.ctx.fillText("分数:"+this.score,10,this.clientHeight-14);
      this.ctx.closePath();
    },
    drawCrushBreaks() {
      this.ctx.clearRect(0, 0, this.clientWidth, this.clientHeight);
      this.crushBalls.forEach(item => {
        this.ctx.beginPath();
        this.ctx.arc(item.x, item.y, item.r, 0, 2 * Math.PI);
        this.ctx.fillStyle = item.color;
        this.ctx.fill();
        this.ctx.closePath();
        item.x += item.dx;
        item.y += item.dy;
        if (
          // 碰到左右墙壁
          item.x - item.r < 0 ||
          item.x + item.r > this.clientWidth
        ) {
          item.dx = -item.dx;
        }
        if (
          // 碰到上下墙壁
          item.y - item.r < 0 ||
          item.y + item.r > this.clientHeight
        ) {
          item.dy = -item.dy;
        }
      });
    },
    getRandomColor() {
      return randomColor[Math.floor(Math.random() * randomColor.length)];
    },
    getRandomArbitrary(min, max) {
      return Math.random() * (max - min) + min;
    },
    getCurshBreaks() {
      let _this = this;
      this.breaks.forEach(item => {
        if (item.show) {
          item.show = false;
          for (let i = 0; i < 8; i++) {
            this.crushBalls.push({
              x: item.x + this.breaksConfig.width / 2,
              y: item.y + this.breaksConfig.height / 2,
              dx: _this.getRandomArbitrary(-6, 6),
              dy: _this.getRandomArbitrary(-6, 6),
              r: _this.getRandomArbitrary(1, 4),
              color: _this.getRandomColor()
            });
          }
        }
      });
    },
    drawBall() {
      this.ctx.beginPath();
      this.ctx.arc(this.ball.x, this.ball.y, this.ball.r, 0, 2 * Math.PI);
      this.ctx.fillStyle = "#008b8b";
      this.ctx.fill();
      this.ctx.closePath();
    },
    drawPannel() {
      this.drawRoundRect(
        this.pannel.x,
        this.pannel.y,
        this.pannel.width,
        this.pannel.height,
        5
      );
    },
    drawRoundRect(x, y, width, height, radius) {
      this.ctx.beginPath();
      this.ctx.arc(x + radius, y + radius, radius, Math.PI, (Math.PI * 3) / 2);
      this.ctx.lineTo(width - radius + x, y);
      this.ctx.arc(
        width - radius + x,
        radius + y,
        radius,
        (Math.PI * 3) / 2,
        Math.PI * 2
      );
      this.ctx.lineTo(width + x, height + y - radius);
      this.ctx.arc(
        width - radius + x,
        height - radius + y,
        radius,
        0,
        (Math.PI * 1) / 2
      );
      this.ctx.lineTo(radius + x, height + y);
      this.ctx.arc(
        radius + x,
        height - radius + y,
        radius,
        (Math.PI * 1) / 2,
        Math.PI
      );
      this.ctx.fillStyle = "#008b8b";
      this.ctx.fill();
      this.ctx.closePath();
    },
    drawBreaks() {
      let _this = this;
      _this.breaks.forEach(item => {
        if (item.show) {
          _this.drawRoundRect(
            item.x,
            item.y,
            _this.breaksConfig.width,
            _this.breaksConfig.height,
            _this.breaksConfig.radius
          );
        }
      });
    }
  }
};
</script>
 
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.break-ball {
  width: 900px;
  height: 600px;
  position: relative;
  #breakBall {
    background: #2a4546;
  }
  .container {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    background-color: rgba(0, 0, 0, 0.3);
    text-align: center;
    font-size: 0;
    white-space: nowrap;
    overflow: auto;
  }
  .container:after {
    content: "";
    display: inline-block;
    height: 100%;
    vertical-align: middle;
  }
  .dialog {
    width: 400px;
    height: 300px;
    background: rgba(255, 255, 255, 0.5);
    box-shadow: 3px 3px 6px 3px rgba(0, 0, 0, 0.3);
    display: inline-block;
    vertical-align: middle;
    text-align: left;
    font-size: 28px;
    color: #fff;
    font-weight: 600;
    border-radius: 10px;
    white-space: normal;
    text-align: center;
    .once-again-btn {
      background: #1f9a9a;
      border: none;
      color: #fff;
    }
  }
}
</style>

到此这篇关于VUE+Canvas 实现桌面弹球消砖块小游戏的文章就介绍到这了,更多相关vue弹球消砖块小游戏内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/denglouhen/article/details/115487802

延伸 · 阅读

精彩推荐
  • vue.jsvue实现拖拽进度条

    vue实现拖拽进度条

    这篇文章主要为大家详细介绍了vue实现拖拽进度条,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    前端菜鸡日常6312022-01-24
  • vue.jsVue如何实现变量表达式选择器

    Vue如何实现变量表达式选择器

    这篇文章主要介绍了Vue如何实现变量表达式选择器,帮助大家更好的理解和学习使用vue框架,感兴趣的朋友可以了解下...

    紫圣6642022-01-20
  • vue.jsvue中配置scss全局变量的步骤

    vue中配置scss全局变量的步骤

    这篇文章主要介绍了vue中配置scss全局变量的步骤,帮助大家更好的理解和使用vue框架,感兴趣的朋友可以了解下...

    吃火鸡的馒头4452021-12-21
  • vue.js基于Vue2实现移动端图片上传、压缩、拖拽排序、拖拽删除功能

    基于Vue2实现移动端图片上传、压缩、拖拽排序、拖拽删除功能

    这篇文章主要介绍了基于Vue2实现移动端图片上传、压缩、拖拽排序、拖拽删除功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一...

    前端小白菜~5082021-12-27
  • vue.jsvue 页面跳转的实现方式

    vue 页面跳转的实现方式

    这篇文章主要介绍了vue 页面跳转的实现方式,帮助大家更好的理解和使用vue,感兴趣的朋友可以了解下...

    青小记11712021-12-30
  • vue.js详解vue 表单绑定与组件

    详解vue 表单绑定与组件

    这篇文章主要介绍了vue 表单绑定与组件的相关资料,帮助大家更好的理解和学习使用vue框架,感兴趣的朋友可以了解下...

    Latteitcjz5582022-02-12
  • vue.jsVue自定义v-has指令实现按钮权限判断

    Vue自定义v-has指令实现按钮权限判断

    这篇文章主要给大家介绍了关于Vue自定义v-has指令实现按钮权限判断的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参...

    OrzR34552022-03-02
  • vue.jsvue-cli中实现响应式布局的方法

    vue-cli中实现响应式布局的方法

    这篇文章主要介绍了vue-cli中实现响应式布局的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下...

    我叫胡八一5402022-01-25