赞
踩
/* 垂直居中方式 */ .aaaaa { /* 直接定位 */ position: absolute; // 子绝父相 top: 45px; left: 45px; margin: 0 auto; // 块级 top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; // 文本居中 vertical-align: middle; // 图片 display: flex; // 自由布局 justify-content: center; align-items: center; height: 100px; // 行高等于实际高度 line-height: 100px; }
/* css3盒子,不需要手动计算盒子尺寸||内减模式 */
box-sizing: border-box;
.grid-item { width: 33.3%; height: 200rpx; display: flex; flex-direction: column; /* 竖向排列 */ align-items: center; /*水平居中 */ justify-content: center; /* 垂直居中 */ border-right: 1rpx solid #efefef; border-bottom: 1rpx solid #efefef; box-sizing: border-box; /* 内减模式 */ } .img-box { display: flex; padding: 20rpx 10rpx; justify-content: space-around; /* 四周平均留空 */ }
/* 清除float影响 1.尾部额外标签,添加块元素的css样式clear:both 2.单伪元素清除法 .clearfix::after{ content:''; display:blok; clear:both; //低版本浏览器添加 height:0; visibility:hidden; } 3.双伪元素解决塌陷法 .clearfix::before, .clearfix::after{ content:''; display:table; } //真正清除浮动部分 .clearfix::after{ clear:both; } 4.父元素添加overflow:hidden; */
适用于input标签和普通标签文本内容超出部分省略号显示。
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
overflow属性的使用:
特点:必须给块级容器指定高度,或者使用不换行属性让内容变宽
属性值:
white-space属性的使用 :处理元素中的空白
属性值:常用
text-overflow属性的使用:
特点:该属性不会强制发生溢出,要是文本溢出其容器,必须设置overflow和white-space
属性值:
三角形原理:边框的均分原理
通过设置 border 的 top、left、right、bottom 属性实现,transparent 表示透明色
.box1 { width: 0; height: 0; border-top: 100px solid red; border-left: 100px solid blue; border-right: 100px solid green; border-bottom: 100px solid yellow; } .box2 { width: 0; height: 0; /* transparent 透明色 */ border-top: 200px solid transparent; border-left: 0px solid blue; border-right: 100px solid green; border-bottom: 0 solid yellow; } .box3 { width: 0; height: 0; border-color: transparent green transparent transparent; border-style: solid; border-width: 200px 100px 0 0; }
特别:
cookie 数据存放在客户的浏览器上,session 数据放在服务器上;
cookie 不安全,可能被别人分析欺骗
① 传递方式不同
cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。
sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
② 数据大小不同
Cookie 4KB、sessionStorage 约 5M、localStorage 约 20M
③ 数据有效期不同
sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;
localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;
cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。
④ 作用域(生命周期)不同
sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;
localStorage 在所有同源窗口中都是共享的;
cookie也是在所有同源窗口中都是共享的。
iframe 元素会创建包含另一个文档的内联框架。
优点:
缺点:
搜索引擎无法解读这种页面,不利于 SEO
iframe 和主页面共享连接池,而浏览器对相同区域有限制所以会影响性能。
HTML 语义化标签是指正确的标签包含了正确的内容,结构良好,便于阅读,比如 nav 表示导航条,类似的还有 article、header、footer 等等标签。
web标准:web标准主要分为结构、表现、行为3部分,
结构:指我们平时在body里面写的标签,主要是由HTML标签组成
表现:指更加丰富HTML标签样式,主要由CSS样式组成,
行为:指页面和用户的交互,主要由JS部分组成
W3C:W3C对web标准提出了规范化的要求,即代码规范对结构的要求1、标签字母要小写2、标签要闭合3、标签不允许随意嵌套
对表现和行为的要求1、建议使用外链CSS和js脚本,实现结构与表现分离、结构与行为分离,
能提高页面的渲染效率,更快地显示网页内容
回流:当一个元素自身的宽高,布局,显示或隐藏,或元素内部的文字结构发生变化
,导致需要重新构建页面的时候,就产生了回流复制
重绘:当一个元素自身的宽高,布局,及显示或隐藏没有改变,
而只是改变了元素的外观风格的时候,就产生了重绘
① 标准流(标签自带布局)
② 浮动(float)
③ 定位(position)
层级关系
标准流<浮动<定位(默认情况,定位的盒子,后来者居上;z-index:整数;取值越大,显示顺序越在上;默认为0,必须配合定位。)
1. 防抖(debounce):
防抖触发高频率事件时n秒后只会执行一次,如果n秒内再次触发,则会重新计算。
简单概括:每次触发时都会取消之前的延时调用。(将多次执行变为最后一次执行)
2. 节流(thorttle):
高频事件触发,每次触发事件时设置一个延迟调用方法,并且取消之前延时
调用的方法。
简单概括:每次触发事件时都会判断是否等待执行的延时函数。(将多次连续的执行变成每隔一段时间执行)
区别:
降低回调执行频率,节省计算资源。
防抖和节流本质是不一样的。防抖是将多次执行变为最后一次执行,节流是将
多次执行变成每隔一段事件执行
函数防抖一定连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行
一次。
通过 typeof 和 instanceof
typeof 可以用来区分除了 Null 类型(可以用全等===
判断)以外的原始数据类型
instanceof 不能用于判断原始数据类型的数据
var、let 区别:
1.使用var声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象;
2.使用let声明的变量,其作用域为该语句所在的代码块内,不存在变量提升;
3.let不允许在相同作用域内,重复声明同一个变量
const
(1) const是设置常量,也就是不能改变。const定义的数值字符串的时候值不能改变。
(2) const 定义的对象的时候,对象不能改变,但是对象的属性值可以改变。
var | let | const |
---|---|---|
只有全局作用域和函数作用域 | 有块级作用域 | 有块级作用域 |
存在变量提升 | 不存在变量提升 | 不存在变量提升 |
可以重复声明 | 不能重复声明 | 不能重复声明 |
没有死区 | 存在暂时性死区 | 存在暂时性死区 |
可以先声明后赋值 | 可以先声明 后赋值 | 声明即赋值 |
变量提升
简单说就是在 JavaScript 代码执行前引擎会先进行预编译,预编译期间会将变量声明与函数声明提 升至其对应作用域的最顶端,函数内声明的变量只会提升至该函数作用域最顶层。当函数内部定义的一个变量与外部相同时,那么函数体内的这个变量就会被升到最顶端
函数提升
函数提升只会提升函数声明式写法,函数表达式的写法不存在函数提升
函数提升的优先级大于变量提升的优先级,即函数提升在变量提升之上
概念:代码(变量)可以使用的范围就是作用域。主要是为了提高程序的可靠性,也是为了减少命名冲突
全局作用域和局部作用域
全局作用域:指的是整个js文件,定义在全局中的全局变量,可以在局部作用域中使用,函数内部没有声明直接赋值的变量也叫全局变量
局部作用域:主要指的是函数作用域,函数内部也就是局部作用域
在函数内部var定义的变量-,叫做局部变量,局部变量无法被外部获取
概念:当我们点击子元素触发父元素的事件,这种现象,我们叫做事件冒泡,即由子元素向祖先元素传播,就像气泡从水底上浮
event.stopPropagation();阻止事件冒泡
通俗的讲,子代有事,让父级执行,当我们点击li时,子元素会通过事件的冒泡来触发父元素的事件,主要是通过事件冒泡
原理: 不要给每个子节点单独设置事件监听器,而是事件监听设置在其父节点上,然后利用冒泡原理影响设置每个子节点
闭包就是能够读取其他函数内部变量的函数
闭包基本上就是一个函数内部返回一个函数
特点:
函数嵌套函数
内部函数可以访问外部变量
参数和变量不会被回收(回收牵扯出全局变量和局部变量,因为全局变量在页面关闭后销毁,比较占内存资源。局部变量在函数执行完毕后销毁,闭包保护局部变量不会在函数执行完被回收也就是销毁)
浅拷贝:基本数据类型拷贝的是值,引用数据类型拷贝的是地址
深拷贝:引用数据类型拷贝的是开辟新地址中的值
① JS 中可以使用 node.cloneNode()
复制;参数为空或者false,浅拷贝,只复制标签不复制内容;可以添加true,深复制
② JQuery 中可以使用 $.extend([deep], target, object, [objectN])
,把 deep 参数设为 true
③ json暴力转化
对象和字符串的相转化
var a = JSON.stringify(one);//先转字符串再转对象
var b = JSON.parse(a);
封装开辟新地址的函数
function deepCopy(obj){
var objs = JSON.stringify(obj);
var newObj = JSON.parse(objs);
return newObj;
}
这种简单粗暴的方式有局限性,当值为undefined、function、symbol会在转换过程中被忽略。
④ ES6 新语法扩展运算符
var obj = {name:'123',age:13};
var obj2 = {...obj}
只能深度拷贝对象的第一层,如果对象中的属性也是对象的话,没有办法进行深度拷贝的。
⑤ for in 循环遍历对象
var obj = {
name: "小明",
age: 20
}
var obj1 = {}
for (var key in obj) {
//遍历属性值,深拷贝
obj1[key] = obj[key]
}
console.log(obj1);
同样的,只能深度拷贝对象的第一层,如果对象中的属性也是对象的话,没有办法进行深度拷贝的。
⑥ Object.assign() 对象的合并
利用Object.assign(), 第一个参数必须是空对象
var obj = {name:'123',age:13};
var obj2 = Object.assign({},obj1);
只能深度拷贝对象的第一层,如果对象中的属性也是对象的话,没有办法进行深度拷贝的。
⑦ 利用循环和递归的方式
function deepClone(obj, newObj) {
var newObj = newObj || {};
for (let key in obj) {
if (typeof obj[key] == 'object') {
newObj[key] = (obj[key].constructor === Array) ? [] : {}
deepClone(obj[key], newObj[key]);
} else {
newObj[key] = obj[key]
}
}
return newObj;
}
在循环递归中需要注意设置临界值(typeof obj[key] == ‘object’),否则会造成死循环。
循环递归可以处理对象中嵌套数组或对象的问题。相当于第三种方法的优化。
含义:垃圾回收器会每隔一段时间找出那些不再使用的内存,然后为其释放内存
一般使用标记清除方法(mark and sweep), 当变量进入环境标记为进入环境,离开环境标记为离开环境
垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了
还有引用计数方法(reference counting), 在低版本IE中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个 变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变为0的时 候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。
在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,但BOM与DOM对象却是通过引用计数回收垃圾的, 也就是说只要涉及BOM及DOM就会出现循环引用问题。
概念: 同源策略是客户端脚本(尤其是Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。
这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。
指一段脚本只能读取来自同一来源的窗口和文档的属性。
定义:程序中己动态分配的堆内存由于某种原因程序未释放或无法释放引发的各种问题。
js中可能出现的内存泄漏情况:结果:变慢,崩溃,延迟大等
js中可能出现的内存泄漏原因:
JavaScript 单线程语言
问题:前一个任务耗时,程序假死
① 同步任务(synchronous)
② 异步任务 (asynchronous)
① 宏任务(macrotask)
② 微任务 (microtask)
降低请求量:合并资源,减少 HTTP 请求数,minify / gzip 压缩,webP,lazyLoad。
加快请求速度:预解析 DNS,减少域名数,并行加载,CDN 分发。
缓存:HTTP 协议缓存请求,离线缓存 manifest,离线数据缓存 localStorage。
渲染:JS/CSS 优化,加载顺序,服务端渲染,pipeline。
确保组件间数据相互不被影响,防止变量污染
1、含义
computed:计算属性,并且有缓存,只有她所依赖的属性值发生变化computed才会重新计算,并且支持同步
watch:监听器,不支持缓存(可以在data中直接使用),监听的数据发生变化才会触发,watch支持异步,监听的函数可以接收两个参数,一个是最新的值,另一个是改变之前的值
2、特点
计算属性 computed :
支持缓存,只有依赖数据发生改变,才会重新进行计算
不支持异步,当computed内有异步操作时无效,无法监听数据的变化
侦听属性watch:
3、使用场景
computed
watch
handle()
deep:true; immediate:truev-if:是真正的条件渲染,同时他也是惰性的,如果在初始渲染时条件为假,则什么也不做,直到第一次变为真时,才会开始渲染,条件切换过程会发生销毁和重建,动态创建和删除元素
具有更高的切换开销,如果在运行是条件很少改变,使用v-if比较好
v-show:不管初始条件是什么,元素总是会被选二胺,并且知识简单的基于css(display:none/block)进行切换
具有更高的初始开销,如果切换非常频繁,则使用v-show比较好
概念:vue实例从创建到销毁的过程就是生命周期,也就是从开始创建,出啊石化数据,编译模板,挂载dom->渲染,更新->渲染,卸载等一系列过程
beforeCreate():vue实例创建之前调用
created():vue实例创建完成
beforeMount():视图编译之前
mounted():视图编译完成,vuedom加载之后
beforeUpdate():数据改变之前
updated():数据改变之后
beforeDestory():vue2销毁之前 || beforeUnmount():vue3销毁之前
destory():vue2销毁之后 || Unmounted():vue3销毁之后
特别的:
keep-alive 对应的生命周期函数
被缓存:deactivated
被激活:activated
父组件向子组件传递数据
:(v-bind)
一个自定义属性并把数据绑定在自定义属性上,在子组件添加props
接收即可(自定义属性)子组件向父组件传递数据
$emit
进行触发并且可以携带参数,父组件监听使用@(v-on)
绑定的事件进行监听,然后方法处理(自定义方法)兄弟组件之间传递数据
引入第三方 new vue 定义为 eventBus
在组件中 created 中订阅方法 eventBus.$on(“自定义事件名”,methods 中的方法名)
在另一个兄弟组件中的 methods 中写函数,在函数中发布 eventBus 订阅的方法
eventBus.$emit("自定义事件名”)
在组件的 template 中绑定事件(比如 click)
祖孙之间的传值
provide
定义的对象会加载到子组件或者孙子组件中
inject
接收祖先组件中provide函数return出的内容
父子之间的双向数组同步
<button @click="count++">+1</button> APP-----count: {{count}} <MyCounter v-model:number="count"></MyCounter> ---------------------------------------------- <template> <div> <p>count 值:{{ number }}</p> <button @click="add">+1</button> </div> </template> <script> export default { name: 'MyCounter', props: ['number'], emits: ['update:number'], methods: { add() { this.$emit('update:number', this.number + 1) } }, } </script>
可以通过 vuex 传值
可以使用本地存储进行传值(cookie、localstorge、sessionStorage)
修饰符 | 作用 |
---|---|
.stop | 等同于js中event.stopPropagation(),防止事件冒泡 |
.prevent | 等同于js中event.preventDefault(),阻止默认行为 |
.capture | 当元素发生冒泡时,先触发带有修饰符的元素,若有多个修饰符,则由内而外触发。如 div1中嵌套div2中嵌套div3.capture中嵌套div4,那么执行顺序为:div3=》div4=》div2=》div1 |
.slef | 只触发自己范围内的事件,不包含子元素 |
.once | 只触发一次 |
.lazy | 延迟执行,一般用于表单输入框 |
.trim | 自动去除首位空格 |
.number | 自动转化为数值类型 |
当你修改了data的值然后马上获取这个dom元素的值,是不能获取到更新后的值,你需要使用$nextTick这个回调,让修改后的data值渲染更新到dom元素之后在获取,才能成功。
在使用某个第三方插件时,希望在vue生成的某些DOM动态发生变化时重新应用该插件,也会用到该方法,这时候就需要$nextTick的回调函数中执行重新应用插件的方法,例如:应用滚动插件better-scroll时
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。
(1)Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
(2)改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。
主要包括以下几个模块:
import { mapGetters } from 'vuex' // 导入
computed: { // 计算属性
...mapGetters([
'属性名'
])
}
this.$store.commit('set属性名', 属性值) // 设置
// 直接调用
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染 ,其有以下特性:
需要做 vuex 数据持久化,一般使用本地储存的方案来保存数据,可以自己设计存储方案,也可以使用第三方插件。
推荐使用 vuex-persist 插件,它是为 Vuex 持久化储存而生的一个插件。不需要你手动存取 storage,
而是直接将状态保存至 cookie 或者 localStorage中。
1、工厂模式 - 传入参数即可创建实例
虚拟 DOM 根据参数的不同返回基础标签的 Vnode 和组件 Vnode。
2、单例模式 - 整个程序有且仅有一个实例
vuex 和 vue-router 的插件注册方法 install 判断如果系统存在实例就直接返回掉。
3、发布-订阅模式。(vue 事件机制)
4、观察者模式。(响应式数据原理)
5、装饰器模式(@装饰器的用法)
6、策略模式,策略模式指对象有某个行为,但是在不同的场景中,
该行为有不同的实现方案 - 比如选项的合并策略。
1、vue异步组件实现路由懒加载
component:resolve=>(['需要加载的路由的地址',resolve])
2、es提出的import(推荐使用这种方式)
const HelloWorld = ()=>import('需要加载的模块地址')
在开发中,可能会遇到这样的情况。有些资源不需要马上用到,但是希望尽早获取,这时候就可以使用预加载。
预加载其实是声明式的 fetch ,强制浏览器请求资源,并且不会阻塞 onload 事件,可以使用以下代码开启预加载
link rel=“preload” href=“http://example.com”
预加载可以一定程度上降低首屏的加载时间,因为可以将一些不影响首屏但重要的文件延后加载,唯一缺点就是兼容性不好。
DNS 解析也是需要时间的,可以通过预解析的方式来预先获得域名所对应的 IP。
在https协议中默认a标签不会开启预解析,因此需要手动设置meta懒执行就是将某些逻辑延迟到使用时再计算。
该技术可以用于首屏优化,对于某些耗时逻辑并不需要在首屏就使用的,
就可以使用懒执行。懒执行需要唤醒,一般可以通过定时器或者事件的调用来唤醒。
懒加载就是将不关键的资源延后加载。懒加载的原理就是只加载自定义区域(通常是可视区域,
但也可以是即将进入可视区域)内需要加载的东西。对于图片来说,
先设置图片标签的 src 属性为一张占位图,
将真实的图片资源放入一个自定义属性中,当进入自定义区域时,
就将自定义属性替换为 src 属性,这样图片就会去下载资源,实现了图片懒加载。懒加载不仅可以用于图片
//数组去重['x', 's', 'a', 's', 'g', 'a', 'h', 'm', 'd', 'l'] //1、目标:把旧数组中里面不重复的元素取出来放到新数组里,重复元素只保留一个,放到新数组里去重 //2、核心算法:遍历旧数组,拿旧数组元素去查新数组,如果该元素在新数组里没有出现过就添加,否则不添加 //3、利用 新数组.indexOf(数组元素) 如果返回是-1就说明新数组没有该元素,那就添加上 //封装一个 去重函数 unique function unique(arr) { var newArr = []; for (var i = 0; i < arr.length; i++) { if (newArr.indexOf(arr[i]) === -1) { newArr.push(arr[i]) } } return newArr; } console.log(['x', 's', 'a', 's', 'g', 'a', 'h', 'm', 'd', 'l']); console.log(unique(['x', 's', 'a', 's', 'g', 'a', 'h', 'm', 'd', 'l']));
// 查找字符串'ascascasdsacsfea'中所有a出现的位置以及次数
// 核心算法:先查找第一个a出现的位置
// 然后,只要indexOf返回的结果不是-1,就继续往后查找
// 因为indexOf只能查找到第一个元素,所以后边的查找,一定是当前索引加1,从而继续查找
var str = 'ascascasdsacsfea';
var index = str.indexOf('a');
var num = 0;
while (index !== -1) {
num++;
addr = index + 1;
console.log('第' + num + '个的位置是:' + addr);
index = str.indexOf('a', index + 1);
}
console.log('a出现的次数是:' + num);
tocbot.js(目录生成)
waypoints.js(平滑滚动)
swiper.js(轮播图)
qrcode.js(生成二维码)
Day.js(时间日期处理)
lodash.js(鲁大师,高效处理array、number、objects、string等对象,降低JS操作难度)
zplayer.js(音乐)
gallery.js(画廊,图片管理)
distance.js(实现计算两点经纬度之间的距离)
Dropzone.js(文件拖拽上传)
zy.media.js (视频管理)
1、相同点
(1) 都是循环遍历数组中的每一项。
(2) 每次执行匿名函数都支持三个参数,参数分别为item(当前每一项),index(索引值),arr(原数组)。
(3) 匿名函数中的this都是指向window。
(4) 只能遍历数组。
2、不同点
(1) map()会分配内存空间存储新数组并返回,forEach()不会返回数据。
(2) forEach()允许callback更改原始数组的元素。map()返回新的数组
双向数据绑定原理不同;
是否支持碎片;
API类型不同;
定义数据变量和方法不同;
生命周期钩子函数不同;
父子传参不同;
指令与插槽不同;
main.js文件不同。
// 树状结构数据 const data = [ { id: 1, pid: null, title: '研发部', children: [ { id: 5, title: '前端研发部', pid: 1 }, { id: 6, title: '后端研发部', pid: 1 }, { id: 7, title: '算法研发部', pid: 1 }, ], }, { id: 2, pid: null, title: '开发部', children: [ { id: 8, title: '前端开发部', pid: 2 }, { id: 9, title: '后端开发部', pid: 2 }, { id: 10, title: '算法开发部', pid: 2 }, ], }, { id: 3, title: '市场部', pid: null }, { id: 4, title: '销售部', pid: null }, ]; // 方法一 function treeToArray1(array) { const result = []; array.forEach((item) => { if (item.children) { // 得到push进去最后一位成员的位置 从1开始,同时直接返回数组长度index let index = result.push(item, ...item.children); // 删除children属性 delete result[index - item.children.length - 1].children; } else { result.push(item); } }); return result; } // 方法二 function treeToArray2(array) { return array.reduce((prev, cur) => { if (cur.children) { // 删除chidren项 因为push得到的是push进去的成员在第几个位置 从1开始 因此要减1 delete prev[prev.push(cur, ...cur.children) - cur.children.length - 1].children; } else { prev.push(cur); } return prev; }, []); } // 数组结果数据 const data = [ { id: 1, title: '研发部', pid: null, }, { id: 2, title: '开发部', pid: null, }, { id: 3, title: '市场部', pid: null, }, { id: 4, title: '销售部', pid: null, }, { id: 5, title: '前端研发部', pid: 1, }, { id: 6, title: '后端研发部', pid: 1, }, { id: 7, title: '算法研发部', pid: 1, }, { id: 8, title: '前端开发部', pid: 2, }, { id: 9, title: '后端开发部', pid: 2, }, { id: 10, title: '算法开发部', pid: 2, }, ];
比如,将以下二维数组:
const arr = [
["a", "aa", "aaa", "aaaa"],
["b", "bb", "bbb"],
["a", "ab", "aba"],
["a", "aa", "aab"]
]
转为树结构的对象数组:
[{ "name" : "a", "child" : [ { "name" : "aa", "child" : [ { "name" : "aaa", "child" : [ { "name" : "aaaa", "child" : [] } ] }, { "name" : "aab", "child" : [] } ] }, { "name" : "ab", "child" : [ { "name": "aba", "child" : [] } ] } ] }, { "name": "b", "child" : [ { "name" : "bb", "child" : [ { "name" : "bbb", "child" : [] } ] } ] }]
实现思路基本是将一维数组转为链表,再进行合并去重。算法如下:
// 实现思路基本是将一维数组转为链表,再进行合并去重。算法如下: function arr2List(arr) { const list = []; const head = { name: arr[0], child: [], }; let prev = head; list.push(prev); for (let i = 1; i < arr.length; i++) { const current = { name: arr[i], child: [], }; // 将当前节点挂载到链表尾节点上 prev.child.push(current); prev = current; } // 返回链表头节点, 已经挂载了所有节点 return list; } function mergeList(tree, list) { // 递归终止条件,因为可能有多个链表头节点挂载到树上 if (!tree) { return; } // 遍历树,查找是否有共同的父节点 const hasCommonParent = tree.some(treeItem => { // 有共同的父节点 if (treeItem.name === list[0].name) { // 将链表头节点挂载到树上 mergeList(treeItem.child, list[0].child); // 确保链表头节点的子节点不会丢失 // 递归终止条件 return true; } // 递归继续 return false; }) // 没有共同的父节点,将链表头节点挂载到树上 if (!tree.length || !hasCommonParent) { tree.push(list[0]); } } function arr2Tree(arr) { const tree = []; // 遍历二维数组,将每个一维数组转为链表,再将链表合并到树中 arr.forEach((item) => { const list = arr2List(item); mergeList(tree, list); }); return tree; } const arr = [ ['a', 'aa', 'aaa', 'aaaa'], ['b', 'bb', 'bbb'], ['a', 'ab', 'aba'], ['a', 'aa', 'aab'], ['b', 'ba', 'aabb'], ['b', 'ba', 'aabbaa'], ]; arr2Tree(arr);
Date() : Date()日期对象 是一个构造函数,必须用new来调用;
无参数时 为当前时间;
字符串格式 ‘2023-4-9 12:48:12’;
数字格式 2023, 4, 9 返回的是5月;
//Date()日期对象 是一个构造函数,必须用new来调用 var date1 = new Date(); var date2 = new Date('2023-4-9 12:48:12'); var date3 = new Date(2023, 4, 9); console.log(date1); //返回当前时间 console.log(date2); //正常 console.log(date3); //返回的是5月,不是4月 var date4 = new Date(); console.log(date4.getFullYear()); //返回当前年份 console.log(date4.getMonth() + 1); //返回当前月份,返回月份默认从0开始,记得加1 console.log(date4.getDate()); //返回当前几号 console.log(date4.getDay()); //返回当前星期,从 星期日到星期六 依次是 0,1,2,3,4,5,6 console.log(date4.getHours()); //时 console.log(date4.getMinutes()); //分 console.log(date4.getSeconds()); //秒 var year = date4.getFullYear(); var month = date4.getMonth() + 1; //加1 var dates = date4.getDate(); var arr = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六']; var day = date4.getDay(); console.log('当前日期是:' + year + '年' + month + '月' + dates + '日 ' + arr[day]); function getTime() { var time = new Date(); var h = time.getHours(); //时 h = h < 10 ? '0' + h : h; //小于10,前边补0 var m = time.getMinutes(); //分 m = m < 10 ? '0' + m : m; //小于10,前边补0 var s = time.getSeconds(); //秒 s = s < 10 ? '0' + s : s; //小于10,前边补0 return h + '时' + m + '分' + s + '秒'; } console.log(getTime()); //00时00分00秒
时间戳(总的毫秒数)
//获取总的毫秒数(时间戳),距离1970年1月1日过了多少毫秒
//1、通过valueOf() 或者 getTime() 获取
var date5 = new Date();
console.log(date5.valueOf());
console.log(date5.getTime());
//2、简单写法(常用)
var date6 = +new Date();
console.log(date6);
//3、H5新增的方法
console.log(Date.now());
倒计时
//1、核心算法:输入的时间减去现在的时间就是剩余时间,即倒计时,但是不能拿着时分秒直接相减 //2、用时间戳来做,用户输入的时间的总毫秒数减去现在时间的总毫秒数,得到剩余时间的总毫秒数 //3、把剩余时间总毫秒数转化为天、时、分、秒(时间戳转化为时分秒) //转化公式如下: // d = parseInt(总秒数/ 60/60 /24); //计算天数 // h = parseInt(总秒数/ 60/60 %24); //计算小时 // m = parseInt(总秒数/ 60 % 60); //计算分数 // s = parseInt(总秒数 %60); //计算当前秒数 function countDown(time) { var nowTime = +new Date(); //当前时间的总毫秒数 var inputTime = +new Date(time); //用户输入时间的总毫秒数 var times = (inputTime - nowTime) / 1000; //剩余时间总秒数 var d = parseInt(times / 60 / 60 / 24); //计算天数 d = d < 10 ? '0' + d : d; var h = parseInt(times/ 60 / 60 % 24); //计算小时 h = h < 10 ? '0' + h : h; var m = parseInt(times/ 60 % 60); //计算分数 m = m < 10 ? '0' + m : m; var s = parseInt(times % 60); //计算当前秒数 s = s < 10 ? '0' + s : s; return d + '天' + h + '时' + m +'分' + s + '秒'; } console.log(countDown('2023-4-11 18:00:00')); var date = new Date(); console.log(date);
//数组去重['x', 's', 'a', 's', 'g', 'a', 'h', 'm', 'd', 'l'] //1、目标:把旧数组中里面不重复的元素取出来放到新数组里,重复元素只保留一个,放到新数组里去重 //2、核心算法:遍历旧数组,拿旧数组元素去查新数组,如果该元素在新数组里没有出现过就添加,否则不添加 //3、利用 新数组.indexOf(数组元素) 如果返回是-1就说明新数组没有该元素,那就添加上 //封装一个 去重函数 unique function unique(arr) { var newArr = []; for (var i = 0; i < arr.length; i++) { if (newArr.indexOf(arr[i]) === -1) { newArr.push(arr[i]) } } return newArr; } console.log(['x', 's', 'a', 's', 'g', 'a', 'h', 'm', 'd', 'l']); console.log(unique(['x', 's', 'a', 's', 'g', 'a', 'h', 'm', 'd', 'l']));
css 盒模型(Box Model),在html中任何一个元素都可以看作盒子,这里说的盒子与现实不太一样,css中盒子是二维的,盒子由内到外分四个部分:margin(外边距)、border(边框)、padding(内边距)、content(内容)。css通过margin、border、padding三个属性来控制盒子,content是html元素的内容。
1、link属于html标签,而@import是css提供的,只能加载CSS
2、加载顺序,link在页面加载时被加载,@import在页面加载完之后再加载
3、link是html标签,因此没有兼容性,而@import只有IE5以上才能识别
4、link是可以通过 JS 操作 DOM ,插入link标签来改变样式;由于 DOM 方法是基于文档的,无法使用@import
创建仓库:1.创建一个仓库,git init 2.git clone一个远程仓库
git日常工作流程:1.git pull拉取最新的代码 2.git add将修改的代码文件提交到暂存区 3.git commit -m 将暂存区的代码提交到本地仓 4.git push将代码推送到远程仓
分支相关的命令:git branch 查看分支,git checkout分支名 切换分支,git checkout -b分支名 新建并切换到新的分支,git merge合并分支,其实合并分支还有另一种,是git rebase,但是很少去用,这两个的区别就是merge保留了完整的历史记录,它是将当前的commit和公共分支合并在一起,形成一个新的commit,rebase不会保留完整的历史记录 ,它是将当前分支的commit放到公共分支的最后面,形成一条新的分支
在 Web 前端开发中,浏览器兼容性问题是一个常见的挑战。由于不同的浏览器实现了不同的标准和规范,因此相同的代码在不同的浏览器上可能会有不同的表现,或者甚至无法正常工作。
常见的浏览器兼容性问题包括以下几点:
CSS 盒模型问题:不同浏览器对盒模型的解释可能不一致,导致页面布局不同。解决方法是在 CSS 中明确指定盒模型的属性。(内减模式)
CSS 属性兼容性问题:某些 CSS 属性在不同浏览器中表现不一致,如某些浏览器不支持某些属性或值,解决方法是使用 CSS hack 或兼容性前缀。
JavaScript 兼容性问题:不同浏览器对 JavaScript 的解释也可能不一致,如一些浏览器不支持某些 DOM 方法或事件。解决方法是使用浏览器检测和兼容性处理。
HTML 兼容性问题:不同浏览器对 HTML 标签和属性的解释也可能不一致,如一些浏览器对一些 HTML5 标签和属性支持不完全。解决方法是使用 polyfill 或兼容性库。
图片加载问题:不同浏览器对图片加载的处理也可能不同,如某些浏览器在加载图片时可能会阻塞其他资源的加载。解决方法是使用图片懒加载或使用适当的图片格式。
响应式布局问题:不同浏览器在解释媒体查询时可能存在差异,导致响应式布局不同。解决方法是在编写媒体查询时尽可能明确和具体,避免使用模糊的描述词汇。
跨域访问问题:由于安全限制,浏览器禁止从一个域名的网页中直接访问另一个域名的资源。解决方法是使用 CORS(跨域资源共享)或 JSONP(JSON with Padding)等技术。
表单元素的兼容性问题:不同浏览器对表单元素的默认样式和行为可能存在差异,如某些浏览器对某些表单元素的样式可能不支持修改。解决方法是使用自定义的样式或 JavaScript 代码对表单元素进行处理。
CSS 动画效果兼容性问题:某些浏览器对 CSS3 动画效果的支持不完全或不一致,解决方法是使用 JavaScript 实现动画效果,或使用 CSS hack 或兼容性前缀。
字体兼容性问题:不同浏览器在对字体的解释和渲染上也可能存在差异,解决方法是使用 Web 字体或使用适当的字体格式。
针对以上兼容性问题,前端开发者需要在开发过程中注意不同浏览器的差异性,并采用相应的解决方法来保证页面在各种浏览器中能够正确地展示和运行,例如使用 polyfill 库、CSS hack、媒体查询、特定的前缀等。同时,可以使用一些兼容性检测工具来帮助开发者发现和解决兼容性问题。
Can I Use: https://caniuse.com/ 是一个免费的 Web 工具,提供了各种前端技术在各种浏览器和平台中的支持情况,包括 HTML5、CSS3、JavaScript 等。
BrowserStack: https://www.browserstack.com/ 是一个基于云端的跨浏览器测试工具,可以模拟各种浏览器和操作系统,帮助开发者发现和解决兼容性问题。
CrossBrowserTesting: https://crossbrowsertesting.com/ 是另一个基于云端的跨浏览器测试工具,可以模拟各种浏览器和操作系统,并提供自动化测试和调试工具。
Modernizr: https://modernizr.com/ 是一个 JavaScript 库,用于检测浏览器对 HTML5 和 CSS3 特性的支持情况,开发者可以根据检测结果进行相应的兼容性处理。
HTML5 Boilerplate: https://html5boilerplate.com/ 是一个针对 HTML5 开发的模板和工具集合,包括一些兼容性处理和优化技术。
W3C 标准测试工具: https://validator.w3.org/ 和 https://jigsaw.w3.org/css-validator/ 是 W3C 提供的 HTML 和 CSS 标准测试工具,开发者可以使用这些工具来检测代码的规范性和兼容性。
LambdaTest: https://www.lambdatest.com/ 是一个跨浏览器测试工具,提供云端虚拟机和实时测试功能,可以模拟各种浏览器和操作系统,并支持自动化测试和调试工具。
Browsershots: https://browsershots.org/ 是一个免费的在线截图工具,可以在不同的浏览器和操作系统上生成网站截图,用于检测网站在不同浏览器上的表现。
IE NetRenderer: http://www.netrenderer.com/ 是一个免费的在线工具,可以在不同的 IE 版本中预览网站的效果,用于检测和调试网站在 IE 浏览器上的兼容性问题。
Sauce Labs: https://saucelabs.com/ 是一个基于云端的测试平台,提供跨浏览器和跨平台测试功能,支持各种桌面和移动浏览器,并提供自动化测试和调试工具。
Browserling: https://www.browserling.com/ 是一个在线测试工具,可以在各种浏览器和操作系统上测试网站的兼容性,支持自动化测试和调试工具。
这些工具都可以帮助开发者检测和解决网站在不同浏览器和操作系统上的兼容性问题,从而提高网站的可访问性和用户体验。开发者可以根据自己的需求选择合适的工具来进行兼容性测试和调试。
答:
prop用于定义外部接口,state用于记录内部状态。
prop的赋值在外部使用组件时,state的赋值在组建内部。
组件不应该改变prop的值,但是state的存在目的是让组件来改变。
资料:https://segmentfault.com/a/1190000013040438?utm_source=tag-newest
父组件向子组件传值(通过props)
子传父(回调函数)
跨级组件传值
没有嵌套关系的组件通信
参考:https://www.cnblogs.com/dhcn/p/11125448.html
可以直接改为本地存储,sessionstorage等。
资料:https://www.cnblogs.com/goloving/p/9074574.html
cmd规范推崇依赖就近,amd规范推崇依赖前置。
对依赖模块amd是提前执行,cmd是延迟执行。
服务器端渲染ssr,预渲染。
预渲染指的是在服务器端生成静态 HTML。在用户访问 SPA 应用之前,服务器可使用 headless 浏览器进行渲染,并生成 HTML 网页,该网页将包含静态的内容和必要的元数据。搜索引擎可以抓取和索引这些预渲染的网页,而用户在访问 SPA 应用时,JavaScript 代码会接管交互过程。
友情链接,关键字,网站功能多时可以设置网站导航地图。
一种是设置超时时间让ajax自动断开,
另一种为手动去停止ajax请求,其核心是调用XMLHttpRequest对象上的abort方法
资料:https://blog.csdn.net/qq_27674439/article/details/99821474
字面量方式
构造函数
资料:https://www.cnblogs.com/topsyuan/p/11260399.html
用原生的方法监听对象的变化?如对象有个name属性,如果改变为张三就alert张三,如果改变为李四就alert李四?
重绘:当更新render tree中某个元素属性时,而这些属性只是影响元素外观风格,不影响布局,称为重绘。
回流:当render tree的一部分因为元素规模尺寸,布局,隐藏等改变需要重新构建时,称为回流。当页面第一次加载时一定会发生回流。
区别:回流必将引起重绘,重绘不一定会引起回流。
使用js监听div.style.height,在赋值给div的宽。
call的语法:函数名.call(obj,参数1,参数2,参数3……);
apply的语法:函数名.apply(obj,[参数1,参数2,参数3……]);
这两个东西功能相同,就是把一个函数里面的this设置为某个对象,区别就是后面的参数的语法。call需要使用逗号分隔列出所有参数,但是apply是把所有参数写在数组里面。需要注意的是即使只有一个参数,也必须写在数组里面。
例如:插件安装问题,请求跨域问题等。
watch:{} 对象,可监听数据,数据发生变化, 处理函数
目的: watch虽可监听,但只是浅监听,只监听数据第一层或者第二层,watch监听不到。可以设置deep:true做深度监听。
对vue的数据双向绑定。
403服务器拒绝访问。
能。
具体实现参考:

方法(@click.native.prevent):
<el-radio-group v-model="radio2">
<el-radio @click.native.prevent="clickitem(3)" :label="3"> 备选项</el-radio>
<el-radio @click.native.prevent="clickitem(6)" :label="6"> 备选项</el-radio>
<el-radio @click.native.prevent="clickitem(9)" :label="9"> 备选项</el-radio>
</el-radio-group>
clickitem (e) {
e === this.radio2 ? this.radio2 = '' : this.radio2 = e
},

图形图像优化,声音文件优化,文件及库的优化,代码的优化。
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
四种:1.jsonp 2.cros 3.domain.xml配置 4.正向代理。
post安全性比get好,get的参数在url上,post请求文件中,get用于获取数据,post主要用于提交数据。
内存泄露是指程序中已动态分配的堆内存由于某种原因程序未释放或者无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
闭包使用不当引发
ie盒模型content部分包含了padding和border
w3c盒模型content不包含。
雪碧图技术,压缩代码,合并复用的js和css文件,懒加载技术,css放在head中,设置浏览器缓存等。
答: url-loader封装了file-loader。url-loader不依赖于file-loader,例如:我们需要background样式用url引入一张背景图,我们都知道webpack会将各模块进行打包,因此用url的路径是html页面入口,而不是原始的css文件,会导致图片引入失败。而使用file-load,可以解析项目中的url引入,根据我们的配置,将图片拷贝到相应的路径,根据我们的配置,修改打包后文件引用路径,指向正确文件。
答:使用css3的transform属性。
@keyframes
都是事件绑定,
区别:事件委托。
1、es6新增了箭头函数,es5没有;
2、ES6中新增了块级作用域,es5没有;
3、ES6引入Class概念,不再像ES5一样使用原型链实现继承;
ES6引入了class
关键字,提供了更易读和理解的面向对象编程方式。另外,ES6还引入了模块化的概念,使用import
和export
关键字实现模块的导入和导出。
4、ES6中可以设置默认函数参数,es5不行;
5、ES6中新增了promise特性。
6、ES6中新增模版字符串
7、ES6中新增结构赋值
B+tree索引、Hash索引、Full-text索引
javascript原始类型有6种,分别为:
1、number(数字类型);
2、string(字符串类型);
3、null;
4、undefined(未定义);
5、boolean(布尔类型);
6、symbol,表示独一无二的值。
原生JS
1、window.history.go(0)方法
window.history.go(0)
2、location.reload()方法
location.reload()
3、location.href=location.href方法
location.href=location.href
4、vue-router方法
const router = useRouter()
router.go(0)
5、react-router方法
import { createBrowserHistory, createHashHistory } from 'history';
const history = createBrowserHistory() // history模式
const history = createHashHistory() // hash模式
history.go(0)
发布订阅者模式又叫观察者模式,发布订阅者模式一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得将得到通知;观察者模式则是一种一对一的依赖关系。
面试题:浏览器输入 URL 后回车发生了什么? (baidu.com)
个人对“vue2与vue3响应式原理的区别”的理解 - 知乎 (zhihu.com)
在响应式原理方面 Vue3 与 Vue2 有什么不同? (zhihu.com)
原型链:原型链主要有三部分构成:原型、构造函数、实例,实例可以通过new构造函数获取,构造函数可以通过实例的constructor或者原型的constructor获取,原型可以通过实例的__proto__或者构造函数的prototype获取。原型也可以通过__proto__获取父级元素的原型,直到最终拿到null。
1、学习曲线的区别
React:React的学习曲线相对较陡,尤其是当引入Redux等数据流管理工具时,开发者需要花费更多时间掌握。React更注重JavaScript的本质,强调函数式编程,对于具有较强JS基础的开发者来说,更容易上手。
Vue:相比之下,Vue的学习曲线相对较缓。Vue集成了许多React和Angular的优点,同时其API设计更为直观,使得初学者可以更快地上手并进行开发。同时,Vue的文档也非常友好,对初学者更有帮助。
2、数据流管理的区别
React:React使用Redux进行状态管理,Redux是一个高度严谨和可预测的状态管理器,但也因此变得相对复杂。初学者可能会对其有一些困惑。
Vue:Vue使用Vuex进行状态管理,Vuex的设计原则和Redux相似,但在实际使用中,Vuex的API更简单,学习成本更低。
3、社区支持的区别
React:React由Facebook维护,拥有庞大的社区支持。同时,由于其长时间的历史,React有更多的库可供选择,且生态系统更为成熟。
Vue:Vue虽然社区相对较小,但发展非常快速,国内的支持也非常热烈。
4、基础结构的区别
React:React是由Facebook开发的一个JavaScript库,它只关注视图层。这种设计理念使得React可以与其他库无缝协作。另一方面,React使用虚拟DOM,并引入了一种叫做JSX的语法糖,可以在JavaScript中写HTML。
Vue:Vue也是一个专注于视图层的JavaScript框架,同时也易于学习。Vue使用了一种类似于HTML的模板语法,让开发者可以将HTML元素绑定到Vue实例的数据上。另外,Vue也使用了虚拟DOM。
5、数据绑定的区别
React:React实现了单向数据流,这种设计使得应用的状态预测更为准确。当视图需要变化时,必须通过Dispatch Action,然后通过Reducer函数来改变State状态。
Vue:Vue实现了双向数据绑定,通过v-model指令可以很容易地实现。这种设计使得开发者在编写业务代码时,可以更快速地响应用户输入,而不需要手动监听和更新DOM。
6、性能的区别
React:React通过引入虚拟DOM,降低了直接操作DOM带来的性能损耗。在每次状态更新时,React会创建一个新的虚拟DOM树,并与上一次的树进行比较,然后高效地更新实际DOM。
Vue:Vue也使用了虚拟DOM,但它进一步优化了虚拟DOM的性能。在初始化应用时,Vue会预先计算出模板中的依赖关系,因此在重新渲染时,只需要更新依赖的部分,从而提高渲染效率。
1、rem
2、media
@media screen and开头的语句就是媒体查询语句。@media后面是一个或者多个表达式,如果表达式为真,则应用样式。@media screen and (min-width:320px) 这句话的意思就是:设备宽度小于320就选中这个样式。
也可以利用第三方库lib-flexible动态font-size
3、viewport
/* width: 100px / 3.75px = 26.6667vw */
4、media+viewport
略
5、media+rem
略
特比地:vw和rem的对比
rem事实上是作为一种过渡的方案,它利用的也是vw的思想
vw相比于rem的优势:
JSON、循环、递归、reduce函数迭代、es6扩展运算符
@keyframe move {
from {left: 0;}
to {left: 100%;}
}
/*
@keyframe move {
0 {tranform: translateX(0);}
100% {tranform: translateX(100%);}
}
*/
element {
animation: move 2s
}
导入导出方式不同:
CJS 是通过 require 导入,module.exports 和 exports 导出的
ESM 是通过 import 导入,export 导出的
输出值方式不同
加载机制不同
ESM 模块会自动使用严格模式,不管你有没有在模块头部添加 “use strict”
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。