4.7蓝桥杯做题-心愿便利贴-消失的 Token-封装 Promisefy 函数-趣购-乾坤大挪移心法
4.7蓝桥杯做题
文章目录
- 4.7蓝桥杯做题
- 1.心愿便利贴
- 2.消失的 Token
- 3.封装 Promisefy 函数
- 4.趣购
- 5.乾坤大挪移心法
- 总结:
1.心愿便利贴
在初始化的时候输入框并没有做验证,输入内容发布后,许愿贴并不能出现。
目标
请在 index.html
文件中补全代码,具体需求如下:
- 将填写完的表单正确渲染到许愿墙上。
- 完成表单验证,姓名(必填项) 2-4 个字符,许愿内容(必填项)长度在 1 到 30 个字符。
本项目使用到的 element-ui
表单验证 API 如下:
表单属性
参数 | 说明 | 类型 |
---|---|---|
rules | 表单验证规则 | object |
表单项属性
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
prop | 表单域 model 字段,在使用 validate、resetFields 方法的情况下,该属性是必填的 | string | 传入 Form 组件的 model 中的字段 | - |
required | 是否必填 | boolean | - | false |
trigger | 验证时触发的事件 | string | click/focus/change/blur/input | - |
min | 最小长度 | number | - | - |
max | 最大长度 | number | - | - |
message | 验证不通过时的错误信息 | string | - | - |
使用示例
<el-form-item label="姓名" prop="activeName"><el-input v-model="form.activeName" placeholder="请输入姓名"></el-input></el-form-item>
// ....rules: {activeName: [{ required: true, message: '请输入活动名称', trigger: 'blur' },{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }],}
完成后效果如下:
<!-- TODO 待修改的代码 -->
<div class="card" :class="item.css" v-for="(item,index) in wishList" :key="index">
copyrules: {// TODO 待补充验证的代码name: [{ required: true, message: '请输入姓名', trigger: 'blur' },{ min: 2, max: 4, message: '长度在 2 到 4 个字符', trigger: 'blur' }],content: [{ required: true, message: '请输入许愿内容', trigger: 'blur' },{ min: 1, max: 30, message: '长度在 1 到 30 个字符', trigger: 'blur' }]
}
这道题主要是要看懂题目给的例子,看懂就能进行模仿做出题目。看懂题目案例,就能使用题目给的数据进行验证,分两种情况,一种是框里什么都没有写,就验证不能请输入,另一种情况就是输入的长度不对,进行两次验证。
2.消失的 Token
在浏览器中预览 index.html
页面效果如下:
此时输入用户名后回车/点击确定,数据发生改变,但还是停留在登录页,无法正确显示登录成功界面。
目标
找到 index.html
中的 TODO
部分,仔细阅读 store
文件夹下的相关代码并结合 Vuex
相关知识,排查代码中存在的问题,修改后使得登录界面输入 admin 时,点击确认按钮/回车可以正确显示如下界面:
这道题通过查看Vuex仓库 store 文件夹下的 index.js 可知有两个Vuex模块,模块名 base 所对应的是 BaseModule ,模块名 user 所对应的是 UserModule ,再通过查看 UserModule.js 与 UserModule.js 可知,只有 user 模块通过 namespaced: true 开启了命名空间功能。因此,在调用 user 模块中的 getters 与 mutations 时,需要使用以下特定语法:
'模块名/模块中的getters或mutations'
修改前
var app = new Vue({el: '#app',data() { },computed: {welcome() {return store.getters.welcome},username() {return store.getters.username},token() {return store.getters.token}},methods: {// 回车/点击确认的回调事件login(username) {username && store.commit('login', { username, token: 'sxgWKnLADfS8hUxbiMWyb' })username && store.commit('say', '登录成功,欢迎你回来!')}}})
所以,修改后的代码如下:
// TODO 修改下面错误代码var app = new Vue({el: '#app',data() { },computed: {welcome() {return store.getters.welcome},username() {return store.getters['user/username']},token() {return store.getters['user/token']}},methods: {// 回车/点击确认的回调事件login(username) {username && store.commit('user/login', { username, token: 'sxgWKnLADfS8hUxbiMWyb' })username && store.commit('say', '登录成功,欢迎你回来!')}}
})
3.封装 Promisefy 函数
目标
请在 index.js
文件中的补全代码,完成 promisefy
函数的封装。将 fs
中的 readFile
方法 promise
化。也就是说 readFileSync
方法执行后,会返回一个 promise
,可以调用 then
方法执行成功的回调或失败的回调。
在实际应用中,一个函数满足这几个条件,就可以被 promisify
化:
- 该方法必须包含回调函数
- 回调函数必须执行
- 回到函数第一个参数代表 err 信息,第二个参数代表成功返回的结果
在控制台运行:
node index
此时应打印出 true
,即:回调形式的 fs.readFile
方法读取同个文件的结果与 Promise
形式读取结果一致。
**思路:**在promise函数中设置两个函数,分别为处理正确和错误的两个函数,promisify 是个函数,参数里面传个函数,promisify 的返回值也是个函数,调用这个函数,这个函数的返回是 promise 对象。在promise函数中,设置变量判断处于那个状态,设置值接收,两个函数在内部判断并将值赋值给外层接收。
const promisefy = (fn) => {// TODO 此处完成该函数的封装//读取文件return (textPath,utf8)=>{//返回一个新的Promise对象,有正确值和错误值输出return new Promise((resolve,reject)=>{//读取文件,返回错误信息或者读取到的值fs.readFile(textPath,utf8,(err,data)=>{if(err){return reject(err)}return resolve(data)})}) }
}
4.趣购
目标
<div class="good-list"><div v-for="good in goods" :key="good.name" class="good" draggable="true" @dragstart="dragstart($event,good)"><img :src="good.cover" /><span>{{ good.name }}</span><span>¥{{ good.price }}</span></div>
</div>
上面先为每个商品绑定draggable="true"
使其变成可拖放元素,再为其绑定dragstart
事件,其对应的dragstart
事件处理程序如下:
dragstart(ev,good){// 向dataTransfer属性中添加拖拽数据ev.dataTransfer.setData("name", good.name);ev.dataTransfer.setData("price", good.price);
}
根据题目信息,我们很容易知道可以在dataTransfer
属性中保存事件的数据。
draggable:这个属性是枚举类型 (en-US),而不是布尔类型。这意味着必须显式指定值为 true 或者 false,像 这样的简写是不允许的。正确的用法是 。
dragstart事件:当用户开始拖拽一个元素或选中的文本时触发
之后需要为购物车图标绑定放置事件drop
:
<div id="trolley" class="trolley" @dragover.prevent @drop="drop" ><span id="bought" class="bought" v-if="bought.length !== 0">{{bought.length}}</span><img src="./images/trolley.jpeg" />
</div>
根据题目信息可以得知,可以通过drop事件来获取可拖放元素的数据,而要想触发drop事件需要先清除dragover事件的默认行为,在Vue中可以通过.prevent修饰符来清除事件的默认行为,所以在购物车图标上还需要绑定一个@dragover.prevent。drop事件对应的事件处理程序如下:
drop(ev){// 先获取dataTransfer上保存的可拖放元素的数据const name = ev.dataTransfer.getData("name");const price = ev.dataTransfer.getData("price");// 向bought数组中添加该商品的信息(向购物车中添加商品)this.bought.push({name,price:Number(price)}) // 这里将price转换成number类型,方便之后的计算
},
观察题目代码推断出data
中的bought
是用来存放购物车的数据的
通过上面的步骤后题目的要求我们已经实现了一半了,下面需要解决的问题就是将购物车(bought
)内的数据渲染到页面上,观察发现页面中使用到了两个计算属性来显示购物车(bought
)数据:
<div class="result"><div>购物车商品:<span id="goods">{{ goodsDetail }}</span></div><div>购物车商品总计:<span id="total">{{ totalPrice }}</span></div>
</div>
所以接下来只需要补全goodsDetail
和totalPrice
这两个计算属性就ok了:
totalPrice() {// 通过数组的reduce求和函数来获取购物车商品总计return this.bought.reduce((a, b) => {return a + b.price}, 0);
},
goodsDetail() {/*** 这里用了两次reduce* 第一次是为了将bought中相同的商品合并为同一个对象,并为其添加一个amount字段表示其数量* 第二次是为了将数据转换成符合题目要求的字符串格式*/return this.bought.reduce((a, b) => {const good = a.find(item => item.name === b.name) // 先查询a中与b相同的商品if (good) {// 如果a中有与b相同的商品,则将其amount加1即可good.amount++} else {// 如果a中没有与b相同的商品,则向其push b商品的信息并初始化一个amount字段a.push({ name: b.name, price: Number(b.price), amount: 1 })}return a}, []).reduce((a, b) => {return a + b.name + '*' + b.amount + ' '}, '');
},
reduce 为数组中的每一个元素依次执行回调函数,reduce可以操作数组里的数据,这道题使用reduce将数据合并新数据进数组里,或者对数组里的数据进行更改,reduce跟常用的map,forEach一样,也是用于遍历循环,只不过它可以设置初始值,这样可以大大增强代码的可读性。
还可以使用类一种方法使用forEach来遍历判断后添加数据或者更改数据。
<!-- TODO: 补充拖拽事件,请不要改动任何 id 属性 -->
<template><div class="container"><div class="good-list"><divv-for="good in goods":key="good.name"class="good"draggable="true"@dragstart="dragstart($event, good)">< img :src="good.cover" /><span>{{ good.name }}</span><span>¥{{ good.price }}</span></div></div><div id="trolley" class="trolley" @dragover.prevent @drop="drop($event)"><span id="bought" class="bought" v-if="bought.length !== 0">{{bought.length}}</span>< img src="./images/trolley.jpeg" /></div><div class="result"><div>购物车商品:<span id="goods">{{ goodsDetail }}</span></div><div>购物车商品总计:<span id="total">{{ totalPrice }}</span></div></div></div>
</template>
module.exports = {data() {return {goods: [{name: "畅销书",price: 30,cover: "./images/book.jpeg",},{name: "收纳箱",price: 60,cover: "./images/box.jpeg",},{name: "纸巾",price: 20,cover: "./images/paper.jpeg",},{name: "电视",price: 1000,cover: "./images/tv.jpg",},],//购物车所有商品的数量bought: [],//购物车列表shoplist:[]};},// TODO: 请补充实现代码computed: {//购物车总价totalPrice() {sumPrice = 0;this.shoplist.forEach((item) => {sumPrice += item.price * item.num;});return sumPrice;},//购物车显示列表goodsDetail() {s = "";this.shoplist.forEach((item) => {s += item.name + "*" + item.num + " ";});return s;},},methods: {//开始拖拽事件dragstart(event, good) {//存储商品event.dataTransfer.setData("name", good.name);event.dataTransfer.setData("price", good.price);//动态给每个商品添加数量属性this.$set(good, "num", 1);//进行存储event.dataTransfer.setData("num", good.num);},drop(event) {//获取商品const name = event.dataTransfer.getData("name");//计算商品数量this.bought.push(name)const price = event.dataTransfer.getData("price");const num = event.dataTransfer.getData("num");//判断购物车中是否有数据if (this.shoplist.length !== 0) {//查找商品与当前加入商品相同的index = this.shoplist.findIndex((item) => {return item.name == name;});//如果不相同直接存储到商品列表中if (index == -1) {this.shoplist.push({ name, price, num });} else {//如果相同就直接加该商品的数量即可this.shoplist[index].num++;}} else {this.shoplist.push({ name, price, num });}},},
};
5.乾坤大挪移心法
目标
到 main.js
文件中的“乾坤大挪移心法” mentalMethod
函数,完成函数中的 TODO 部分。
mentalMethod
需要返回一个函数,可以一直进行调用,但是最后一次调用不传参。- 函数通过以下方式执行,返回结果均为
'战胜峨眉,武当,少林'
。
mentalMethod('峨眉')('武当')('少林')();
mentalMethod('峨眉','武当')('少林')();
mentalMethod('峨眉','武当','少林')();
注意逗号为英文逗号。
完成后,在命令行输入 node main.js
效果如下:
思路:这道题ES6的拓展运算符以及函数的封装及作用域的问题。这是一道循环调用函数的题,要实现可以一直调用并传参,但是最后一次调用不传参,也就是当函数没有参数传入时就退出循环函数的调用,并将传入的参数进行整理后并输出。
方法一:这是一个钻空子的写法,应为本题中传入的参数都是相同的,所以用了一个钻空子的写法让他的输出参数都是固定的,这个方式在传参不同时,就是不可取的。通过这个方式,明白函数是如何实现循环调用的以及拓展运算符的相关知识点。
console.log(this.mentalMethod(1,2)())//战胜峨眉,武当,少林// 此时的的...args是作为一个剩余参数使用的,剩余参数是聚合用的,将函数传入的参数进行组合为一个数组。function mentalMethod(...args) {console.log((args))//[1,2],将传入的参数组合为一个数组进行输出。if (args.length) {//当传入的参数为空时,就会跳出这个if循环,此时就会进入输出'战胜峨眉,武当,少林'。//所以不论传入的参数时是什么,有几个最终输出的都是最终return的结果。console.log((111))return this.mentalMethod;}return '战胜峨眉,武当,少林'},
方式二:这个方式解决传入的参数不同的情况下,进行输出的。
<template></template><script>export default{data(){return{arr:[]}},mounted() {console.log(this.mentalMethod('峨眉')('武当')('少林')());console.log(this.mentalMethod('峨眉', '武当')('少林')());console.log(this.mentalMethod('峨眉', '武当', '少林')());},methods:{mentalMethod(...args) {//由于在首先执行mentalMethod()函数时,就会将第一个参数传入,所以数组的初始值就应该为第一个传入的参数。let arr = argsconsole.log(args)//输出["峨眉"]//此时就想到了在函数中在套入函数,在该函数中进行循环push,此时arr就不会置为空。console.log(...args)//输出峨眉let fn = function(...rest){//此时再调用该函数时,传入的参数是从第二个开始的console.log(rest)//输出["武当"]console.log(...rest)//输出武当if(rest.length>0){arr.push(...rest)console.log(arr)//输出["峨眉", "武当"]return fn}else{//此时表示传入的参数为空,也就是不能再继续循环调用,应退出循环了。arr[0] = '战胜'+ arr[0]console.log(arr)//输出["战胜峨眉", "武当", "少林"]let a = ''//就需要对输出的数组内容进行整理arr.forEach((item,index) =>{if(index+1 !=arr.length){//遍历是从0开始算起的,而长度是从1算起的,所以要将索引值加1//判断不是最后一个就加上值和,a += item+','}else{//是最后一个则直接加a+=item}})return a}}return fn;},}}
</script><style>
</style>
相关知识点:
1… args是什么意思?
…被称为扩展运算符。
通常,…args表示"任意数量的值"。 例如,您可以传递null或1,2,3,4-没关系,并且该方法足够聪明来处理它。
这是ES6中引入的新语法。 请在此处查看文档developer.mozilla.org/en/docs/Web/JavaScript/Reference/
关于o (…args) =>,…args是rest参数。它始终必须是参数列表中的最后一个条目,并且将被分配一个数组,该数组包含所有尚未分配给先前参数的参数。
2.ES6学习–函数剩余参数 (rest参数)
ES6 引入 rest 参数(形式为“…变量名”),用于获取函数的多余参数,这样就不需要使用arguments
对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。(可以拿到除开始参数外的参数)
这个rest 参数和arguments不一样,它是程序员自定义的一个普通标识符,只是需要在前面加上三个点:…
function func(a, ...rest) {console.log(a)console.log(rest)
}
func(1) // 1 []
func(1, 2, 3, 4) //1 [2,3,4]
又比如,在前面定义2个参数
function func(a, b, ...rest) {console.log(a, b)console.log(rest)
}
func(1, 2) // 1 2 []
func(1, 2, 3, 4) 1 2 [3,4]
注意:剩余参数后面不能跟其他参数,否则会报错
function func(a, ...rest, b) {
}//报错
当使用剩余参数后,函数的length属性会发生一些变化
function func(a, b, ...rest) {
}
func.length // 2
即length不包含rest,为2。
剩余参数前面可以不跟其他参数,即一个参数也没有。如
function func(...rest) {console.log(rest)
}
func(1) // [1]
func(1, 2, 3, 4) // [1,2,3,4]
总结:
今天做了心愿便利贴、消失的 Token、封装 Promisefy 函数,趣购。心愿便利贴是根据题目给的案例,按照题目给的案例方法进行验证数据输入是否符合要求。消失的 Token考查了使用vuex的特殊命名空间后使用仓库是路径如何写,这道题通过查看Vuex仓库 store 文件夹下的 index.js 可知有两个Vuex模块,模块名 base 所对应的是 BaseModule ,模块名 user 所对应的是 UserModule ,再通过查看 UserModule.js 与 UserModule.js 可知,只有 user 模块通过 namespaced: true 开启了命名空间功能。封装 Promisefy 函数考查了Promise的异步封装函数写法和读取文件的回调形式的 fs.readFile
结合一起使用读取文件,主要是使用回调的方式写这道题。在promise函数中设置两个函数,分别为处理正确和错误的两个函数,promisify 是个函数,参数里面传个函数,promisify 的返回值也是个函数,调用这个函数,这个函数的返回是 promise 对象。在promise函数中,设置变量判断处于那个状态,设置值接收,两个函数在内部判断并将值赋值给外层接收。在做趣购时根据题目给的一些属性进行操作,使得商品可以移动到购物车,商品移动时也能将商品的信息带给购物车,购物车进行计算出购买商品的数量和总价。上面先为每个商品绑定draggable="true"
使其变成可拖放元素,再为其绑定dragstart
事件,将需要传递的参数绑定到dragsstart一起携带过去。购物车则先解除默认的事件@dragover.prevent,绑定新的数据@drop=“drop”,接收传递过来的数据。然后补全goodsDetail
和totalPrice
这两个计算属性,使用reduce()对数组进行添加,计算,合并等操作。或者使用forEach()的方法对数组进行遍历查找,添加的操作。 乾坤大挪移心法,这道题看了好久才明白需要进行什么操作。这道题的考点就在于函数的循环调用的使用以及对传入的数据使用拓展运算符进行展开或是聚合。在使用第一种方式进行解决时,只是对该函数进行循环调用,对于其中传入的参数并没有做什么操作,但是还是能够通过,原因就是题目传入的参数都是相同的,让它的return都是相同的,但这种方式是不可取的,当参数发生变化时,就会出现错误。第二种方式就是对其中的参数进行了拓展或是聚合的操作,初步想法是先放置一个空数组,当传入的参数不是空的时候,就将其中的参数进行push进数组。此时就会发现一个问题,由于当传入的参数不是空的情况下,就会继续循环调用该函数,也就是再次进入mentalMethod()函数,此时arr又会再一次置为空,所以此方法无效。所以就需要在在函数中在套入函数,在该函数中进行循环push,此时arr就不会置为空。在这个循环调用的函数的封装时,就需要多次输出其中传入的参数的值,并实时对代码进行输出查看。
4.7蓝桥杯做题-心愿便利贴-消失的 Token-封装 Promisefy 函数-趣购-乾坤大挪移心法相关推荐
- 第五届蓝桥杯真题解析【JavaC组】
第五届蓝桥杯真题解析[JavaC组] 业精于勤,荒于嬉:行成于思,毁于随.--韩愈 文章目录 ***第五届蓝桥杯真题解析[JavaC组]*** 前言 A:猜年龄 B:等额本金 C:猜字母 D:大衍数列 ...
- 【蓝桥杯真题】16天冲刺 Python
距离比赛很快了,希望和我一起准备的PY党能更加熟练的掌握Python! 1.距离和(模拟赛填空题) 问题描述: 两个字母之间的距离定义为它们在字母表中位置的距离.例如 A和 C 的距离为 2,L 和 ...
- 蓝桥杯 提高题 母牛的故事
蓝桥杯 提高题 母牛的故事 题目描述 有一头母牛,它每年年初生一头小母牛.每头小母牛从第四个年头开始,每年年初也生一头小母牛.请编程实现在第n年的时候,共有多少头母牛? 输入 输入数据由多个测试实例组 ...
- # 2014年蓝桥杯真题CC++B组
2014年蓝桥杯真题C/C++B组 1.啤酒和饮料 题目描述 啤酒每罐2.3元,饮料每罐1.9元,小明买了若干啤酒和饮料,一共花了82.3元. 我们还知道她买的啤酒比饮料的数量多,请你计算他买了几罐啤 ...
- 蓝桥杯python省赛冲刺篇2——常用算法的详细解析及对应蓝桥杯真题:打表模拟法、递推递归法、枚举法、贪心算法、差分与前缀和
注意:加了题目链接 目录 注意:加了题目链接 一.打表模拟法 介绍 1. 算式问题 题目描述 解析与代码演示 2. 求值 题目描述 解析与代码演示 3. 既约分数 题目描述 解析与代码演示 4. 天干 ...
- 第十届蓝桥杯c语言试题,第十届蓝桥杯真题编程题1-7解析(高级组).pdf
scratch 少儿编程第十届蓝桥杯真题 7 大家好 ~今天我们来讲解 scratch 蓝桥杯第十届编程大题的第七道题. 同样,这道题也是非常有难度的一道题.一起来看一下吧 解析: 女孩的程序 1.在 ...
- 第九届蓝桥杯真题解析JavaC组
第九届蓝桥杯真题解析JavaC组 文章目录 ***第九届蓝桥杯真题解析JavaC组*** 前言 A.哪天回家 B.猴子分香蕉 C.字母阵列 D.第几个幸运数 E.书号验证 F.打印大X G.缩位求和 ...
- 蓝桥杯真题2017-2021
刷完近几年真题,感觉理解完之后,拿奖问题不大,本人这次获得2022年蓝桥杯javaB组省一,以下是历年javaB组省赛题目. 文章目录 2017年真题 一.购物单 二.纸牌三角形 三.承压计算 四.魔 ...
- scratch编程 蓝桥杯编程题 红绿灯
小恐龙以前做过一道蓝桥杯编程题,实在是想不起在哪里看到的了,真是该打.大意是模拟道路上的红绿灯效果,红灯停绿灯行: 如果哪位小可爱知道此题出处的话,不妨告知小恐龙一声. 我们来康康怎么编程的吧.首先导 ...
最新文章
- img标签 文件不存在_HTML常用标签
- 99_leetcode_Best Time to Buy and sell Stock
- python统计特定类型文件数量_分享一些常见的Python编程面试题及答案
- 嵌入式http服务器boa 简介
- springMVC项目在jboss7中配置应用自己的log4j--转载
- java launcher_JAR清单类路径不仅适用于Java Application Launcher
- 【定时同步系列4】QPSK调制+OM定时(FFT实现及频域补偿)+信号分段处理+误码率曲线之MATLAB仿真(复信号模型)
- mysql主从结构主数据库_mysql主从结构主数据库中的日志
- 第10篇:Flowable-BPMN操作流程部署、启动
- 关于SEL的简单总结
- MAT分析android内存泄漏
- Android开发者网址导航
- 送你一份万字机器学习资料
- 【干货】js 数组操作合集(前端自我修养)
- JavaScript混淆器
- 用ArcGIS对图像进行地理配准
- 2021,要这样学大数据开发
- CAJ阅读器相关问题
- 【百科】有关地震的一些知识
- Libuv源码分析 —— 9. DNS
热门文章
- android 7.1 RIL 获取SIM卡号
- java精简学习笔记(黑马毕老师授)
- 微信8.0状态视频无水印素材+个人设置技巧(最全小白教程)
- 三款野生动物识别软件不容错过
- kali社会工程工具包基本使用
- openGL之API学习(一四八)3D全息眼镜HoloLens
- SpringBoot+logback实现日志打印
- 2021年青海省副高考试成绩查询,【青海软考高级职称成绩查询_2021年软考高级职称成绩查询】- 环球网校...
- neo4j Desktop桌面版的下载与使用(windows版本)【下】
- 有道云笔记Windows客户端打开白屏的问题,一个字,等