工作记录二
组件篇
1. 在前端ui组件中的聚焦或者失焦事件中拿不到event
,.capture
用法
@focus.native.capture="selectFocus($event)" @blur.native.capture="selectBlur($event)"
会覆盖掉原有组件的失焦事件
2. ref的一些小细节
-
组件内部有多个同名ref引用时
- 没有父子关系
<template> <h2 ref="test">test1</h2> <h2 ref="test">test2</h2> </template> <script> export default { mounted(){ console.log(this.$refs.test) } } </script> <!-- 为最后一个元素的dom --!>
- 存在父子关系
<h2 ref="test"> test1 <h3 ref="test">children test1</h3> </h2> <script> export default { mounted(){ console.log(this.$refs.test) } } </script> <!-- 为父元素的dom --!>
- 使用v-for循环生成
<ul> <template v-for="i in 3"> <li :key="i" ref="test">i</li> </template> </ul> <script> export default { mounted(){ console.log(this.$refs.test) } } </script> <!-- 为长度为3的数组 --!>
3. vue数字变化动画插件
4. 炫酷外壳,轻量大数据展示组件
5. 精致开源的icon
库
官网上有对react中使用css.gg的例子,在vue中我是这么使用的。
//安装一下css.gg库
yarn add css.gg
//在mian.js中添加
import 'css.gg/icons/all.css';
//然后就可以写了
<i class="gg-{iconName}" />
//例如
<i class="gg-add-r" />
6. 中国风的配色网站
7. 前端新手引导组件
8. vue莫名刷新问题
//App.vue
<div class="contain" @click="mouse">
<HelloWorld :image="{src:musi}" />
<span>{{visible}}</span>
</div>
<script>
import HelloWorld from './components/HelloWorld.vue'
import musi from "@/assets/musi.gif";
export default {
name: 'App',
components: {
HelloWorld
},
data(){
return{
musi,
visible:false
}
},
methods:{
mouse(){
this.visible++
}
}
}
</script>
//HelloWorld.vue
<template>
<div style="width:fit-contain">
<img
:src="image.src"
>
</div>
</template>
<script>
export default {
name:"list",
props:{
image:Object
},
beforeUpdate(){
console.log('change');
}
}
</script>
这是一个很简单的设计,点击contain数字+1,但是由于是临时创建的对象,每次点击contain都会导致Helloword.vue刷新,以后千万不能用对象包裹,去data声名一下。
9. vue打包之后添加二级目录
//在router的index.js中
const router = new VueRouter({
mode: 'history',
base: '/web',
//添加被嵌套的文件夹
routes
})
//在vue.config.js中
module.exports = {
publicPath:"/web"
}
//在入口文件的index.html中
<meta base ="/web/">
10.hooks模拟componentWillUnmount
useEffect(() => {
return () => {
console.log('will unmount');
}
}, []);
复制代码当在 useEffect 的回调函数中返回一个函数时,这个函数会在组件卸载前被调用。我们可以在这里面清除定时器或事件监听器。
11.有趣的动画插件
12.antd在线配置样式网站
加载有点慢…耐心等待…
13.element在线配置样式网站
14.浏览器顶部进度条组建
15.console.log输出颜色
16.terminal的等待动画
17.md文件徽牌
一篇少数派的使用文章
18. ip校验工具
CSS
样式
1. onResize
和ResizeObserver
因为出现滚动条不停抖动的解决方式
/*其实暂时没有一个很好的解决方法,我认为可以通过debounce函数解决。
既然是因为滚动条的出现而不停抖动的话,那就直接让滚动条全都显示出来,*/
body{
overflow-y: scroll
}
2. 元素垂直居中的方法
- 使用绝对定位,设定四个方向值为0,设置margin为auto
.center{
width: 100px;
height: 100px;
position: absolute;
border: 1px solid red;
top: 0;
bottom: 0;
right: 0;
left: 0;
margin: auto;
}
- 绝对定位,top50%,left50%,margin为负(必须知道子元素高度)
.center{
width: 100px;
height: 100px;
position: absolute;
border: 1px solid red;
top: 50%;
left: 50%;
margin: -50px 0 0 -50px;
}
- 绝对定位,top50%,left50%,translate(-50%,-50%)
.center{
width: 100px;
height: 100px;
position: absolute;
border: 1px solid red;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
- display:flex
.contain{
width: 500px;
height: 500px;
display: flex;
justify-content: center;
align-items:center;
position: relative;
border: 1px solid red;
}
.center{
width: 100px;
height: 100px;
border: 1px solid red;
}
- 使用伪元素基线校准
.contain{
width: 500px;
height: 500px;
text-align: center;
position: relative;
border: 1px solid red;
}
.center{
width: 100px;
height: 100px;
display: inline-block;
vertical-align: middle;
border: 1px solid red;
}
.contain::after{
content: "";
display: inline-block;
height: 100%;
vertical-align: middle;
}
3. css一像素线缩放实现方法
.onepixel {
display: block;
}
.onepixel::before{
content: "";
display: block;
transform-origin: 0 0;
}
.onepixel.top::before {
width: 100%;
border-top: 1px solid #000;
}
@media (min-resolution: 2dppx) {
.onepixel.top::before {
width: 200%;
transform: scale(.5) translateZ(0);
}
}
@media (min-resolution: 3dppx) {
.onepixel.top::before {
width: 300%;
transform: scale(.333333) translateZ(0);
}
}
4. 好看的滚动条样式
<style>
*::-webkit-scrollbar {
width: 7px;
}
/*滚动条的滑轨背景颜色,可以用display:none让其不显示,也可以添加背景图片,颜色改变显示效果。*/
*::-webkit-scrollbar-track {
background-color: #f5f5f5;
-webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0.1);
border-radius: 5px;
}
*::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, 0.2);
border-radius: 5px;
}
*::-webkit-scrollbar-button {
background-color: #eee;
display: none;
}
*::-webkit-scrollbar-corner {
background-color: black;
}
</style>
vue
项目放在App.vue
中就可以。
JS
篇
1. 原型 原型链
2. 闭包
3. 深拷贝浅拷贝
是什么
- 浅拷贝:浅拷只是复制某个对象的指针,而不复制对象本身,新旧对象中还有一部分共处同一个内存。
- 深拷贝:深拷贝完全创造一个一模一样的对象,并不会共享内存。
怎么弄
- 浅拷贝
- 对于对象来说可以
Object.assign
let a = {
1:"a",
2:"b",
3:{
1:"a"
}
}
let b = Object.assign({},a)
b[3][1]="b"
console.log(a)
/*{
1: "a",
2: "b",
3: {1: "b"}
}*/
-
对于数组来说
Array.prototype.concat()
let a = [1,2,{ 3:'a' }] let b = a.concat([]) a[2][3] = 'b' console.log(a) /*[ 0: 1, 1: 2, 2: {3: "b"} ]*/
Array.prototype.slice()
let a = [1,2,{ 3:'a' }] let b = a.slice(0) a[2][3] = 'b' console.log(a) /*[ 0: 1, 1: 2, 2: {3: "b"} ]*/
- 共有方法扩展运算符
...
- 深拷贝
- 自己写简单的
// 定义检测数据类型的功能函数
function checkedType(target) {
return Object.prototype.toString.call(target).slice(8, -1)
}
// 实现深度克隆---对象/数组
function clone(target) {
// 判断拷贝的数据类型
// 初始化变量result 成为最终克隆的数据
let result, targetType = checkedType(target)
if (targetType === 'object') {
result = {}
} else if (targetType === 'Array') {
result = []
} else {
return target
}
// 遍历目标数据
for (let i in target) {
// 获取遍历数据结构的每一项值。
let value = target[i]
// 判断目标结构里的每一值是否存在对象/数组
if (checkedType(value) === 'Object' ||
checkedType(value) === 'Array') {
// 对象/数组里嵌套了对象/数组
// 继续遍历获取到value值
result[i] = clone(value)
} else {
// 获取到value值是基本的数据类型或者是函数。
result[i] = value;
}
}
return result
}
JSON,stringify
let arr = [1, 3, {
username: ' kobe'
},function(){}];
let arr4 = JSON.parse(JSON.stringify(arr));
arr4[2].username = 'duncan';
- 会忽略
undefined
- 会忽略
symbol
- 不能序列化函数
- 不能解决循环引用的对象
- 函数库
lodash
var _ = require('lodash');
var obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);
// false
4. vue2
监听数据的方法简写
//判断函数:如果给的值是对象数据类型,那你再走一遍循环吧。
function judge(value) {
if(Object.prototype.toString.call(value) !== "[Object Object]"){
return
}
for(let key in value){
defineReactive(value,key,value[key])
}
}
//定义监听函数,可以在set中进行对视图的变化
function defineReactive(obj,key,value){
judge(value)
Object.defineProperty(obj,key,{
get:function () {
console.log("我被取值了,怎么办好难!")
return value
},
set:function (newValue) {
console.log("我被监听到了,可以搞dom了")
judge(newValue)
return value = newValue
}
})
}
//传入一个对象让他变成可以被监控
function set(obj) {
for(let key in obj){
defineReactive(obj,key,obj[key])
}
}
let test = {
name:"小红"
}
set(test)
// test.name = "小明" 我被监听到了,可以搞dom了
// test.name = {
// firstName : "小", 我被监听到了,可以搞dom了
// lastName : "明", 我被监听到了,可以搞dom了
// }
// console.log(`我的名字是${test.name.firstName}${test.name.lastName}`)
// 我被监听到了,可以搞dom了
// 我被取值了,怎么办好难!
// 我被取值了,怎么办好难!
// 我的名字是小明
这个老哥的
Object.defineProperty
解释的详细,我记录一下地址
5. Proxy
简单例子,简单解释vue3
数据监听
let test = {
name:"小红",
children:{
name:"红红"
}
}
let testObject = new Proxy(test,{
get(target,key){
console.log(target,key)
return key in target ? target[key] : "哈哈并没有"
},
set(target,key,value){
//console.log(target,key,value)
target[key] = value
return true
}
})
// console.log(testObject.age)
// testObject.name = "小明"
6. 手写一个简单的promise
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
function myPromise(fn){
const that = this
that.state = PENDING
that.value = null
//成功回调的列表
that.resolvedCallbacks = []
//失败回调的列表
that.rejectedCallbacks = []
//成功时调用的函数
function resolve(value){
that.state = RESOLVED
that.value = value
that.resolvedCallbacks.map(cb => cb(that.value))
}
//失败时调用的函数
function reject(value){
that.state = REJECTED
that.value = value
that.rejectedCallbacks.map(cb => cb(that.value))
}
//then方法
//必须这两个参数是函数,如果不是函数则定义为一个函数;
//只有在promise不在等待的状态的时候才会执行传入的函数。
myPromise.prototype.then = function(onResolve,onReject){
const that = this
onResolve = typeof onResolve == 'function' ? onResolve : onResolve => onResolve
onReject = typeof onReject == 'function' ? onReject : onReject => { throw onReject }
if(that.state == PENDING){
that.resolvedCallbacks.push(onResolve)
that.rejectedCallbacks.push(onReject)
}
if(that.state == RESOLVED){
onResolve(that.value)
}
if(that.state == REJECTED){
onReject(that.value)
}
}
try{
fn(resolve,reject)
}catch(e){
reject(e)
}
}
//例子
new myPromise((resolve)=>{
console.log("这是promise内部的打印")
setTimeout(() => {
console.log("这是settimeout内部的打印")
resolve("xixi")
}, 2000);
}).then(res =>{
console.log(res)
})
console.log("这是最外层")
7. 宏任务微任务之间的执行关系

8. Event loop
由于JavaScript是单线程执行,在主线程上从上到下依次执行,在执行耗时比较大的代码片段会产生堵塞的情况,为了避免这一情况引入异步的思想,异步任务分为宏任务和微任务,所以执行顺序就变成了:
- 执行主线程的同步代码,即为宏任务执行。存在微任务压入本次task队列。
- 执行当前轮训的微任务。
- 执行异步的宏任务,存在微任务压入task队列,再次执行微任务。
这样的轮训机制,直到所有任务完成,这种轮训过程称为event loop
微任务包括 process.nextTick
,promise.then
,MutationObserver
。
宏任务包括 script
, setTimeout
,setInterval
,setImmediate
.