CSS
1.绘制三角形
div {
width: 0;
height: 0;
border: 50px solid transparent;
border-color: red green blue black;
/*想要实现其他三角形只需要把对应的颜色改成transparent即可*/
line-height: 0;
font-size: 0;
}
2.CSS3滤镜处理
filter CSS属性将模糊或颜色偏移等图形效果应用于元素
filter: 函数(); --> 例如: filter: blur(5px); --> blur模糊处理 数值越大越模糊
3.border-collapse
border-collapse:collapse; 表示相邻边框合并在一起
4.实现盒子居中
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%) ====> 动态居中
position: absolute;
left:50%
margin-left:-(width/2)
top:50%
margin-top:-(高度/2)
5.textarea 设置属性防止拖拽文字域
textarea {
/* 防止拖拽文本域 */
resize: none;
}
6.设置鼠标样式
- cursor: pointer; =====> 小手模式
- cursor: move; =========>移动模式
- cursor: text;===========>文本模式
- cursor: not-allowed;=====>禁止模式
7.文本溢出方法
/*1.强行一行显示文本*/
white-space: nowrap; ( 默认 normal 自动换行)
/*2.对溢出的部分采用隐藏*/
overflow: hidden;
/*3.文字用省略号替代超出的部分*/
text-overflow: ellipsis;
8.失去焦点操作
outline:none;
9.实现波纹扩散效果
<div class="city">
<div class="dotted"></div>
<div class="pulse1"></div>
<div class="pulse2"></div>
<div class="pulse3"></div>
</div>
.city {
position: absolute;
top: 227px;
right: 193px;
color: #fff;
}
.dotted {
width: 8px;
height: 8px;
background-color: #09f;
border-radius: 50%;
}
.city div[class^="pulse"] {
/* 保证我们小波纹在父盒子里面水平垂直居中 放大之后就会中心向四周发散 */
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 8px;
height: 8px;
box-shadow: 0 0 12px #009dfd;
border-radius: 50%;
animation: pulse 1.2s linear infinite;
}
.city div.pulse2 {
animation-delay: 0.4s;
}
.city div.pulse3 {
animation-delay: 0.8s;
}
@keyframes pulse {
0% {}
70% {
/* transform: scale(5); 我们不要用scale 因为他会让 阴影变大*/
width: 400px;
height: 400px;
opacity: 1;
}
100% {
width: 700px;
height: 700px;
opacity: 0;
}
10. flex布局技巧
- 因为flex 属性定义子项目分配剩余空间,用flex来表示占多少份数。
- 如果要分配的盒子不定义宽度(这样的话就继承了浏览器的宽度)的话,那么整个大盒子就都是所谓的“剩余空间”
- 给各个属性的值是flex:1既可以自己主动划分等量的宽度。
11.让背景图片随着浏览器宽度自适应
background-size:cover/contain;
cover:在缩放时铺满整个盒子
contain:缩放时让背景图完整的显示出来
12.快速的将表单的内容全部清空
使用原生js的reset()方法
$("#formAddCmt")[0].reset(); // $(“formAddCmt”)[0] ==> 转换成原生的js
13.快速获取表单的所有数据
使用FormData快速获取表单中的数据
// 1. 通过 DOM 操作,获取到 form 表单元素
var form = document.querySelector('#form1')form.addEventListener('submit', function (e) {
// 阻止表单的默认提交行为
e.preventDefault()// 创建 FormData,快速获取到 form 表单中的数据
var fd = new FormData(form)var xhr = new XMLHttpRequest()
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
xhr.send(fd)xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText))
}
}
})
JS
1.获取指定范围的随机整数
Math.floor(Math.random() * (max - min + 1)) + min;
2.格式化日期
// 格式化日期 年月日
var date = new Date();
console.log(date.getFullYear()); // 返回当前日期的年 2019
console.log(date.getMonth() + 1); // 月份 返回的月份小1个月 记得月份+1 呦
console.log(date.getDate()); // 返回的是 几号
console.log(date.getDay()); // 3 周一返回的是 1 周六返回的是 6 但是 周日返回的是 0
// 我们写一个 2019年 5月 1日 星期三
var year = date.getFullYear();
var month = date.getMonth() + 1;
var dates = date.getDate();
var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
var day = date.getDay();
console.log('今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day]);// 格式化日期 时分秒
var date = new Date();
console.log(date.getHours()); // 时
console.log(date.getMinutes()); // 分
console.log(date.getSeconds()); // 秒
// 要求封装一个函数返回当前的时分秒 格式 08:08:08
function getTimer() {
var time = new Date();
var h = time.getHours();
h = h < 10 ? '0' + h : h;
var m = time.getMinutes();
m = m < 10 ? '0' + m : m;
var s = time.getSeconds();
s = s < 10 ? '0' + s : s;
return h + ':' + m + ':' + s;
}
3.选项框全选和反选
// 1. 全选和取消全选做法: 让下面所有复选框的checked属性(选中状态) 跟随 全选按钮即可
// 获取元素
var j_cbAll = document.getElementById('j_cbAll'); // 全选按钮
var j_tbs = document.getElementById('j_tb').getElementsByTagName('input'); // 下面所有的复选框 (是一个数组来的)
// 注册事件
j_cbAll.onclick = function () {
// this.checked 它可以得到当前复选框的选中状态如果是true 就是选中,如果是false 就是未选中
console.log(this.checked);
for (var i = 0; i < j_tbs.length; i++) {
j_tbs[i].checked = this.checked;
}
}
// 2. 下面复选框需要全部选中, 上面全选才能选中做法: 给下面所有复选框绑定点击事件,每次点击,都要循环查看下面所有的复选框是否有没选中的,如果有一个没选中的, 上面全选就不选中。
for (var i = 0; i < j_tbs.length; i++) {
j_tbs[i].onclick = function () {
// flag 控制全选按钮是否选中
var flag = true;
// 每次点击下面的复选框都要循环检查者4个小按钮是否全被选中
for (var i = 0; i < j_tbs.length; i++) {
if (!j_tbs[i].checked) {
flag = false;
break; // 退出for循环 这样可以提高执行效率 因为只要有一个没有选中,剩下的就无需循环判断了
}
}
j_cbAll.checked = flag;
}
}
4.获得父元素下的子类的小技巧
1、parentNode.children()
2、DOM原生提供的方法
<script>
// DOM 提供的方法(API)获取
var ul = document.querySelector('ul');
var lis = ul.querySelectorAll('li');
console.log(lis);
var ul = document.getElementsByTagName("ul")[0];
var lis = ul.getElementsByTagName("li")
console.log(lis);
// 2. children 获取所有的子元素节点 也是我们实际开发常用的
console.log(ul.children); //记住后面是没有括号的
</script>
5.button按钮里面的内容是通过innerHTML来更改的,不是通过value值来更改,跟其他表单元素不一样。
6.轮播图制作
<div class="focus fl">
<!-- 左侧按钮 -->
<a href="javascript:;" class="arrow-l">
<
</a>
<!-- 右侧按钮 -->
<a href="javascript:;" class="arrow-r"> </a>
<!-- 核心的滚动区域 -->
<ul>
<li>
<a href="#"><img src="upload/focus.jpg" alt=""></a>
</li>
<li>
<a href="#"><img src="upload/focus1.jpg" alt=""></a>
</li>
<li>
<a href="#"><img src="upload/focus2.jpg" alt=""></a>
</li>
<li>
<a href="#"><img src="upload/focus3.jpg" alt=""></a>
</li>
</ul>
<!-- 小圆圈 -->
<ol class="circle"></ol>
</div>
.focus {
position: relative;
width: 721px;
height: 455px;
background-color: purple;
overflow: hidden;
}.focus ul {
position: absolute;
top: 0;
left: 0;
width: 600%; //这里是为了让所有的图片可以在一行上显示
}.focus ul li {
float: left;
}.arrow-l,
.arrow-r {
display: none;
position: absolute;
top: 50%;
margin-top: -20px;
width: 24px;
height: 40px;
background: rgba(0, 0, 0, .3);
text-align: center;
line-height: 40px;
color: #fff;
font-family: 'icomoon';
font-size: 18px;
z-index: 2;
}.arrow-r {
right: 0;
}.circle {
position: absolute;
bottom: 10px;
left: 50px;
}.circle li {
float: left;
width: 8px;
height: 8px;
/*background-color: #fff;*/
border: 2px solid rgba(255, 255, 255, 0.5);
margin: 0 3px;
border-radius: 50%;
/*鼠标经过显示小手*/
cursor: pointer;
}
window.addEventListener('load', function() {
// 1. 获取元素
var arrow_l = document.querySelector('.arrow-l');
var arrow_r = document.querySelector('.arrow-r');
var focus = document.querySelector('.focus');
var focusWidth = focus.offsetWidth;
// 2. 鼠标经过focus 就显示隐藏左右按钮
focus.addEventListener('mouseenter', function() {
arrow_l.style.display = 'block';
arrow_r.style.display = 'block';
clearInterval(timer);
timer = null; // 清除定时器变量
});
focus.addEventListener('mouseleave', function() {
arrow_l.style.display = 'none';
arrow_r.style.display = 'none';
timer = setInterval(function() {
//手动调用点击事件
arrow_r.click();
}, 2000);
});
// 3. 动态生成小圆圈 有几张图片,我就生成几个小圆圈
var ul = focus.querySelector('ul');
var ol = focus.querySelector('.circle');
// console.log(ul.children.length);
for (var i = 0; i < ul.children.length; i++) {
// 创建一个小li
var li = document.createElement('li');
// 记录当前小圆圈的索引号 通过自定义属性来做
li.setAttribute('index', i);
// 把小li插入到ol 里面
ol.appendChild(li);
// 4. 小圆圈的排他思想 我们可以直接在生成小圆圈的同时直接绑定点击事件
li.addEventListener('click', function() {
// 干掉所有人 把所有的小li 清除 current 类名
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
// 留下我自己 当前的小li 设置current 类名
this.className = 'current';
// 5. 点击小圆圈,移动图片 当然移动的是 ul
// ul 的移动距离 小圆圈的索引号 乘以 图片的宽度 注意是负值
// 当我们点击了某个小li 就拿到当前小li 的索引号
var index = this.getAttribute('index');
// 当我们点击了某个小li 就要把这个li 的索引号给 num
num = index;
// 当我们点击了某个小li 就要把这个li 的索引号给 circle
circle = index;
// num = circle = index;
console.log(focusWidth);
console.log(index);animate(ul, -index * focusWidth);
})
}
// 把ol里面的第一个小li设置类名为 current
ol.children[0].className = 'current';
// 6. 克隆第一张图片(li)放到ul 最后面
var first = ul.children[0].cloneNode(true);
ul.appendChild(first);
// 7. 点击右侧按钮, 图片滚动一张
var num = 0;
// circle 控制小圆圈的播放
var circle = 0;
// flag 节流阀
var flag = true;
arrow_r.addEventListener('click', function() {
if (flag) {
flag = false; // 关闭节流阀
// 如果走到了最后复制的一张图片,此时 我们的ul 要快速复原 left 改为 0
if (num == ul.children.length - 1) {
ul.style.left = 0;
num = 0;
}
num++;
animate(ul, -num * focusWidth, function() {
flag = true; // 打开节流阀
});
// 8. 点击右侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放
circle++;
// 如果circle == 4 说明走到最后我们克隆的这张图片了 我们就复原
if (circle == ol.children.length) {
circle = 0;
}
// 调用函数
circleChange();
}
});// 9. 左侧按钮做法
arrow_l.addEventListener('click', function() {
if (flag) {
flag = false;
if (num == 0) {
num = ul.children.length - 1;
ul.style.left = -num * focusWidth + 'px';}
num--;
animate(ul, -num * focusWidth, function() {
flag = true;
});
// 点击左侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放
circle--;
// 如果circle < 0 说明第一张图片,则小圆圈要改为第4个小圆圈(3)
// if (circle < 0) {
// circle = ol.children.length - 1;
// }
circle = circle < 0 ? ol.children.length - 1 : circle;
// 调用函数
circleChange();
}
});function circleChange() {
// 先清除其余小圆圈的current类名
for (var i = 0; i < ol.children.length; i++) {
ol.children[i].className = '';
}
// 留下当前的小圆圈的current类名
ol.children[circle].className = 'current';
}
// 10. 自动播放轮播图
var timer = setInterval(function() {
//手动调用点击事件
arrow_r.click();
}, 2000);})
7. 动态的返回顶部
//1. 获取元素
var sliderbar = document.querySelector('.slider-bar');
var banner = document.querySelector('.banner');
// banner.offestTop 就是被卷去头部的大小 一定要写到滚动的外面
var bannerTop = banner.offsetTop
// 当我们侧边栏固定定位之后应该变化的数值
var sliderbarTop = sliderbar.offsetTop - bannerTop;
// 获取main 主体元素
var main = document.querySelector('.main');
var goBack = document.querySelector('.goBack');
var mainTop = main.offsetTop;
// 2. 页面滚动事件 scroll
document.addEventListener('scroll', function() {
// console.log(11);
// window.pageYOffset 页面被卷去的头部
// console.log(window.pageYOffset);
// 3 .当我们页面被卷去的头部大于等于了 172 此时 侧边栏就要改为固定定位
if (window.pageYOffset >= bannerTop) {
sliderbar.style.position = 'fixed';
sliderbar.style.top = sliderbarTop + 'px';
} else {
sliderbar.style.position = 'absolute';
sliderbar.style.top = '300px';
}
// 4. 当我们页面滚动到main盒子,就显示 goback模块
if (window.pageYOffset >= mainTop) {
goBack.style.display = 'block';
} else {
goBack.style.display = 'none';
}})
// 3. 当我们点击了返回顶部模块,就让窗口滚动的页面的最上方
goBack.addEventListener('click', function() {
// 里面的x和y 不跟单位的 直接写数字即可
// window.scroll(0, 0);
// 因为是窗口滚动 所以对象是window
animate(window, 0);
});
8.元素的宽度总结
- offset系列 经常用于获得元素位置 offsetLeft offsetTop
- client经常用于获取元素大小 clientWidth clientHeight
- scroll 经常用于获取滚动距离 scrollTop scrollLeft
注意页面滚动的距离通过 window.pageXOffset 获得
9.解构赋值
const obj = { name: '林三心', age: 22, gender: '男', doing: { morning: '摸鱼', afternoon: '摸鱼', evening: 'sleep' } }
const { name, age, gender } = obj
console.log(name, age, gender) // 林三心 22 男
// 解构重名
const { name: myname } = obj
console.log(myname) // 林三心
// 嵌套解构
const { doing: { evening } } = obj console.log(evening) // sleep
const arr = [1, 2, 3]
const [a, b, c] = arr
console.log(a, b, c) // 1 2 3
// 默认赋值
const [a, b, c, d = 5] = arr
console.log(a, b, c, d) // 1 2 3 5
// 乱序解构
const { 1: a, 0: b, 2: c } = arr
console.log(a, b, c) // 2 1 3
JQuery
1.实现对话框居中
function showDialog() {
// 实现对话框动态居中
var objW = $(window);
var objC = $(".dialog");// 1、获取屏幕的宽和高
var scrW = objW.width();
var scrH = objW.height();// 2、获取屏幕的滚动距离
var roL = objW.scrollLeft();
var roT = objW.scrollTop();// 3、获取对话框的宽和高
var diaW = objC.width();
var diaH = objC.height();// 4、实现动态居中
// 左边距 = 左边滚动距离 + (屏幕的宽 - 对话框的宽)/2
var left = roL + (scrW - diaW) / 2;
// 上边距 = 上边滚动距离 + (屏幕的高 - 对话框的高)/2
var top = roT + (scrH - diaH) / 2;objC.css({
left: left,
top: top
})
}// 检测屏幕尺寸改变
$(window).resize(function () {
// 如果对话框没有显示,则不操作该对话框
if (!$('.dialog').is(':visible')) {
return;
}
showDialog();
})
2.检测选择框有没有被选中
this.checked 它可以得到当前复选框的选中状态如果是true 就是选中,如果是false 就是未选中
其他属性也是一样的道理!!!
3.排他思想:当前元素设置样式,其余的兄弟元素清除样式
//干掉所有人
$(this).siblings(). css(“color”,””);
//设置我自己
$(this).css(“color”,”red”);
4.tab栏互切
$(function () {
// 2、给每一个li增加一个mouseover事件
// 01.获取li元素
// 02.添加事件 ==>与js的有点不相同要注意
$('#left li').mouseover(function () {
// 1、获取索引值 ==>jQuery 得到当前元素索引号 $(this).index()
var index = $(this).index();
// 3、取到索引值对应的图片
// 01.获取图片元素
// 02.获取当前索引值中的图片 ==> eq()
$("#content div").eq(index).show().siblings().hide();})
})//第二种类型
$(function() {
// 1.点击上部的li,当前li 添加current类,其余兄弟移除类
$(".tab_list li").click(function() {
// 链式编程操作
$(this).addClass("current").siblings().removeClass("current");
// 2.点击的同时,得到当前li 的索引号
var index = $(this).index();
console.log(index);
// 3.让下部里面相应索引号的item显示,其余的item隐藏
$(".tab_con .item").eq(index).show().siblings().hide();
});
})
// 5. tab栏自动切换效果
// 开启定时器每隔3s,自动让a触发点击事件即可
var as = $(".sales .caption a");
var index = 0;
var timer = setInterval(function() {
index++;
if (index >= 4) index = 0;
as.eq(index).click();
}, 1000);
// 鼠标经过sales,关闭定时器,离开开启定时器
$(".sales").hover(
function() {
clearInterval(timer);
},
function() {
clearInterval(timer);
timer = setInterval(function() {
index++;
if (index >= 4) index = 0;
as.eq(index).click();
}, 1000);
}
);知识点:
利用$(this).index()获取索引号
一般都会使用.eq()来利用获取的索引号来找到对应的元素
5. 隐式迭代的效果
// 遍历内部 DOM 元素(伪数组形式存储)的过程就叫做隐式迭代。
// 简单理解:给匹配到的所有元素进行循环遍历,执行相应的方法,而不用我们再进行循环,简化我们的操作,方便我们调用。
$('div').hide(); // 页面中所有的div全部隐藏,不用循环操作注意:隐式迭代是对同一类元素做了同样的操作,如果想对同一类元素做不同的操作,就需要使用遍历了
6.JQuery实现全选效果
$(".checkall").change(function() {
// console.log($(this).prop("checked"));
$(".j-checkbox, .checkall").prop("checked", $(this).prop("checked"));
});// 2. 如果小复选框被选中的个数等于3 就应该把全选按钮选上,否则全选按钮不选。
$(".j-checkbox").change(function() {
// if(被选中的小的复选框的个数 === 3) {
// 就要选中全选按钮
// } else {
// 不要选中全选按钮
// }
// console.log($(".j-checkbox:checked").length);
// $(".j-checkbox").length 这个是所有的小复选框的个数
if ($(".j-checkbox:checked").length === $(".j-checkbox").length) {
$(".checkall").prop("checked", true);
} else {
$(".checkall").prop("checked", false);
}
if ($(this).prop("checked")) {
// 让当前的商品添加 check-cart-item 类名
$(this).parents(".cart-item").addClass("check-cart-item");
} else {
// check-cart-item 移除
$(this).parents(".cart-item").removeClass("check-cart-item");
}
});
7.返回顶部动画
// 返回顶部
$(".back").click(function() {
// $(document).scrollTop(0);
$("body, html").stop().animate({
scrollTop: 0
});
// $(document).stop().animate({
// scrollTop: 0
// }); 不能是文档而是 html和body元素做动画
})
8.当有一系列的相同元素需要做出相同的响应时
//1 直接绑定==>利用JQuery的隐式迭代,但是这样每一个元素都添加了事件,程序效率不高
$("ul li").click(function() { // 此时的click不能给动态创建的a添加事件
alert(11);
})
//2 利用事件委托 ==>绑定到父元素上,利用on绑定事件 效率↑
$("ul").on("click", "li", function() {
alert(11);
});
9.遍历小技巧
$.each(data, function(i, n) {
// console.log(n);
if (n.done) {
$("ul").prepend("<li><input type='checkbox' checked='checked' > <p>" + n.title + "</p> <a href='javascript:;' id=" + i + " ></a></li>");
doneCount++;
} else {
$("ol").prepend("<li><input type='checkbox' > <p>" + n.title + "</p> <a href='javascript:;' id=" + i + " ></a></li>");
todoCount++;
}}); // ===========================>利用属性中的i(索引号) 添加给元素 成为自定义的索引号
JWT 认证机制
- 安装 JWT 相关的包 ------->npm i jsonwebtoken express-jwt
- 导入JWT相关的包 -------> const jwt = require('jsonwebtoken') const expressJWT = require('express-jwt')
3.定义 secret 密钥
- 当生成 JWT 字符串的时候,需要使用 secret 密钥对用户的信息进行加密,最终得到加密好的 JWT 字符串。
- 当把 JWT 字符串解析还原成 JSON 对象的时候,需要使用 secret 密钥进行解密。
const secretKey = 'beita'
4.在登录成功后生成 JWT 字符串
// 登录接口
app.post('/api/login', function (req, res) {
// 将 req.body 请求体中的数据,转存为 userinfo 常量
const userinfo = req.body
// 登录失败
if (userinfo.username !== 'admin' || userinfo.password !== '000000') {
return res.send({
status: 400,
message: '登录失败!',
})
}
// TODO_03:在登录成功之后,调用 jwt.sign() 方法生成 JWT 字符串。并通过 token 属性发送给客户端
// 参数1:用户的信息对象
// 参数2:加密的秘钥
// 参数3:配置对象,可以配置当前 token 的有效期
// 记住:千万不要把密码加密到 token 字符中
const tokenStr = jwt.sign({ username: userinfo.username }, secretKey, { expiresIn: '30s' })
res.send({
status: 200,
message: '登录成功!',
token: tokenStr, // 要发送给客户端的 token 字符串
})
})
5.客户端每次在访问那些有权限接口的时候,都需要主动通过请求头中的 Authorization 字段,将 Token 字符串发 送到服务器进行身份认证。
// TODO_04:注册将 JWT 字符串解析还原成 JSON 对象的中间件
// 注意:只要配置成功了 express-jwt 这个中间件,就可以把解析出来的用户信息,挂载到 req.user 属性上
app.use(expressJWT({ secret: secretKey }).unless({ path: [/^\/api\//] }))
6.可在那些有权限的接口中,使用 req.user 对象,来访问从 JWT 字符串中解析出来的用户信息了。
// 这是一个有权限的 API 接口
app.get('/admin/getinfo', function (req, res) {
// TODO_05:使用 req.user 获取用户信息,并使用 data 属性将用户信息发送给客户端
console.log(req.user)
res.send({
status: 200,
message: '获取用户信息成功!',
data: req.user, // 要发送给客户端的用户信息
})
})
7.捕获解析 JWT 失败后产生的错误
// TODO_06:使用全局错误处理中间件,捕获解析 JWT 失败后产生的错误
app.use((err, req, res, next) => {
// 这次错误是由 token 解析失败导致的
if (err.name === 'UnauthorizedError') {
return res.send({
status: 401,
message: '无效的token',
})
}
res.send({
status: 500,
message: '未知的错误',
})
})
Vue动态菜单配置