这里写目录标题
- css 重置normalize.css
- 透明度兼容
- css一个元素盖住的下面那层模糊
- 获取非行内的样式
- 颜色随机
- 解除绑定事件removeEvent
- 封装函数实现获取一个对象的非行间样式,并且保证兼容性
- onscroll滚动条
- 阻止浏览器默认行为兼容性写法
- 阻止冒泡写法
- 鼠标右键
- 滚轮事件
- 滚动条平滑滚动到某个位置
- 判断一个元素是否在可视区显示
- 跨页面传值encodeURI(),decodeURI()编码,解码
- 跨页面传多个值,转对象
- js将秒转化为时分秒
- 判断鼠标是否暂停
- ajax封装函数
- ajax jq
- cookie设置
- 防抖:事件多次出发后,只执行最后一次.利用计时器,当再次点击的时候,会从新计时
- 节流: 事件多次出发后,一定时间内只执行一次
- 文本内容可编辑
- 网页切换过程中运动函数setinterval
- 媒体查询
- 网络状态
- 全屏显示
- fetch请求,用来解决ajax的回调地狱
- 递归
- 判断俩对象是否相等
- 秒杀倒计时
- 输入时间倒计时
- 面向对象选项卡
- 数组去重filter 过滤出第一次出现的位置和当前位置相等的元素
- 知道角度求弧度
- 数组排序
- 数组拍平
- 取出数组中每个对象的某个值
- 获取一个月第一天,有多少天
- js合并两个有序链表
- 判断对象是不是空对象
- 判断俩对象的值是否相等
- 数组去重
- 知道角度求弧度
- float和flex区别
- userAgent是什么
- 数组随机变化顺序
- 判断一个数是否是整数
- 数组转为树状结构
- 树状转给数组
- 判断数组最大值
- 路由地址栏路径去掉vue3,2传参
- v2 element-ui el-input修改不了
- FormData 传递接口数据post
- 判断对象数组中,对象是否包含某个属性,返回true/false
- 判断对象数组中,对象的某个属性所在的位置
- 对象,数组中找一个属性使用递归
- 修改若依vue项目首页加载loading动画
- vue-quill-editor 里面内置135/秀米编辑器
- 当描述图片加载提示、加载失败提示
- 前端倒计时(类似于订单支付的倒计时显示),不考虑浏览器失活的情况
- Vue 中 input 输入框被赋值后,无法再修改和编辑
css 重置normalize.css
index.html
<link rel="stylesheet" href="./normalize.css">
/*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */
/**
* 1. Change the default font family in all browsers (opinionated).
* 2. Correct the line height in all browsers.
* 3. Prevent adjustments of font size after orientation changes in
* IE on Windows Phone and in iOS.
*/
/* Document
========================================================================== */
html {
font-family: sans-serif;
/* 1 */
line-height: 1.15;
/* 2 */
-ms-text-size-adjust: 100%;
/* 3 */
-webkit-text-size-adjust: 100%;
/* 3 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers (opinionated).
*/
body {
margin: 0;
}
/**
* Add the correct display in IE 9-.
*/
article,
aside,
footer,
header,
nav,
section {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* Add the correct display in IE 9-.
* 1. Add the correct display in IE.
*/
figcaption,
figure,
main {
/* 1 */
display: block;
}
/**
* Add the correct margin in IE 8.
*/
figure {
margin: 1em 40px;
}
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box;
/* 1 */
height: 0;
/* 1 */
overflow: visible;
/* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace;
/* 1 */
font-size: 1em;
/* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* 1. Remove the gray background on active links in IE 10.
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
*/
a {
background-color: transparent;
/* 1 */
-webkit-text-decoration-skip: objects;
/* 2 */
}
/**
* Remove the outline on focused links when they are also active or hovered
* in all browsers (opinionated).
*/
a:active,
a:hover {
outline-width: 0;
}
/**
* 1. Remove the bottom border in Firefox 39-.
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none;
/* 1 */
text-decoration: underline;
/* 2 */
text-decoration: underline dotted;
/* 2 */
}
/**
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
*/
b,
strong {
font-weight: inherit;
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace;
/* 1 */
font-size: 1em;
/* 2 */
}
/**
* Add the correct font style in Android 4.3-.
*/
dfn {
font-style: italic;
}
/**
* Add the correct background and color in IE 9-.
*/
mark {
background-color: #ff0;
color: #000;
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Add the correct display in IE 9-.
*/
audio,
video {
display: inline-block;
}
/**
* Add the correct display in iOS 4-7.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Remove the border on images inside links in IE 10-.
*/
img {
border-style: none;
}
/**
* Hide the overflow in IE.
*/
svg:not(:root) {
overflow: hidden;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers (opinionated).
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: sans-serif;
/* 1 */
font-size: 100%;
/* 1 */
line-height: 1.15;
/* 1 */
margin: 0;
/* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input {
/* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select {
/* 1 */
text-transform: none;
}
/**
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
* controls in Android 4.
* 2. Correct the inability to style clickable types in iOS and Safari.
*/
button,
html [type="button"],
/* 1 */
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
/* 2 */
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Change the border, margin, and padding in all browsers (opinionated).
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box;
/* 1 */
color: inherit;
/* 2 */
display: table;
/* 1 */
max-width: 100%;
/* 1 */
padding: 0;
/* 3 */
white-space: normal;
/* 1 */
}
/**
* 1. Add the correct display in IE 9-.
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
display: inline-block;
/* 1 */
vertical-align: baseline;
/* 2 */
}
/**
* Remove the default vertical scrollbar in IE.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10-.
* 2. Remove the padding in IE 10-.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box;
/* 1 */
padding: 0;
/* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield;
/* 1 */
outline-offset: -2px;
/* 2 */
}
/**
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button;
/* 1 */
font: inherit;
/* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in IE 9-.
* 1. Add the correct display in Edge, IE, and Firefox.
*/
details,
/* 1 */
menu {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Scripting
========================================================================== */
/**
* Add the correct display in IE 9-.
*/
canvas {
display: inline-block;
}
/**
* Add the correct display in IE.
*/
template {
display: none;
}
/* Hidden
========================================================================== */
/**
* Add the correct display in IE 10-.
*/
[hidden] {
display: none;
}
a {
text-decoration: none;
color: #333;
}
html {
color: #000;
background: #fff;
overflow-y: scroll;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%
}
html * {
outline: 0;
-webkit-text-size-adjust: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0)
}
html,
body {
font-family: sans-serif
}
body,
div,
dl,
dt,
dd,
ul,
ol,
li,
h1,
h2,
h3,
h4,
h5,
h6,
pre,
code,
form,
fieldset,
legend,
input,
textarea,
p,
blockquote,
th,
td,
hr,
button,
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
menu,
nav,
section {
margin: 0;
padding: 0
}
input,
select,
textarea {
font-size: 100%
}
table {
border-collapse: collapse;
border-spacing: 0
}
fieldset,
img {
border: 0
}
abbr,
acronym {
border: 0;
font-variant: normal
}
del {
text-decoration: line-through
}
address,
caption,
cite,
code,
dfn,
em,
th,
var {
font-style: normal;
font-weight: 500
}
ol,
ul {
list-style: none
}
caption,
th {
text-align: left
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-size: 100%;
font-weight: 500
}
input{
display:block;
border: none;
outline: none;
}
透明度兼容
filter:alpha(opacity=30);
css一个元素盖住的下面那层模糊
backdrop-filter: blur(20px);
获取非行内的样式
var allStyle=getComputedStyle('box');
allStyle.width
绑定事件兼容处理
function addMyEvent(obj,event,fn){
if(obj.addEventListener){
//判断对象有没有addEventListener
obj.addEventListener(event,fn,false)
}else{
//ie低版本
obj.attachEvent('on'+event,fn)
}
}
addMyEvent(box,'click',my)
颜色随机
function randomColor(){
var r=Math.round(Math.random()*255);
var g=Math.round(Math.random()*255);
var a=Math.round(Math.random()*255);
return 'rgb('+r+','+g+','+a')'
}
解除绑定事件removeEvent
function removeEvent(obj,event,fn){
if(obj.removeEventListener){
//判断对象有没有addEventListener
obj.removeEventListener(event,fn,false)
}else if(obj.detachEvent){
//ie低版本
obj.detachEvent('on'+event,fn)
}
}
封装函数实现获取一个对象的非行间样式,并且保证兼容性
function getStyle(obj.attr){
//获取谁的属性:obj
//获取什么属性:attr
//判断浏览器是否支持getComputedStyle
if(window.getComputedStyle){
return window.getComputedStyle(obj,null)[attr];
}else{
//ie低版本方法
return obj.currentStyle[attr]
}
}
/// 事件兼容写法
box.onclick = function (e){
//兼容写法
e = e || window.event
}
onscroll滚动条
var scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;
阻止浏览器默认行为兼容性写法
event.preventDefault ? event.preventDefault() : (event.returnValue = false);
阻止冒泡写法
event.stopPropagation ? event.stopPropagation() : (event.cancelBubble = true);
鼠标右键
document.oncontextmenu=function(){};
滚轮事件
ie/chrome : onmousewheel
ie/chrome : event.wheelDelta
向上滚动返回值大于0,向下滚动返回值小于0
firefox : DOMMouseScroll 必须用addEventListener
document.addEventListener('DOMMouseScroll',fn,false);
firefox : event.detail
向上滚动返回值小于0,向下滚动返回值大于0
滚动条平滑滚动到某个位置
window.scrollTo({
left:0,
top:div1s[this.index].offsetTop,
behavior:"smooth"
})
判断一个元素是否在可视区显示
可视区高度+滚动条高度>元素的offsetTop;
跨页面传值encodeURI(),decodeURI()编码,解码
var a=decodeURI(location.search);
function my(a){
var obj={};
var b=a.slice(1);
var c=b.split('&');
for(var i=0;i<c.length;i++){
var d=c[i];
var f=d.split('=');
obj[f[0]]=f[1];]
}
return obj
}
my(a)
跨页面传多个值,转对象
var str=‘?name=张三&age=12&city=北京&name=王五&age=18&city=上海’;
var str2=str.slice(1);
var arr=str2.split(‘&’);
var arr0=[];
for(var i=0;i<arr.length;i++){
var obj={};
while(arr.length>0){
var b=arr.splice(0,3);
for(var z=0;z<b.length;z++){
var c=b[z].split(‘=’);
obj[c[0]]=c[1];
}
arr0.push(obj);
obj={};
}
}
console.log(arr0)
js将秒转化为时分秒
function formatSeconds(value) {
let result = parseInt(value)
let h = Math.floor(result / 3600) < 10 ? '0' + Math.floor(result / 3600) : Math.floor(result / 3600)
let m = Math.floor((result / 60 % 60)) < 10 ? '0' + Math.floor((result / 60 % 60)) : Math.floor((result / 60 % 60))
let s = Math.floor((result % 60)) < 10 ? '0' + Math.floor((result % 60)) : Math.floor((result % 60))
result = `${h}:${m}:${s}`
return result
}
判断鼠标是否暂停
(function(){
let isMove = false,
timer = null;
window.onmousemove = function(){
isMove = true;
clearTimeout(timer);
console.log(isMove); // 移动时
timer = setTimeout(function(){
isMove = false;
console.log(isMove); // 静止后
},200);
}
}());
ajax封装函数
function ajax(options){
var xhr = null;
var params = formsParams(options.data);
//创建对象
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest()
} else {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
// 连接
if(options.type == "GET"){
xhr.open(options.type,options.url + "?"+ params,options.async);
xhr.send(null)
} else if(options.type == "POST"){
xhr.open(options.type,options.url,options.async);
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
xhr.send(params);
}
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
options.success(xhr.responseText);
}
}
function formsParams(data){
var arr = [];
for(var prop in data){
arr.push(prop + "=" + data[prop]);
}
return arr.join("&");
}
}
ajax({
url : "http://localhost:8082/Ajax/my4.json", // url---->地址
type : "POST", // type ---> 请求方式
async : true, // async----> 同步:false,异步:true
data : { //传入信息
name : "张三",
age : 18
},
success : function(data){ //返回接受信息
var a=JSON.parse(data);
console.log(a);
}})
ajax jq
$(function(){
//请求参数
$.ajax({
type : "POST",//请求方式
cache:true,//开启缓存 缓存问题用随机数解决
async:true,//是否异步请求
contentType: "application/x-www-form-urlencoded; charset=utf-8", //请求的媒体类型 默认是:"application/json;charset=UTF-8"
url : "http://127.0.0.1/admin/list/", //请求地址
//数据,json字符串
dataType:"json",
data : JSON.stringify({
}),
success : function(result){//请求成功
console.log(result);//已经转换成对象了
},
error : function(e){ //请求失败,包含具体的错误信息
console.log(e.status);
console.log(e.responseText);
},
beforeSend:function(){},//ajax请求之前执行
complete:function(){ },//Ajax请求完成后执行
});
});
cookie设置
//获取cookie函数封装 参数为想要获取的cookie的名字
function getCookie(cname){
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i=0; i<ca.length; i++)
{
var c = ca[i].trim();
if (c.indexOf(name)==0) return c.substring(name.length,c.length);
}
return "";
}
//设置cookie,三个参数,第一个参数cookie的名字,第二个参数是cookie的值,第三个参数是过期时间
function setCookie(cname,cvalue,exdays){
var d = new Date();
d.setTime(d.getTime()+(exdays*24*60*60*1000));
var expires = "expires="+d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires;
}
//删除cookie 一个参数,是想要删除的cookie的名字
function removeCookie(name){
var d=new Date()
d.setDate(d.getDate()-1)
document.cookie=name+"=1;expires="+dnjn
}
//发送
cookie.setCookie('token',a.data.token);
//获取
var num=cookie.getCookie('token');
防抖:事件多次出发后,只执行最后一次.利用计时器,当再次点击的时候,会从新计时
aBtn.onclick = function(){
fn1.call(this)//可以更改this指向
// fn1()或者直接调用
}
var fn1=debounce(function () {
console.log(111111)//这里也可以写ajax请求
}, 1000)
//防抖函数封装
function debounce(fun,wait){
var timer=null;
return function(){
console.log(this)//可以由外面更改this指向
clearInterval(timer)
timer=setTimeout(function(){
fun()
},wait)
}
}
节流: 事件多次出发后,一定时间内只执行一次
function debounce(fun,wait){
var flag=true;
return function(){
if(flag){
setTimeout(function(){
fun()
flag=true
},wait)
flag=false
}
}
}
文本内容可编辑
1111111
网页切换过程中运动函数setinterval
思路:如果页面是不可见的,那么我们就会清除定时器,如果页面是可见的,那么我们就重新开启定时器。
所以我们需要用document.onvisibilitychange进行监听,然后用document.visibilityState或者是document.hidden进行判断。
document.onvisibilitychange=function(){ if(document.visibilityState==“visible”){ timer=setInterval(slidemove, 1000); }else{ clearInterval(timer); } }
媒体查询
//当屏幕最小宽度为992px
@media screen and (min-width : 992px) {
body {
background-color: red;
}
}
//当屏幕宽度 最小为768px 最大为991px时
@media screen and (min-width:768px) and (max-width:991px) {
body {
background-color: blue;
}
}
//当屏幕最大宽度为767px
@media screen and (max-width:767px) {
body {
background-color: green;
color: #00a;
}
}
网络状态
console.log(window.navigator.onLine)/true/false
online()有网的时候
offline()断开时候调用
全屏显示
//准备一个按钮
<button onclick="handleFullScreen()">全屏</button>
//document.isFullScreen检测当前是否处于全屏
//定义一个变量进行判断,默认false 非全屏状态
let exitFullscreen = false
// 全屏事件
function handleFullScreen(){
let element = document.documentElement;
if (this.fullscreen) {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
} else {
if (element.requestFullscreen) {
element.requestFullscreen();
} else if (element.webkitRequestFullScreen) {
element.webkitRequestFullScreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.msRequestFullscreen) {
// IE11
element.msRequestFullscreen();
}
}
}
fetch请求,用来解决ajax的回调地狱
let options = {
method:“post”,
body:JSON.stringify({name:“lhy”,content:“hello”}), // 这里传入的数据类型必须和下面content-type的类型一致
cache:‘reload’, // 表示请求时忽略http缓存,但是请求完成后会刷新http缓存
credentials:‘include’, // 表示请求携带cookie等信息
headers:{
‘Token’:“lhytest”, // 用于设置请求头
‘content-type’: ‘application/json’ // 设置发送的数据类型
}
};
fetch(‘http://localhost/Api’,options).then(function (response) {
return response.json()
}).then(function (data) {
console.log(data);
document.getElementsByTagName(‘p’)[0].innerText = data.meta.token;
}).catch(function (error) {
console.log(error);
})
递归
function my(n){
if(n<2){
return 0
}
if(n==2){
return 2
}else{
return my(n-1)+n
}
}
my(3)
判断俩对象是否相等
const isObjectEqual = (obj1, obj2) => {
let o1 = obj1 instanceof Object;
let o2 = obj2 instanceof Object;
if (!o1 || !o2) { // 如果不是对象 直接判断数据是否相等
return obj1 === obj2
}
// 判断对象的可枚举属性组成的数组长度
if (Object.keys(obj1).length !== Object.keys(obj2).length) {
return false;
}
for (let attr in obj1) {
let a1 = Object.prototype.toString.call(obj1[attr]) == ‘[object Object]’
let a2 = Object.prototype.toString.call(obj2[attr]) == ‘[object Object]’
let arr1 = Object.prototype.toString.call(obj1[attr]) == ‘[object Array]’
if (a1 && a2) {
// 如果是对象继续判断
return isObjectEqual(obj1[attr], obj2[attr])
} else if (arr1) {
// 如果是对象 判断
if (obj1[attr].toString() != obj2[attr].toString()) {
return false;
}
} else if (obj1[attr] !== obj2[attr]) {
// 不是对象的就判断数值是否相等
return false
}
}
return true
}
秒杀倒计时
function getTimer(){
//获取当前开始时间
var nowTime =new Date();
//获取截至时间
var endTime = new Date('2021/11/16 10:00:00');
//分别获取时间戳(毫秒数),得到两个时间段之间的时间差
var now = nowTime.getTime();
var end = endTime.getTime();
var diff = end-now;
var t=null;//存放定时器
if(diff>=0){
//定义四个变量用来存放天、时、分、秒 d\h\m\s
var d =Math.floor(diff/1000/60/60/24);
var h =Math.floor(diff/1000/60/60%24);
var m =Math.floor(diff/1000/60%60);
var s =Math.floor(diff/1000%60);
d = d < 10 ? '0' + d : d;
h = h < 10 ? '0' + h : h;
m = m < 10 ? '0' + m : m;
s = s < 10 ? '0' + s : s;
document.getElementById('timer2').innerHTML=d+'天'+h+'时'+m+'分'+s+'秒';
t= setTimeout(getTimer,1000);
}else{
clearTimeout(t);
document.getElementById('timer2').innerHTML='00天'+'00时'+'00分'+'00秒';
}
}
输入时间倒计时
btn.onclick=function(){
var year = Number(document.getElementById('year').value);
var month = Number(document.getElementById('month').value)-1;
var day = Number(document.getElementById('day').value);
var hour = Number(document.getElementById('hour').value);
var minute = Number(document.getElementById('minute').value);
var second = Number(document.getElementById('second').value);
var nowYear = new Date().getFullYear();
var nowMonth = new Date().getMonth();
var nowDay = new Date().getDate();
var nowHour = new Date().getHours();
var nowMinute = new Date().getMinutes();
var nowSecond = new Date().getSeconds();
if(year<nowYear || (month<nowMonth && month>12 && month<0) || (day<nowDay && day<0 && day>31) || (hour<nowHour && hour>60 && hour<0) || (minute<nowMinute && minute>60 && minute<0) || (second<nowSecond && second>60 && second<0)){
alert('请输入大于当前的时间,并且是有效时间数字');
return false;
}
if(timer) clearInterval(timer);
timer = setInterval(function(){
var time = parseInt((new Date(year,month,day,hour,minute,second).getTime() - new Date().getTime())/1000);
// // 2.26小时=2
var oHour = parseInt(time/3600);
// //15.6分钟 = 15分钟
var oMinute = parseInt((time %3600)/60);
// //36秒
var oSecond = time % 60;
text.innerHTML = '距离设定时间还有'+oHour+'小时'+oMinute+'分钟'+oSecond+'秒';
},1000)
}
面向对象选项卡
var that//声明全局变量存储this
class Tab{
constructor(id){
that=this//保存this
this.main=document.querySelector(id);
this.lis=this.main.querySelectorAll('li');
this.sections=this.main.querySelectorAll('.box')
this.add=this.main.querySelector('.add')
this.ul=this.main.querySelector('ul:first-child')
this.init()
}
//初始化操作,相关元素绑定元素
init(){
this.updateNode()
this.add.onclick=this.addTab
for(let i=0;i<this.lis.length;i++){
this.lis[i].index=i
this.lis[i].onclick=this.taggleTab
}
}
clearClass(){//清除lis和box的类名
for(let z=0;z<this.lis.length;z++){
this.lis[z].classList.remove('active1')
this.sections[z].classList.remove('active2')
}}
//获取所有的li和section
updateNode(){
this.lis=this.main.querySelectorAll('li')
this.sections=this.main.querySelectorAll('.box')
}
//1.切换功能
taggleTab(){
that.clearClass()
this.classList.add('active1')
that.sections[this.index].classList.add('active2')//that 指向construction的this
}
//2.添加功能
addTab(){
that.clearClass()
//(1)创建li和section元素
//(2)追加到父元素
// var li=`<li>new</li>`
// that.ul.insertAdjacentHTML('beforeend',li)
var b=document.createElement('div');
b.classList.add('box')
b.classList.add('active2')
b.innerHTML='new'
that.main.appendChild(b)
var a=document.createElement('li')
a.innerHTML='1'
a.classList.add('active1')
that.ul.appendChild(a)
that.init()
}
//3.删除功能
removeTab(){}
//4.修改功能
editTab(){}
}
new Tab('.div')
数组去重filter 过滤出第一次出现的位置和当前位置相等的元素
var aaa = [1, 2, 4, 5, 3, 2, 1, 1]
var bbb = aaa.filter((item, index) => {
return aaa.findIndex(item2 => item2 === item) === index
})
知道角度求弧度
(45*Math.PT)/180
数组排序
function sortNumber(a,b){return a - b};
console.log(arr.sort(sortNumber));
console.log(arr);//会改变原来数组
数组拍平
arr.flat(Infinity)
取出数组中每个对象的某个值
let list=[{name:'a',time:[1,2]},{name:'b',time:[3,4]},{name:'c',time:[5,6 ]}]
let timeArr=[]
list.forEach(i => timeArr = [...timeArr, ...i.time]);
获取一个月第一天,有多少天
function first(year,month){
var firstDay = new Date(year,month-1, 1).getDay();//获取这个月第一天是周几(0-6,0代表星期天)
var nowMonthDates=new Date(year,month,0).getDate()//获取这个月有多少天
var LastMonthDates=new Date(year,month-1,0).getDate()//获取上个月有多少天
}
console.log(first(2022,9)); //标准月份,不用减
js合并两个有序链表
var mergeTwoLists = function(list1, list2) {
// 进行判空的处理
if(list1 == null) return list2;
if(list2 == null) return list1;
// 进行值的比较
if (list1.val <= list2.val){
list1.next = mergeTwoLists(list1.next,list2);
return list1;
}else{
list2.next = mergeTwoLists(list1,list2.next);
return list2;
}
};
判断对象是不是空对象
方法一:将对象转换成字符串,再判断是否等于“{}”
let obj={};
console.log(JSON.stringify(obj)==="{}");
//返回true
方法二:for in循环
let result=function(obj){
for(let key in obj){
return false;//若不为空,可遍历,返回false
}
return true;
}
console.log(result(obj));//返回true
方法三:Object.keys()方法,返回对象的属性名组成的一个数组,若长度为0,则为空对象(ES6的写法)
console.log(Object.keys(obj).length==0);//返回true
方法四:Object.getOwnPropertyNames方法获取对象的属性名,存到数组中,若长度为0,则为空对象
console.log(Object.getOwnPropertyNames(obj).length==0);//返回true
判断俩对象的值是否相等
JSON.stringify(obj)==JSON.stringify(obj);//true
//缺点:数据顺序不一样也不对
const isObjectEqual = (obj1, obj2) => {
let o1 = obj1 instanceof Object;
let o2 = obj2 instanceof Object;
if (!o1 || !o2) { // 如果不是对象 直接判断数据是否相等
return obj1 === obj2
}
// 判断对象的可枚举属性组成的数组长度
if (Object.keys(obj1).length !== Object.keys(obj2).length) {
return false;
}
for (let attr in obj1) {
let a1 = Object.prototype.toString.call(obj1[attr]) == '[object Object]'
let a2 = Object.prototype.toString.call(obj2[attr]) == '[object Object]'
let arr1 = Object.prototype.toString.call(obj1[attr]) == '[object Array]'
if (a1 && a2) {
// 如果是对象继续判断
return isObjectEqual(obj1[attr], obj2[attr])
} else if (arr1) {
// 如果是对象 判断
if (obj1[attr].toString() != obj2[attr].toString()) {
return false;
}
} else if (obj1[attr] !== obj2[attr]) {
// 不是对象的就判断数值是否相等
return false
}
}
return true
}
数组去重
1.new Set()
let a=[1,2,4,2,3,1,2,2]
let c=new Set(a);
console.log(c);//Set(4) {1, 2, 4, 3}
2. for循环+includes
3.filter 过滤出第一次出现的位置和当前位置相等的元素
arr.filter((item,index)=>{
return arr.indexOf(item)===index
})
var aaa = [1, 2, 4, 5, 3, 2, 1, 1]
var bbb = aaa.filter((item, index) => {
return aaa.findIndex(item2 => item2 === item) === index
})
4.双for+splice
5.新数组+indexOf=-1
知道角度求弧度
(45*Math.PT)/180
float和flex区别
float:当需要兼容IE浏览器时使用float布局,当使用float布局时不需要考虑移动端,因为手机上没有人用IE浏览其
flex布局:当不需要兼容IE浏览器又不需要兼容最新浏览器时可以使用flex布局
userAgent是什么
window.navigator返回一个Navigator对象的引用, 用于请求运行当前代码的应用程序的相关信息.
Navigator对象包含了一些关于浏览器的信息, 具体可以查阅MDN, 这边不做列举.
检测浏览器并返回浏览器名称
const getCurrentBrower = () => {
const ua = navigator.userAgent;
let browser;
if (ua.indexOf("Firefox") > -1) {
browser = "Mozilla Firefox";
} else if (ua.indexOf("Opera") > -1 || ua.indexOf("OPR") > -1) {
browser = "Opera";
} else if (ua.indexOf("Trident") > -1) {
browser = "Microsoft Internet Explorer";
} else if (ua.indexOf("Edge") > -1) {
browser = "Microsoft Edge";
} else if (ua.indexOf("Chrome") > -1) {
browser = "Google Chrome or Chromium";
} else if (ua.indexOf("Safari") > -1) {
browser = "Apple Safari";
} else {
browser = "unknown";
}
return browser;
};
数组随机变化顺序
var arr=[1,2,3,4,5,6,7,8,9]
function Random(arr){
let arrClone=[...arr]
arrClone.forEach((i,index)=>{
let num=Math.floor(Math.random()*arr.length)
let temp=arrClone[index]
arrClone[index]=arrClone[num]
arrClone[num]=temp
})
return arrClone
}
console.log(Random(arr))
判断一个数是否是整数
parseint(num)==num
num%1==0
数组转为树状结构
function baseToTree(data) {
let result = []
if (!Array.isArray(data)) {
return result
}
data.forEach((item) => {
delete item.children
})
let map = {}
data.forEach((item) => {
map[item.id] = item
})
data.forEach((item) => {
let parent = map[item.importButaoPid]
if (parent) {
;(parent.children || (parent.children = [])).push(item)
} else {
result.push(item)
}
})
return result
},
树状转给数组
function baseToArr(data) {
const result = []
data.forEach((item) => {
const loop = (data) => {
result.push(data)
let child = data.children
if (child) {
for (let i = 0; i < child.length; i++) {
loop(child[i])
}
}
}
loop(item)
})
return result
},
判断数组最大值
1.for循环
2.Math.max()
3.Math.max.apply
var arr = [1, 23, 4, 5, 6, 7, 99, 8];
var max1 = Math.max.apply(Math, arr);
console.log('使用数学内置对象求得最大值:' + max1);
路由地址栏路径去掉vue3,2传参
router.push({ query: {} });
v2 element-ui el-input修改不了
v3取消了$ set
使用v-model绑定的时候
请求回来的数据,需要这样赋值 this.$set(this.form, “VRurl”, res.data);
FormData 传递接口数据post
FormData 接口提供了一种表示表单数据的键值对 key/value 的构造方式,并且可以轻松的将数据通过前端Ajax 方法发送出去,本接口和此方法都相当简单直接。如果送出时的编码类型被设为 “multipart/form-data”,它会使用和表单一样的格式。
FormData的主要用途有两个:
1、将form表单元素的name与value进行组合,实现表单数据的序列化,从而减少表单元素的拼接,提高工作效率。
2、异步上传文件
let fromData = new FormData();
fromData.append("newhouseId", this.winData.newhouseId);
fromData.append("commentId", vla.id);
fromData.append("isForce", bool);
let res = await delComment(fromData);
//1.FormData.append()添加
//2.FormData.delete()删除
//3.FormData.get()
//4.FormData.set()
判断对象数组中,对象是否包含某个属性,返回true/false
pkListArr.value.some(
(item) => item.newHouseId == props.dataDetail.newhouseId
)
判断对象数组中,对象的某个属性所在的位置
pkListArr.value.map((x) => x.newHouseId).indexOf(type.newHouseId)
对象,数组中找一个属性使用递归
function recursionGet(setValues, valueId) {
let value = null;
for (let index = 0; index < setValues.length; index += 1) {
if (setValues[index].areaCode === valueId) {
value = setValues[index].mergerName;
break;
}
if (
setValues[index].children instanceof Array &&
setValues[index].children.length > 0
) {
const text = recursionGet(setValues[index].children, valueId);
if (text) return text;
}
}
return value;
}
const data = recursionGet(
this.regionList,
this.areaCodeArray[this.areaCodeArray.length - 1]
);
data是返回的
修改若依vue项目首页加载loading动画
<body>
<div id="app">
<div id="loader-wrapper" class="sunshine">
<div class="imgSunshine" id="loader2">
<img style="width: 100px;height: 100px;" src="<%= BASE_URL %>sunLoading.png" />//图片放在public文件下,路径要这样写
</div>
<div class="load_title" style="color: black;top: 55%; letter-spacing: 10px;">足不出户看好房</div>
</div>
<div id="loader-wrapper" class="other">
<div id="loader"></div>
<div class="loader-section section-left"></div>
<div class="loader-section section-right"></div>
<div class="load_title"> 资源加载中,请稍后...</div>
</div>
</div>
<script>
//判断路由url路径
if (window.location.pathname.indexOf('sunshine') != -1) {
document.querySelector('.sunshine').style.opacity = 1
document.querySelector('.other').style.opacity = 0
} else {
document.querySelector('.sunshine').style.opacity = 0
document.querySelector('.other').style.opacity = 1
}
</script>
</body>
vue-quill-editor 里面内置135/秀米编辑器
问题描述:135编辑器直接点击外网复制,到别的富文本编辑器里面样式丢失
秀米官网声明只支持ueditor内核的编辑器内核(本文使用quill富文本框,自定义了一个blot文件,防止quill自动过滤掉秀米和135编辑器里面的section之类的样式)
原文链接
1.html 可去原文链接里面复制
2.当前页面同级 /blot.js
export default function (Quill) {
// 引入源码中的BlockEmbed
const BlockEmbed = Quill.import('blots/block/embed');
// 定义新的blot类型
class AppPanelEmbed extends BlockEmbed {
static create(value) {
const node = super.create(value);
// node.setAttribute('contenteditable', 'false');
// node.setAttribute('width', '100%');
// 设置自定义html
node.innerHTML = this.transformValue(value)
return node.firstChild;
}
static transformValue(value) {
let handleArr = value.split('\n')
handleArr = handleArr.map(e => e.replace(/^[\s]+/, '')
.replace(/[\s]+$/, ''))
return handleArr.join('')
}
// 返回节点自身的value值 用于撤销操作
static value(node) {
return node.innerHTML
}
}
// blotName
AppPanelEmbed.blotName = 'AppPanelEmbed';
// class名将用于匹配blot名称
AppPanelEmbed.className = 'rich-innerHtml';
// 标签类型自定义
AppPanelEmbed.tagName = 'div';
Quill.register(AppPanelEmbed, true);
}
3.修改index.vue里面的配置,详情看原文链接
4.注意quill的版本
当描述图片加载提示、加载失败提示
<img :src="loadImgSrc" :onload="onLoadImg(testImgSrc)" :onerror="onErrorImg(errorImgSrc)">
data: {
errorImgSrc: "https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1917562744,2542638399&fm=26&gp=0.jpg", //图片加载失败时的图片
testImgSrc: "https://gimg2.baidu.com/image_search/", //要加载的图片,此处链接随便填用作演示图片加载失败的情况
loadImgSrc: "/themes/default/demo/public/assets/images/loadinggif.gif", //加载中要显示的图片
},
methods: {
onLoadImg: function(imgSrc) {
console.log("onload", imgSrc)
return 'this.src='+'"'+imgSrc+'";this.οnlοad=null';
},
onErrorImg: function(imgSrc){
console.log("onload", imgSrc)
return 'this.οnerrοr=null;this.src='+'"'+imgSrc+'";';
},
}
});
前端倒计时(类似于订单支付的倒计时显示),不考虑浏览器失活的情况
和后端商量他那边计算 到期时间戳 - 服务器时间戳 = 服务器待付款时间差,最后把服务器待付款时间差的时间戳返给我
对返回的时间戳进行处理,对应天,时,分
递归的方式使用setTimeOut(),每60s调用runBack方法一次,显示动态时间效果
最后在 实例销毁前清除 setTimeOut() 定时器,防止内存泄漏
<template>
<div class="root">
<div class="time" v-if="resData.status !== 3">
<span>剩余</span>
<span v-if="day != '00'">{{ day }}天</span>
<span>{{ hour }}小时</span>
<span>{{ minute }}分钟</span>
<span>{{ resData.status === 1 ? '自动关闭' : '自动收货' }}</span>
</div>
</div>
</template>
<script>
export default {
data () {
return {
day: '00',
hour: '00',
minute: '00',
timer: 0
}
},
methods: {
getOrderDetail () {
signApi['orderDetail']({
orderSn: this.$route.query.order_sn
})
.then(res => {
if (res.data.code === 200) {
this.resData = res.data.data
let temp = res.data.data
let payDiff = temp.pay_off_time // status=1 表示待支付 服务器待付款时间差
let deliverDiff = temp.delivery_finish_time // status=2 表示待收货 服务器待收货时间差 (只会返回其中一种状态)
if (payDiff) {
this.countdown(payDiff)
} else if (deliverDiff) {
this.countdown(deliverDiff)
}
}
})
.catch(error => {
console.log(error)
})
},
// 倒计时
countdown (diff) {
let diffTime = diff * 1000 // 时间差 s转为ms
this.runBack(diffTime)
},
runBack (diff) {
if (diff > 0) {
let dd = parseInt((diff / 1000 / 60 / 60 / 24) % 1)
let hh = parseInt((diff / 1000 / 60 / 60) % 24)
let mm = parseInt((diff / 1000 / 60) % 60)
this.day = dd > 9 ? dd : '0' + dd
this.hour = hh > 9 ? hh : '0' + hh
this.minute = mm > 9 ? mm : '0' + mm
// 递归的方式使用setTimeOut(),相当于setInterval(),显示动态时间效果
// setTimeOut()方法会返回一个数值ID,便于清除定时器时使用
this.timer = setTimeout(() => {
diff -= 60000
this.runBack(diff)
}, 60000)
} else {
// 订单已过期
this.day = '00'
this.hour = '00'
this.minute = '00'
}
}
},
mounted () {
this.getOrderDetail()
},
// 销毁前清除定时器,防止内存泄漏
beforeDestroy () {
clearTimeout(this.timer)
}
}
</script>
<style></style>
Vue 中 input 输入框被赋值后,无法再修改和编辑
Vue 在实例创建之后添加新的属性到实例上,它不会触发视图更新。
用$set