写点什么

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

  • 2022-11-17
    北京
  • 本文字数:6304 字

    阅读完需:约 21 分钟

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


这几年,很多工作 1-3 年的前端小伙伴,经常问我一个问题:“怎么样才算一个合格的前端程序员?”

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


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

第一节、案例需求分析

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


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


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


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



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


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

  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>
复制代码


  1. 使用 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>
复制代码


  1. 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>
复制代码


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


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


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



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

  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>
复制代码


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


<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>
复制代码


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


<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>
复制代码


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


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




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


用户头像

还未添加个人签名 2022-10-21 加入

还未添加个人简介

评论

发布
暂无评论
这些小技巧,让你的前端编程更优雅_前端_好程序员IT教育_InfoQ写作社区