这些小技巧,让你的前端编程更优雅

> 这几年,很多工作 1-3 年的前端小伙伴,经常问我一个问题:“怎么样才算一个合格的前端程序员?”
> > 这些小伙伴们,在日常工作中,也都能熟练使用各种框架、插件完成任务! > > 但是,面对涉及个人编程素养、编程思想的提高层面,很有欠缺! > > 坦白说,这也是初级程序员进阶高级程序员的瓶颈期! > > 那么,如何才能有效的突破这种瓶颈呢?且听好程序员来分享一些个人成长经历!

> 言归正传,我以为,重中之重的应该从我们的「编程思想」入手。 > > 天下没有完全相同的两片树叶,编程更是如此,完全相同的一个需求,不同的技术小伙伴都有不同的解决方案,这些方案甚至会出现惊人的差异化。 > > 所以,每个程序员锻炼出来的编程思维,也一定会有巨大的差异,今天我来分享一下我的「编程思想」锻炼之道,希望能够给诸位小伙伴起到抛砖引玉的作用。 > > 今天,分享的主题是:小案例大收获,100行代码构建 Vue 围棋棋盘效果

第一节、案例需求分析

> 1. 使用 Vue 基础语法 v-for="item in 100" 构建一个正方形网格,配合 CSS3 语法 flex 弹性布局构建一个 10*10 小格子棋盘

> 2. 10*10 棋盘线每行会有 11 个拐角点,使用 Vue 在每个拐角点放一个黑色棋子

> 3. 使用 Vue 的自定义指令,让棋子的颜色成为随机变成红黑色,再修改成随机深色

> 4. 使用计时器,使用递归算法,或者使用数组移除的方式来,实现棋子一粒一粒,随机动画放置到页面上的效果,配合分析其时间空间复杂度的变化

> 5. 在棋盘上绑定点击事件,点击棋盘交替落子黑白棋

第二节、初始化构建棋盘并在棋盘上放上棋子

> 1. 使用 CDN 引入 Vue.js 框架,并初始化

<body>
    <div id="app">

    </div>
</body>
</html>
<!-- 导包,导入 Vue 实例 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    // 实例化 Vue 对象
    const app = new Vue({
        // 关联到 HTML 中对应的 template 节点
        el:"#app"
    })
</script>

> 2. 使用 Vue 基础语法 v-for="item in 100" 构建一个正方形网格,配合 CSS3 语法 flex 弹性布局构建一个 10 * 10 小格子棋盘

<style>
    /* 包含 100 个方格的棋盘盒子,使用 flex 弹性布局 warp 换行即可 */
    .panel-box {
        /* 棋盘内方格有边框,所以需要计算棋盘盒子的真实宽度,配合使用 VW 移动端响应式布局 */
        width: calc(40vw + 20px);
        height: calc(40vw + 20px);
        border: 1px solid #333;
        display: flex;
        flex-wrap: wrap;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
    }
    /* 棋盘内部方格,棋盘线是使用 border 边框实现 */
    .line-box {
        width: 4vw;
        height: 4vw;
        border: 1px solid #333;
    }
</style>
<body>
    <div id="app">
        <!-- 棋盘盒子 -->
        <div class="panel-box">
            <!-- 棋盘线,使用 Vue v-for in num 方式做 100 个小方格 -->
            <div class="line-box" v-for="i in 100"></div>
        </div>
    </div>
</body>
</html>

> 3. 10 * 10 小格子棋盘一共有 11 * 11 个可防止棋子的对角线,所以,需要专门额外做一个棋子专用盒子,覆盖在棋盘上

<style>
    /* 专门用来放棋子的盒子,也是相对 body 元素进行定位,完全覆盖在棋盘上 */
    .other-panel-box {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        /* 棋子的盒子宽高,要比棋盘线的宽高多一个元素偏移 */
        width: calc(44vw + 22px);
        height: calc(44vw + 22px);
        display: flex;
        flex-wrap: wrap;
    }
    /* 棋子使用的盒子 */
    .piece-box {
        width: 4vw;
        height: 4vw;
        /* 需要注意棋子使用的盒子边框透明度更改为 0 */
        border: 1px solid rgba(0, 0, 0, .1);
        display: flex;
        align-items: center;
        justify-content: center;
    }
    /* 圆点棋子 */
    .piece {
        width: 2vw;
        height: 2vw;
        border-radius: 50%;
        background-color: #000;
    }
</style>

<body>
    <div id="app">
        <!-- 棋盘盒子 -->
        <div class="panel-box">
            <!-- 棋盘线,使用 Vue v-for in num 方式做 100 个小方格 -->
            <div class="line-box" v-for="i in 100" :key="'lines'+i "></div>
        </div>
        <!-- 需要专门做一个用来放棋子的盒子,完全覆盖在棋盘盒子上 -->
        <div class="other-panel-box">
            <!-- 棋子房子对角线上,10 * 10 个小格子,共有 11 * 11 个可放置棋子的落子点 -->
            <div class="piece-box" v-for="j in 11*11" :key="'pieces'+j">
                <div class="piece"></div>
            </div>
        </div>
    </div>
</body>

第三节、动画随机摆放不同颜色棋子

> 1. 使用 Vue 自定义指令来实现棋子随机红黑颜色

<div class="piece" v-bkcolor></div>
<script>
    // 实例化 Vue 对象
    const app = new Vue({
        // 关联到 HTML 中对应的 template 节点
        el: "#app",
        // 使用自定义指令来实现棋子的颜色随机使用
        directives: {
            // 自定义指令名称
            bkcolor: {
                // 自定义指令调用的时候,直接操作 el dom 元素即可,注意使用 ES6 简写方式
                inserted(el) {
                    // 使用 Math.random 方法获取一个 0-1 随机数,抛硬币方式来实现红黑子落子
                    el.style.backgroundColor =
                      Math.random() > 0.5 ? "red" : "black"
                }
            }
        }
    })
</script>

> 2. 如果,我们希望的颜色是随机颜色该怎么办?

// 使用颜色方式构建多彩颜色
el.style.backgroundColor = "rgba("
	+ ~~(Math.random() * 256) + ","
  + ~~(Math.random() * 256) + ","
  + ~~(Math.random() * 256) + ",1)"

> 3. 知识延展:这种随机颜色效果,在日常开发中的真实使用场景是什么? > > 谷歌的图片搜索,在往下翻页的时候,会使用到这个自定义指令来构建这样的随机色,让用户的体验更好,但是这个随机色有限制,需要控制在一定的区间内,同时,需要配合图片的懒加载来实现这样的目的,这也是我们前端业界的一个自定义指令经典案例了!

第四节、实现自动落子效果并分析多种算法解决方案

> 1. created 生命周期中,初始化一个用来保存棋子的数组 piecesArr,循环遍历到页面上

<style>
    /* 圆点棋子 */
    .piece {
        /* 在棋子内部填充数字 */
        line-height: 2vw;
        text-align: center;
    }
</style>

<!-- 棋子房子对角线上,10 * 10 个小格子,共有 11 * 11 个可放置棋子的落子点 -->
<div class="piece-box" v-for="(item, index) in piecesArr" :key="'pieces'+index">
	<div class="piece" v-bkcolor>{{item}}</div>
</div>

</html>
<script>
    // 实例化 Vue 对象
    const app = new Vue({
        created() {
            // 初始化填充 piecesArr 数据
            for (let i = 0; i < 11 ** 2; i++) {
                // 将数据 push 到数组中
                this.piecesArr.push(i)
            }
        }
    })
</script>

> 2. 配合计数器实现自动在棋盘上随机落子效果,同步配合一个计数器来统计计算的事件复杂度

<script>
    // 实例化 Vue 对象
    const app = new Vue({
        // 关联到 HTML 中对应的 template 节点
        el: "#app",
        data() {
            return {
                // 用来保存棋子的对象数组
                piecesArr: [],
                // 用来统计时间复杂度
                tis:0
            }
        },
        created() {
            this.randomAddPieces()
        },
        methods: {
            // 在棋盘上随机落下一枚棋子
            addPieces() {
                this.tis++
                // 第一种解决方案,使用递归的方式来进行计算使用,但是其计算时间复杂度会急剧增加
                // 因为,每次随机的数据都要在整个棋子数组中进行查找是否已经被使用
                // 首先生产一个随机数
                var r = ~~(Math.random() * this.piecesArr.length)
                if(this.piecesArr[r]){
                    // 如果,当前棋子的状态已经为真了,那么递归调用自己
                    // 再生产一个随机数,直到发现了一个未落子的位置为止
                    this.addPieces()
                }else{
                    this.piecesArr[r] = true
                    // 数组是引用类型,所以,需要解构赋值一次,触发 Vue update 更新
                    this.piecesArr = [ ...this.piecesArr ]
                }
            },
            // 使用计时器实现动画随机下棋落子效果,将整个棋盘布满
            randomAddPieces() {
                let timer = setInterval(() => {
                    // if (this.piecesArr.indexOf(false) > -1) {
                    if (this.piecesArr.includes(false)) {
                        this.addPieces()
                    } else {
                        console.log("时间复杂度统计为:", this.tis)
                        clearInterval(timer)
                    }
                }, 10);
            }

        },
    })
</script>

> 3. 使用一个映射数组来记录落子情况,动态获取记录中的值,并移除当前记录,提高程序效能,同时,计数器中的判断也基于映射数组记录长度来控制

<script>
    // 实例化 Vue 对象
    const app = new Vue({
        // 关联到 HTML 中对应的 template 节点
        el: "#app",
        data() {
            return {
                // 用来保存棋子的对象数组
                piecesArr: [],
                // 用来和棋子对象数组进行索引映射,已经落子的索引动态移除
                piecesNum: [],
                // 用来统计时间复杂度
                tis:0
            }
        },
        created() {
            // 初始化填充 piecesArr、piecesNum 数据
            for (let i = 0; i < 11 ** 2; i++) {
                // 将数据 push 到数组中,记录当前棋子是否落子,初始化状态是所有都未落子
                this.piecesArr.push(false)
                // 映射保存棋子对象数组索引,用来记录未落子的索引
                this.piecesNum.push(i)
            }
            this.randomAddPieces()
        },
        methods: {
            // 在棋盘上随机落下一枚棋子
            addPieces() {
                this.tis++
                // 第二种方案,每次修改自动移除事先预设的用来保存棋子显示状态的索引
                // 随机找到 映射索引数组长度的 一个随机索引
                var r = ~~(Math.random() * this.piecesNum.length)
                // 将这个索引所对应的棋子落子
                this.piecesArr[this.piecesNum[r]] = true
                // 解构赋值一次,触发页面更新
                this.piecesArr = [...this.piecesArr]
                // 在映射索引数组中移除 已经使用的 随机索引的数字
                this.piecesNum.splice(r, 1)
            },
            // 使用计时器实现动画随机下棋落子效果,将整个棋盘布满
            randomAddPieces() {
                let timer = setInterval(() => {
                  	// 更改为 length 属性,不用遍历数组提高程序效能
                    if (this.piecesNum.length > 0) {
                        this.addPieces()
                    } else {
                        console.log("时间复杂度统计为:", this.tis)
                        clearInterval(timer)
                    }
                }, 10);
            }

        },
    })
</script>

第五节、技术场景拓展介绍及知识小结

> 1. 模拟实现按钮下棋效果,红黑棋子交替下棋,这里需要注意的是

<style>
    .title{
        text-align: center;
        color: #666;
    }
</style>
<body>
    <!--  标题提示落子信息语言 -->
    <h2 class="title">点击棋盘,交替落黑子、红子到随机棋盘位置上</h2>
</body>
<script>
    // 实例化 Vue 对象
    const app = new Vue({
        // 关联到 HTML 中对应的 template 节点
        el: "#app",
        data() {
            return {
                // 用来记录当前落子棋子的交替效果,初始值为 0 代表黑色, 1 代表红色
                pieceStatus: 0
            }
        },
        created() {
            // this.randomAddPieces()
        },
        // 使用自定义指令来实现棋子的颜色随机使用
        directives: {
            // 自定义指令名称
            bkcolor: {
                // 自定义指令调用的时候,直接操作 el dom 元素即可,注意使用 ES6 简写方式
                inserted(el,binding) {
                    // 替代随机,实现红黑棋子交替落子效果    
                    el.style.backgroundColor = 
                      binding.value === 0 ? "black" : "red"
                }
            }
        },
        methods: {
            // 在棋盘上随机落下一枚棋子
            addPieces() {
                this.pieceStatus = this.pieceStatus === 0 ? 1 : 0
            }
        },
    })
</script>

> 2. 知识进阶思考: > > - 持续完成围棋算法,实现一个完整的围棋 demo; > - 基于技术模型扔骰子,配套一个「算命」的匹配库,实现一个「算命大忽悠」小应用!

> 3. 知识总结 > > - 使用 Vue 的一些舒服的命令,可以让我们快速构建大量重复的模块 > - 棋盘的拐角点和棋子的落子位,需要做一个棋盘覆盖。


帮助到你的话就点个关注吧~ 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值