js实现递归算法
!DOCTYPE
html
head
meta content="" charset="utf-8"
title函数的递归调用/title
/head
body
script
//递归的概念:自己调用自己
//注意:使用递归的时候必须有一个结束标志,否则会报内存溢出的错误 Maximum call stack size exceeded;
/* 1.案例一:求1,2,3...n 的和 */
function fn(n){
if(n===1){
return 1;
}
return n+fn(n-1);
}
//console.log(fn(3));
/* 2.案例二:求1,2,3...到n的阶乘 */
function getFactorial(n){
if(n===1){
return 1;
}
return n * getFactorial(n-1);
}
//console.log(getFactorial(3));
/* 案例三:斐波那契数列 *///第n个数等于前两个数的和,除第一个数跟第二个树外:如1,1,2,3,5,8,11,19,30...
function getNFibonacciSequence(n){
if(n===1 || n===2){
return 1;
}
return getNFibonacciSequence(n-1)+getNFibonacciSequence(n-2);
}
console.log(getNFibonacciSequence(4));
/script
/body
/html
JS DOM(五) 购物车案例
style
table {
border-collapse: collapse;
}
td,
th {
border: 1px solid #ccc;
text-align: center;
}
input {
text-align: center;
width: 20px;
outline: none;
}
img {
width: 100px;
}
/style
/head
body
table
thead
tr
thinput type="checkbox" id="ckAll"全选/th
th商品名称/th
th商品图片/th
th商品价格/th
th购买数量/th
th小计/th
th操作/th
/tr
/thead
tbody
/tbody
tfoot
tr
td colspan="7" style="text-align: right;"
span总计:/span
span id="total"/span
/td
/tr
/tfoot
/table
script
let goodses = [{
name: '苹果手机',
img: "",
price: 300,
count: 2,
isck: false
}, {
name: '华为手机',
img: "",
price: 200,
count: 3,
isck: true
}, {
name: '小米手机',
img: "",
price: 100,
count: 8,
isck: false
}, {
name: '中兴手机',
img: "",
price: 500,
count: 4,
isck: false
}];
// 加载商品信息方法
function loadGoodses() {
goodses.forEach(g = {
let tr = document.createElement('tr')
// 每个tr里面有7个td
let td1 = document.createElement('td')
let ck = document.createElement('input') //获取里面的输入框
ck.type = 'checkbox' //获取输入框的按钮选项
ck.className = 'ck' //这里只是添加一个标记
// 设置复选框的选中状态
ck.checked = g.isck
// 设置复选框状态发生改变后的事件
ck.onchange = function() {
// 更新商品的状态
g.isck = ck.checked
// 再次调用计算总计的方法
totalPrice()
// 判断是否需要更新全选复选的状态
document.querySelector('#ckAll').checked = goodses.every(r = r.isck)
}
td1.appendChild(ck) //将获取到的输入框添加到td里面
let td2 = document.createElement('td')
td2.innerHTML = g.name //里面的文本等于数组中商品的name
let td3 = document.createElement('td')
let img = document.createElement('img')
img.src = g.img
td3.appendChild(img)
// td4显示单价
let td4 = document.createElement('td')
td4.innerHTML = '¥' + g.price.toFixed(2)
// td5显示数量
let td5 = document.createElement('td')
let btn1 = document.createElement('button')
btn1.innerHTML = '-'
// 添加减按钮 注册点击事件
btn1.onclick = function() {
g.count--
// 判断商品不能小于1
if (g.count 1) {
g.count = 1
}
// 更新商品数量
count.value = g.count
// 更新小计
td6.innerHTML = '¥' + (g.price * g.count).toFixed(2)
// 更新总计数量,调用函数
totalPrice()
}
td5.appendChild(btn1)
let count = document.createElement('input')
count.value = g.count
td5.appendChild(count)
let btn2 = document.createElement('button')
btn2.innerHTML = '+'
btn2.onclick = function() {
g.count++
// 更新商品数量
count.value = g.count
// 更新小计
td6.innerHTML = '¥' + (g.price * g.count).toFixed(2)
// 更新总计数量,调用函数
totalPrice()
}
td5.appendChild(btn2)
//单个商品的小计
let td6 = document.createElement('td')
td6.innerHTML = '¥' + (g.price * g.count).toFixed(2)
let td7 = document.createElement('td')
let del = document.createElement('button')
del.innerHTML = '删除'
// 添加删除事件
del.onclick = function() {
// 删除tr标签
tr.remove()
// 根据商品的名称获取在数组中的位置
let index = goodses.findIndex(r = r.name === g.name)
// 根据位置删除对应的商品
goodses.splice(index, 1)
// 更新总价 调用函数
totalPrice()
}
td7.appendChild(del)
// 将所有的td添加到tr中
tr.appendChild(td1)
tr.appendChild(td2)
tr.appendChild(td3)
tr.appendChild(td4)
tr.appendChild(td5)
tr.appendChild(td6)
tr.appendChild(td7)
// 将tr 添加到tbody中
document.querySelector('tbody').appendChild(tr)
})
}
loadGoodses() //调用方法
// 封装计算总金额的方法
function totalPrice() {
// 计算总计
let money = goodses.filter(r = r.isck).reduce((a, b) = a + b.count * b.price, 0)
// 显示总计
document.querySelector('#total').innerHTML = '¥' + money.toFixed(2)
}
totalPrice()
// 全选方法
document.querySelector('#ckAll').onchange = function() {
let cks = document.querySelectorAll('.ck')
// 更新DOM
cks.forEach(ck = {
ck.checked = this.checked
})
// 更新数据
goodses.forEach(g = {
g.isck = this.checked
})
// 再次调用计算总计的方法
totalPrice()
}
/script
全网最详bpmn.js教材-事件篇
bpmn.js 是一个BPMN2.0渲染工具包和web建模器, 使得画流程图的功能在前端来完成.
因为公司业务的需要因而要在项目中使用到 bpmn.js ,但是由于 bpmn.js 的开发者是国外友人, 因此国内对这方面的教材很少, 也没有详细的文档. 所以很多使用方式很多坑都得自己去找.在将其琢磨完之后, 决定写一系列关于它的教材来帮助更多 bpmn.js 的使用者或者是期于找到一种好的绘制流程图的开发者. 同时也是自己对其的一种巩固.
由于是系列的文章, 所以更新的可能会比较频繁, 您要是无意间刷到了且不是您所需要的还请谅解 😊.
不求赞👍不求心❤️. 只希望能对你有一点小小的帮助.
所有教材的github地址: 《bpmn-chinese-document》
上一章节我们介绍了利用 bpmn.js 与后台进行交互, 要是对 bpmn.js 不了解的小伙请移步:
《全网最详bpmn.js教材-http请求篇》
这一章节要讲解是关于 bpmn.js 的一些事件, 通过学习此章节你可以学习到:
很多时候你期望的是在用户在进行不同操作的时候能够监听到他操作的是什么, 从而做想要做的事情.
是进行了 shape 的新增还是进行了线的新增.
比如如下的一些监听事件:
继续在项目案例 bpmn-vue-basic 的基础上创建一个 event.vue 文件:
并在 success() 函数中添加上监听事件的函数:
如图所示, 在这里你就可以获取到相关节点的所有信息了:
案例Git地址: LinDaiDai-bpmn.js案例event.vue
上面介绍的是监听 modeler 并绑定事件, 可能你也需要监听用户点击图形上的 element 或者监听某个 element 改变:
继续在 success() 上添加监听事件:
配置好 addEventBusListener() 函数后, 在进行元素的点击、新增、移动、删除的时候都能监听到了.
但是有一点很不好, 你在点击“画布”的时候, 也就是 根元素 也可能会触发此事件, 我们一般都不希望此时会触发, 因此我们可以在 on 回调中添加一些判断, 来避免掉不需要的情况:
此时我们可以把监听到返回的节点信息打印出来看看:
如上图, 它会打印出该节点的 Shape 信息和 DOM 信息等, 但我们可能只关注于 Shape 信息(也就是该节点的 id、type 等等信息), 此时我们可以使用 elementRegistry 来获取 Shape 信息:
或者你也可以直接就用 e.element 获取到 Shape 的信息, 我比较了一下它们两是一样的. 但是官方是推荐使用 elementRegistry 的方式.
上面我们已经介绍了 modeler 和 element 的监听绑定方式, 在事件应用中, 你更多的需要知道用户要进行什么操作, 好写对应的业务逻辑.
这里我就以我工作中要用到的场景为案例进行讲解.
案例Git地址: LinDaiDai-bpmn.js案例event.vue 喜欢的小伙伴请给个 Star 🌟呀, 谢谢😊
系列全部目录请查看此处: 《全网最详bpmn.js教材》
系列相关推荐:
《全网最详bpmn.js教材-基础篇》
《全网最详bpmn.js教材-http请求篇》
《全网最详bpmn.js教材-renderer篇》
《全网最详bpmn.js教材-contextPad篇》
《全网最详bpmn.js教材-编辑、删除节点篇》