小知识点

1、0.1+0.2 !=0.3,理由?

计算机表示十进制是采用二进制表示的。0.1在二进制表示为:0.1=2^-4*1.10011 (0011)

原生解决方式:
let num = parseFloat((0.1+0.2).toFixed(10)) ;// 打印num,输出0.3

2、用display:grid,place-items:center 布局一个九宫格

<view class="nine-container">
<view v-for="item in 9" :key="item">{{item}}</view>
</view>

.nine-container{
width:300rpx;
display:flex;
flex-wrap:wrap;
}
.nine-container view{
width:100rpx;
height:100rpx;
border:1rpx solid black;
display:grid;//网格布局
place-items:center; //子元素水平垂直居中
box-sizing:border-box;
margin:-1rpx 0 0 -1rpx; //负边距
}
.nine-container view:nth-child(3n+1){ //1、4、7子元素,取消左负边距
margin-left:0;
}
.nine-container view:nth-child(-n+3){ //前三个子元素,取消负边距
margin-top:0;
}
.nine-container view:hover{
color:red;
border:1rpx solid red;
z-index:1; //调高层级
}

3、vue2.x 到 vue3详细对比

生命周期的变化:
vue2.x vs vue3
beforeCreate 使用 setup()
created 使用 setup()
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeDestory onBeforeUnmount
destroyed onUnmounted
errorCaptured onErrorCaptured

使用 proxy 代替 definePrototype
vue2.x 双向绑定的核心是 Object.defineProperty()。

Object.defineProperty() 语法:vue为什么对数组对象的深层监听无法实现,因为组件每次渲染都是将data里的数据通过defineProperty
进行响应式或者双向绑定上,之前没有后加的属性是不会被绑定上,也就不会触发更新渲染。
Object.defineProperty(obj,'name',{
enumerable:true,//可枚举
configurable:true;//可配置
get:function(){
return def
},
set:function(val){
def = val
}
}) -------(defineproperty 只能响应首次渲染时候的属性!)

proxy 语法:(两个参数,对象,13个配置项)
const handler = {
get:function(obj,prop){
return prop in obj ? obj[prop]:37;
},
set:function(){},
...13个配置项
}
const p = new Proxy({},handler),
p.a = 1;
p.b = undefined;
console.log(p.a,p.b);//1,undefined
console.log('c' in p,p.c);//false,37


diff算法的提升:

4、hash 以及 new Set 去重

function unique(arr=[]){
if(arr.length===0 || arr.length===1){
return arr
}
const newarr = [];
const hash = {};
for(let i=0;i<arr.length;i++){
if(!hash[arr[i]]){
hash[arr[i]] = 1;
newarr.push(arr[i]);
}
}
return newarr
}

function unique(arr=[]){
if(arr.length===0||arr.length===1){
return arr
}
return [...new Set(arr)]
}

 5、cmd里面有prettier警告提示,如何关闭?

//vue3项目中
可以在 package.json 文件 的 eslintConfig:{}中的 rules 里面添加: "prettier/prettier":"off" 即可。
或者
执行命令: npm run lint --fix (没有试过0_0)

6、若需要禁止蒙版下的页面滚动,可使用 @touchmove.stop.prevent="moveHandle" , moveHandle 可以用来处理 touchmove 的事件,也可以是一个空函数。

<view class="mask" @touchmove.stop.prevent="moveHandle"></view>

moveHandle(){
//空函数即可
}

7、uniapp中,data属性必须声明为返回一个初始数据对象的函数;否则页面关闭时,数据不会自动销毁,再次打开该页面时,会显示上次数据。

8、github筛选技巧

in:name xxx  => in:name React
in:readme xxx => in:readme React
in:description xxx => in:description 微服务

stars:>xxx =>stars:>5000
forks:>xxx =>forks:>2000
language:xxx => 编程语言是xxxx language:python
pushed:>YYYY-MM-DD =>最后更新时间大于 YYYY-MM-DD

9、用小黑框提交代码 git bash here

git pull origin 分支名字   =>  git pull origin wl

切换分支: git checkout master
提交 git push origin master
查看分支 git branch (带*号表示就是当前分支)

查看冲突 git diff
修改后 git push -u origin master

 10、删除重复项

let arr = [1,2,3,2,32,23,2,3222,33,2];
let restArr = Array.from(new Set(arr));
console.log(restArr,'去重数组元素');

数组去重方法:
1. [...new Set(arr)];
2. Array.from(new Set(arr))
3. indexOf
4. includes
5. 利用filter,例如:
      function unique(arr) {
         return arr.filter(function(item, index, arr) {
            //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
            return arr.indexOf(item, 0) === index;
        });
      }

11、数组到对象

let arr = ['aa','bb','cc'];
let arrObj = {...arr}

12、对象到数组

let number = {
one:1,
two:2
}
let key = Object.keys(number);// ['one','two']
let value = Object.values(number); // [1,2]
let entry = Object.entries(number);// [['one':1],['two':2]]

 13、下载功能实现

最常见的如下:
1. a标签,例如: <a href="xxx" download="xxx'>点击下载</a>
补充:
function download(url,filename){
const a = documnet.createElement('a');
a.href=url;//下载路径
a.download=filename;//下载文件名
a.style.display='none';//不可见
documnet.body.appendChild(a);//挂载
a.click();//触发点击事件
document.body.removeChild(a);//移除a标签
}
或者
<a href="xxxxx" download="hello.png'>点击下载</a>

2. location.href, 例如: window.location.href="xxx"
3. window.open, 例如: window.open(xxx)
4. Content-disposition, 例如:Content-disposition:attachment;filename='xx'

blob方式:
if(reqConf.responseType == 'blob'){
//返回文件名
let contentDisposition = config.headers['content-disposition'];
if(!contentDisposition){
contentDisposition=`;filename=${decodeURI(config.headers.filename)}`
}
const filename = window.decodeURI(contentDisposition.split(`filename=`)[1])
//文件类型
const suffix = filename.split('.')[1];
//创建blob对象
const blob = new Blob([config.data], {
type: FileType[suffix],
})

const a = document.createElement('a');
a.style.display='none';
a.href=URL.createObjectURL(blob);//创建url对象
a.download=filename;//下载文件名
document.body.appendChild(a);
a.click();
document.body.removeChild(a); //移除隐藏a标签
URL.revokeObjectURL(a.href);//销毁url对象
}

14、localStorage与sessionStorage区别:

1.关闭网页后重新打开,localStorage会保留数据,而sessionStorage会被删除;
2.在页面内实现跳转,localStorage会保留数据,sessionStorage也会保留数据;
3.在页面外实现跳转(打开新网页),localStorage会保留数据,而sessionStorage不会保留数据。

15、git did not exit cleanly报错

 

16、forEach使用注意事项

场景描述: 如果在forEach中使用异步请求,请求结果可能与我们想要的结果不一样。
例如:
async function func(){
let arr = [3,2,1];
arr.forEach(async (item) =>{
const res = await syncFunc(item)
console.log(res);
})
console.log('end');
}
function syncFunc(item){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve(item);
}, 1000*item)
})
}
func();//打印结果为: end 1 2 3
注意: 如果我们想要的结果是 3 2 1 end的话,那么就需要进行改造
改造方法一(使用for循环):
async function func(){
let arr = [3,2,1];
for(let i=0;i<arr.length;i++){
const res = await syncFunc(arr[i]);
console.log(res);
}
console.log('end');
}
function syncFunc(item){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve(item);
}, 1000* item)
})
}
func();// 3 2 1 end

改造方法二(使用map,filter,reduce等等,原因是他们支持在函数中返回promise,并且会等待所有promise完成。):
下面会选择使用 map+Promise.all()来处理异步函数:
const arr = [1,2,3,4,5];
async function func(item){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
reslove(item)
}, 1000)
})
}
// 这里把map换成for循环也可以,例如 ----start
const promises = arr.map(async(item)=>{
const res = await func(item);
return res
})
Promise.all(promises).then((res)=>{
console.log(res);//[1,2,3,4,5]
})
//----end
//----change for循环 start
async function forFunc(){
let ress = [];
for(let i=0;i<arr.length;i++){
const res = await func(arr[i]);
ress.push(res);
}
console.log(ress);//[1,2,3,4,5]
}
forFunc();
//----change for循环 end


关于forEach总结一波:
由于forEach()方法是一个同步方法,不支持处理异步函数。如果在forEach中执行了异步函数,forEach无法等待异步函数
完成,会继续执行下一项,即无法保证异步任务的执行顺序。
forEach()方法不支持使用break/continue跳出循环。
使用map+Promise.all()/for循环等来解决异步函数。

 17、宏任务与微任务

js任务分为同步任务和异步任务,其中异步任务又分为 宏任务与微任务两类,分别是:
宏任务:
setTimeout, setInterval
异步ajax请求,
其他操作,
其他宏任务
微任务:
promise.then,catch,finally
process.nextTick


执行顺序为:
每一个宏任务执行完之后,都会检查是否存在待执行的微任务。
如果有,则执行完所有微任务之后,再继续执行下一个宏任务。


例如:
setTimeout(()=>{
console.log(1) //宏任务
})
new Promise((resolve, reject)=>{
console.log(2); //同步任务
resolve();
}).then(()=>{
console.log(3); // 微任务
})
console.log(4); //同步任务
//打印结果为: 2,4,3,1

18. vue项目中重载页面方法

场景描述:假如用户切换账号角色时,需要更新菜单栏数据
方法一(使用 provide/inject):
//在根组件中,即 App.vue文件:
<template>
<div id="app">
<router-view v-if=isRouterAlive></router-view>
</div>
</template>
<script>
export default {
name: 'App',
provide(){
return { reload: this.reload }
},
data(){
return { isRouterAlive: true }
},
methods: {
reload(){
this.isRouterAlive = false
this.$nextTick(()=>{
this.isRouterAlive = true
})
}
}
}
</script>
// 在触发的子组件中引用即可
// other.vue
export default{
inject: ['reload'],
data(){
return{}
},
methods:{
handleClick(){
this.reload() // 在子组件中引入 inject:['reload'], 然后调用reload方法即可刷新页面
}
}
}

方法二: 使用 window.location.reload(), 不过这种方法有点暴力,个人更推荐使用方法一来操作。

 

 

参考链接:

   https://juejin.cn/post/7207078219215732794

   https://blog.csdn.net/daicooper/article/details/129392055?spm=1000.2115.3001.6382&utm_medium=distribute.pc_feed_v2.none-task-blog-personrec_tag-18-129392055-null-null.pc_personrec&depth_1-utm_source=distribute.pc_feed_v2.none-task-blog-personrec_tag-18-129392055-null-null.pc_personrec

posted on 2023-03-07 15:56  有匪  阅读(70)  评论(0编辑  收藏  举报

导航