学习

2022-03-28  本文已影响0人  大佬_娜

一. css相关

1. flex布局

<style>
   ul{
      width:300px;
      border:1px solid red;
      display: flex;
      justify-content: space-between;      //X轴对齐方式  两端对齐。
      flex-wrap:wrap;     //是否进行换行处理  nowrap; 默认值,不换行处理
    }
    ul li {
      width: 80px;
      height:80px;
      background-color: red;     
      margin-bottom: 10px;
    }
</style>  
  <ul>
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
    </ul>
<style>
   div{
      width: 100px;
      height:100px;
      border:1px solid red;
      display: flex;
      flex-direction: row;  //布局的排列方向
      justify-content: center;  //水平居中
      align-items: center;//垂直居中
    }
    div p {
      width: 80px;
      height:80px;
      background-color: red;
    }</style>
   <div>
      <p>文本内容</p>
    </div>
  <style>

    .box{
      width:100%;
      display: flex;
      height:500px;
    }
    .left{
      width:200px;
      background-color: red; 
      height:500px;
    }
    .box .right{
      background-color: green; 
      height:500px;
      flex:1;  // flex-grow、flex-shrink 弹性盒的收缩比率 、flex-basis 元素在主轴方向上的初始大小
    }
    
  </style>
<div class="box">
      <p class="left">文本内容</p>
      <div class="right">右边盒子</div>
    </div>

2. 第三方字体的引用

@font-face {  
    font-family: 'JDbold';  
    src: url('jdfont/JDLangZhengTi_Bold.TTF');  
    font-weight: normal;  
    font-style: normal;  
}

3. BFC

BFC块级格式化上下文,是一个完全独立的空间,让空间里的子元素不会影响到外面的布局。
触发BFC:

二. js相关

3. 原型与原型链

原型: 创建Class类,有prototype属性,称为显示属性; 当你实例一个对象的时候,有proto属性称为隐士原型
原型链:

image.png

4. call、apply 、bind的区别

obj.myFun.call(db,'成都','上海');  // 德玛 年龄 99  来自 成都去往上海
obj.myFun.apply(db,['成都','上海']);      // 德玛 年龄 99  来自 成都去往上海  
obj.myFun.bind(db,'成都','上海')(); 

5. async/await

async getCountByLevel(type, index) {
      const res = await mgopHttp("mgop.jd.bzgf.countByLevel", APP_KEY, {
        stLevel: type,
      });
      this.list[index].number = res.data;
 },

8. 宏任务,微任务

先执行微任务,后执行宏任务
宏任务:script(整体代码),setTimeout,setInterval,dom事件,ajax请求
微任务: Promise.then,Object.observe,async/await
微任务>dom渲染>宏任务

9. Event Loop 轮循事件

10. 函数节流、防抖

function throttle (f, wait) {
  let timer
  return (...args) => {
    if (timer) { return }
    timer = setTimeout(() => {
      f(...args)
      timer = null
    }, wait)
  }
}

// test
function testFn(e, content) {
    console.log(e, content);
}
let _testFn= throttle(testFn, 1000); // 节流函数
document.onmousemove = function (e) {
    _testFn(e, 'throttle'); // 给节流函数传参
}

function debounce (fn, wait=1000) {
  let timer,
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => {
      fn(...args);
    }, wait)
  }
}
// test
function testDebounce(e, content) {
    console.log(e, content);
}
var testDebounceFn = debounce(testDebounce, 1000); // 防抖函数
document.onmousemove = function (e) {
    testDebounceFn(e, 'debounce'); // 给防抖函数传参
}

\

9. 数组去重方法

  1. new Set方法 [...new Set()] 、Array.from() 讲set格式转为数组
var arr = [1,3,4,5,1,23,4,5]
function unique(arr){
  return new Set(arr)   //Set(5) {1, 3, 4, 5, 23}   //new Set返回set数据格式
  // return Array.from(new Set(arr))    //[1, 3, 4, 5, 23]    //Array.from  将set格式转为数组
  // return [...new Set(arr)]   //[1, 3, 4, 5, 23]   //[...]将set格式转为数组
}

  1. for循环
function unique1(arr){
 for(var i = 0 ,len = arr.length; i < len;i++ ){
  for(var j = i +1 ,len = arr.length;j < len;j++){
    if(arr[i] == arr[j]){
      arr.splice(j ,1)
      j--;
      len--
    }
  }
 }
 return arr
}
  1. indexOf
function unique2(arr){
  let arr1 = []
   for(var i = 0 ;i < arr.length;i++ ){
      if(arr1.indexOf(arr[i])  == -1){
        arr1.push(arr[i])
      }
   }
   return arr1
}
  1. includes
function unique3(arr){
  let arr1 = []
   for(var i = 0 ;i < arr.length;i++ ){
      if(!arr1.includes(arr[i])){
        arr1.push(arr[i])
      }
   }
   return arr1
}
  1. filter
function unique4(arr){
  return arr.filter( function(item,index){
    return arr.indexOf(item,0) == index
  })
}

三. ES6相关

模块化、面向对象语法、promise、箭头函数、let和const、数组解构赋值、模板字符串....

1. let与const 的区别

image.png
例题:
var a = 1;
console.log(window.a )   //1
let b = 1;
console.log(window.b )   //undefined

例题
const a = [];
a.push('Hello'); 
a.length = 0;    
a = ['Dave'];       //报错

//例题:
function f1() {
  let n = 5;
  if (true) {
    let n = 10;
  }
  console.log(n);    //5
}

2. 变量的解构赋值

let person = ['赵本山','刘能','宋小宝']
let [a,b,c] = person;
console.log(b)
let xiaopin = {
  name:'小娜',
  age:18,
  see:function(){
    console.log('我会演小品')
  }
}
let {name,age,see}  = xiaopin
console.log(age)

3. 箭头函数与普通函数的区别

image.png
var name = "xiaona"
let obj = {
  name: 'xiaona2',
  getName:function(){
    console.log(this.name)   
  },
  getName2:()=>{
    console.log(this.name)
  }
}

obj.getName()
obj.getName2()

4. 函数的默认值与解构赋值搭配使用

function contain ({host='127:100.1.20',port}){
  console.log(host)
  console.log(port)
}
contain({
  port:'8080'
})

5. rest参数, 类似ES5的arguments获取实参参数

rest 返回的是一个数组 ,必须要放到所有参数最后面

function fn (){
  console.log(arguments)   
}
fn(1,2,3)

function fn2 (a,b...args){
  console.log(a)   //1
  console.log(b)   //2
  console.log(args)   //[3,4,5]
}
fn2(1,2,3,4,5)

6. 扩展运算符

let stars = ['易烊千玺','王源','王俊凯']
function fn(){
  console.log(arguments)
}
fn(stars)   //arguments1个值
fn(...stars)  //arguments3个值

应用场景

const a = ['肖央','王太利']
const b = ['曾毅','玲花']
const c = a.concat(b) 
const d = [...a,...b]

7. Symbol

Symbol 不可以使用关键字new;它是唯一的 ; Symbol的诞生是处理对象的属性名重复后属性值会被覆盖 ;
参数只作为修饰使用;

let game = {
  name:'狼人杀',
  up:function(){
    console.log('快速向上')
  },
  down:function(){
    console.log('快速向上')
  }
}
let methods = {
  up:Symbol(),
  down:Symbol()
}
game[methods.up] = function(){
  console.log('修改方法')
}

game.up()  //快速向上

//game里的  up 与down方法都是唯一的,不会直接改变此方法 

7. 生成器Generator

  1. 生成器是一个特殊的函数,异步编程的一个解决方案;
  2. 生成器对象中包含三个函数,next() return() throw()
  1. yield关键字,函数代码分隔符,这个yield关键字让 Generator内部的逻辑能够切割成多个部分。
// 案例:1秒后控制台输出111,2s后输出222,3s后输出333 
//回调地域
setTimeout(()=>{
 console.log(111)
 setTimeout(()=>{
   console.log(222)
   setTimeout(()=>{
     console.log(333)
   },3000)
 },2000)
},1000)

function fun1(){
 setTimeout(()=>{
   console.log(111)
   comput.next()
 },1000)
}
function fun2(){
 setTimeout(()=>{
   console.log(222)
   comput.next()
 },2000)
}
function fun3(){
 setTimeout(()=>{
   console.log(333)
 },3000)
}
function * gen(){
 yield fun1()
 yield fun2()
 yield fun3()
}
let comput = gen();
comput.next();

8. promise

    let p = new Promise((resolve, reject) => {
        //做一些异步操作
      setTimeout(function(){
            var num = Math.ceil(Math.random()*10); //生成1-10的随机数
            if(num<=5){
                resolve(num);
            }
            else{
                reject('数字太大了');
            }
      }, 2000);
    });
    p.then((data) => {
            console.log('resolved',data);
    }).catch((err) => {
     console.log('rejected',err);
   });

8.集合 Set ,它的值都是唯一的

let s = new Set(['好事','坏事','喜事','坏事'])
console.log(typeof s )   //object
s.size()  //长度
s.add('糟心事')   //添加
s.delete('坏事')    //删除
s.clear()  //清空
s.has('好事')   //判断是否有值
//集合实践
let arr1 = [2,1,3,2,1,4]
let arr2= [3,4,6,5,1]
//数组去重
let s1 = [...new Set(arr1)]
console.log(s1)
//并集
let s2 = [...new Set([...arr1,...arr2])]
console.log(s2)
//交集
let s3 = [...new Set(arr1)].filter(item =>  new Set(arr2).has(item))
console.log(s3)

9.class类

function Phone(name,price){
  this.name = name
  this.price= price
}
Phone.prototype.call = function(){
  console.log('我可以打电话')
}

function SmartPhone(name,price,color){
  Phone.call(this,name,price)   //继承属性
  this.color = color
}
SmartPhone.prototype = Phone.prototype;   //继承方法
SmartPhone.prototype.photo = function(){
  console.log('我可以拍照')
}
let apple = new SmartPhone('苹果',5999,'金色')
console.log(apple)
class Phone{
  constructor(name,price){
     this.name = name
    this.price= price
  }
  call(){
    console.log('我可以打电话')
  }
}

class SmartPhone extends Phone{
   constructor(name,price,color){
     super(name,price)    //Phone.call('SmartPhone',name,price)
     this.color = color
  }
  photo(){
    console.log('我可以拍照')
  }
}
let apple = new SmartPhone('苹果',5999,'金色')
console.log(apple)
class Phone{
  static name = '手机';   //静态属性 , 属性只在Phone对象上,实例对象不能调用
}
let apple = new Phone()
console.log(Phone.name)  //手机
console.log(apple.name)  //undefined

10. 数值扩展

function equal(a,b){
  if(Math.abs(a-b) <  Number.EPSILON ){
    return true
  }else{
    return false
  }
}
console.log(0.1 + 0.2 == 0.3)  //false
console.log(equal(0.1 + 0.2 , 0.3))  //false

11.对象扩展

console.log(Object.is(210,200))
console.log(Object.is(NaN,NaN))
let config1 = {
  host:'localhost',
  port:'8080',
  test:'tinajia'
}
let config2 = {
  host:'123.127.0.12',
  port:'8080',
}
console.log(Object.assign(config1,config2))
let school = {
  name:'离石'
}
let citys = {
  xiaoqu:['北京','上海']
}
console.log(Object.setPrototypeOf(school,citys))

12. 模块化

模块功能主要由两个命令构成:export 和 import
export 命令用于规定模块的对外接口
import命令用于输入其他模块提供的功能

// 分别暴露
export let name = 'xiaona'
export function change (){}
import {name,change} from ''     //解构赋值

// 统一暴露
let name = 'xiaona'
function change(){}
export {name,change}
import {name as othername ,change}  from ''     //解构赋值
//默认暴露
export default {
  name:'xiaona',
  change:function(){}
}
import {default as obj}  from ''     //解构赋值
import obj  from ''    //简便形式

语法总结:

//export 可以导出多个变量、方法等
export { getParameter, getCookie,};
import { formatDate } from "@/common/util";
//export default  只能导出一个 , 适合全局引入
export default { getParameter, getCookie, setCookie,};
import _ from "@/common/util";

四. vue相关

1. Vue双向数据绑定

image.png

2. MVC和MVVM的区别

3. 为什么data是个函数并且返回一个对象呢?

data之所以只一个函数,是因为一个组件可能会多处调用,而每一次调用就会执行data函数并返回新的数据对象,这样,可以避免多处调用之间的数据污染。

4. 使用过哪些Vue的修饰符呢?

image.png

5. 使用过哪些Vue的内部指令呢?

6. 组件之间的传值方式有哪些?

7. 路由有哪些模式呢?又有什么不同呢?

8. 如何设置动态class,动态style?

9. computed和watch有何区别,哪个可以进行异步操作?

10. Vue的生命周期,讲一讲?

image.png

11.为什么v-if和v-for不建议用在同一标签?

v-for和v-if同时存在,会先把元素都遍历出来,然后再一个个判断,这样的坏处就是,渲染了无用的节点,增加无用的dom操作,建议使用computed来解决这个问题;

<div v-for="item in list">
    {{item}}
</div>

computed() {
    list() {
        return [1, 2, 3, 4, 5, 6, 7].filter(item => item !== 3)
    }
  }

12. vuex的有哪些属性?用处是什么?

13. 对象新属性无法更新视图,删除属性无法更新视图,为什么?怎么办?

14. 直接arr[index] = xxx无法更新视图怎么办?为什么?怎么办?

15. vue相关知识点比较全面的网址

https://mp.weixin.qq.com/s/-zLlWJxA67GoctMaK0Sk8A

五. vue3相关

六. 前端性能相关

六. 前端性能相关

9. 跨域

同源策略:协议、主机、端口号一致 ,否则跨域
处理跨域:

10. nginx

image.png image.png

11.qiankun

import { registerMicroApps, setDefaultMountApp, start } from "qiankun";
//注册子应用
registerMicroApps([
            {
                name: 'retail',
                entry: process.env.VUE_APP_RETAIL,  //入口地址
                container: '#retail',
                activeRule: getActiveRule('#/cydn/retail'),
            },
 ]);

11.预编译

预编译的阶段就是创建作用域的阶段
预编译过程

  1. 创建AO对象
  2. 找形参和变量的声明,作为AO对象的属性,初始值为undefined
  3. 实参和形参相统一
  4. 找函数声明 覆盖变量的声明
function fn(a,c){
  console.log(a) 
  var a = 123
  console.log(a)  
  console.log(c)  
  function a(){}
  if(false){
    var d =678
  }
  console.log(d)  
  console.log(b) 
  var b = function(){}
  console.log(b) 
  function c(){}
  console.log(c)

}
fn(1,2)
// 解析过程
// AO:{
//   a:undefined 1  function a(){}
//   c:undefined 2 function c(){}
//   d:undefined 
//   b:undefined function(){}
// }

12. this

// 分析过程
function get(content){
  console.log(content)
}
get('你好')  //get.call(window,'你好')
var person = {
  name:'张三',
  run :function(time){
    console.log(`${thia.name} 在跑不 最多${time} min就不行了`)
  }
}
person.run(30)   //person.run.call(person,20)
var  name = 222
var a = {
  name:111,
  say:function(){
    console.log(this.name)
  }
}
var fun = a.say
fun()   //fun.call(window)   
a.say()   //a.say.call(a)  

var b = {
  name:333,
  say:function(fun){
    fun()  //fun.call(window)
  }
}
b.say(a.say)   
b.say = a.say
b.say()   //b.say.call(b)    

13.Es6箭头函数

箭头函数中的this指向外层代码块的this ,它本身没有this指向父级。

var x = 11;
var obj = {
  x:22,
  say:()=>{
    console.log(this.x)   
  }
}
obj.say();  
var obj = {
  birth:1990,
  getAge:function(){
    var b = this.birth;
    var fn = ()=> {
      new Date().getFullYear() - this.birth
    }
    return fn();
  }
}

16. 前端安全

  1. XSS攻击:跨站脚本攻击,页面被注入恶意代码,没有被转义被执行的代码。
    分类:
    储存型XSS攻击:存入到数据库,数据库在返回渲染到页面;
    反射性XSSS攻击:通过a链接或者url地址参数;
    DOM型XSS攻击:代码未经过后台 ,纯前端执行恶意操作的代码;

17. Object.defineProperty 与 proxy

Object.defineProperty

Object.defineProperty(obj,'name',{
  set:function(val){
  },
  get: function(){
  }
})

proxy : ES6为了操作对象引入的API,可以对目标对象读取、函数调用等操作进行拦截,不直接操作对象,通过代理,进行操作。
一个 Proxy 对象由两个部分组成: target(目标对象)、 handler (一个对象,声明了代理 target 的指定行为)

let proxy = new Proxy(target, {
   get: function(target, key) {
        console.log('getting '+key);
        return target[key]; 
    },
    set: function(target, key, value) {
        console.log('setting '+key);
        target[key] = value;
    }
})

两者对比

  1. 对象监听
  1. 监听新增加属性
  1. 无法响应数组操作

18.组件之间传值

  1. 父组件传值子组件
//父组件 
 <son :msg="message"></son>
//子组件
 <div>{{msg}}</div>
export default {
  props:["msg"]
} 
  1. 子组件传值父组件:父组件通过属性值的方法传递给子组件,传递一个函数,回调函数
//子组件
<button @click="sendFather"></button>
  sendFather(){
      this.$emit('sendSon',this.value)
  },
//父组件
 <son @sendSon="getSon"></son>
    getSon(value){
        this.msg = value
    }

//兄弟组件传值eventBus.
eventBus.js
  import Vue from 'vue'
  export default new Vue 
// one组件 (发送)
   import bus from 'eventBus.js'
  <button @click="sendSos">发送</button>
  sendSos(){
      bus.$emit("SOS",this.message)
  },
//two 组件 (接收)
 import bus from 'eventBus.js'
    bus.$on("SOS",(data)=>{
      this.message = data;
    })

19.数组

  1. map的返回一个新数组
  2. forEach没有返回值
  3. filter返回新数组,匹配条件符合的
  4. every数组有一项不满足条件 返回false
  5. some数组有一项满足条件 返回true
  6. push方法返回数组长度

20. 前端性能优化

  1. 首页加载慢的优化
  1. 图片的优化(太多和太大)
  1. 实现webPack打包优化(太多、太大)
  1. 实现CDN加速
  1. 渲染十万条数据如何不造成卡顿

21. 前端webpack打包优化

  1. 优化耗时分析speed-measure-webpack-plugin插件
 npm install -D speed-measure-webpack-plugin

22. 闭包

23.vue3新特性

vue2将业务代码分散到data、methods、mounted里,修改代码 需要反复跳转,所以vue3将其作为优化, 可读性维护性都更高。vue2也曾给出方案Mixin,但是也会遇到命名冲突,不清楚暴露出来变量的作用。
新特性:


image.png
<template>
  <div class="homePage">
    <p>第 {{ year }} 年</p>
    <p>姓名: {{ nickname }}</p>
    <p>年龄: {{ age }}</p>
  </div>
</template>

<script>
import { defineComponent, reactive, ref, toRefs } from "vue";
export default defineComponent({
  setup() {
    const year = ref(0);
    const user = reactive({ nickname: "xiaofan", age: 26, gender: "女" });
    setInterval(() => {
      year.value++;
      user.age++;
    }, 1000);
    return {
      year,
      // 使用toRefs  .可以解构reactive对象转换为属性全部为ref的普通对象,在模板直接使用
      ...toRefs(user),
    };
  },
});
</script>
image.png
import { defineComponent, ref, reactive, toRefs, watch } from "vue";
export default defineComponent({
  setup() {
    const state = reactive({ nickname: "xiaofan", age: 20 });

    setTimeout(() => {
      state.age++;
    }, 1000);

    // 修改age值时会触发 watch的回调
    watch(
      () => state.age,
      (curAge, preAge) => {
        console.log("新值:", curAge, "老值:", preAge);
      }
    );

    return {
      ...toRefs(state),
    };
  },
});

watch 监听ref定义的数据

const year = ref(0);

setTimeout(() => {
  year.value++;
}, 1000);

watch(year, (newVal, oldVal) => {
  console.log("新值:", newVal, "老值:", oldVal);
});

监听多个数据

watch([() => state.age, year], ([curAge, newVal], [preAge, oldVal]) => {
console.log("新值:", curAge, "老值:", preAge); console.log("新值:", newVal,
"老值:", oldVal); });

监听复杂嵌套对象,wacth第三个参数 {deep:true} ;
stop 停止监听,直接调用watch的返回值

watchEffect

  1. watchEffect 不需要手动传入依赖
  2. watchEffect 会先执行一次用来自动收集依赖
  3. watchEffect 无法获取到变化前的值, 只能获取变化后的值
 watchEffect(() => {
        console.log(state);
        console.log(year);
 });
import { ref, Ref, computed } from "vue";

type CountResultProps = {
  count: Ref<number>;
  multiple: Ref<number>;
  increase: (delta?: number) => void;
  decrease: (delta?: number) => void;
};

export default function useCount(initValue = 1): CountResultProps {
  const count = ref(initValue);

  const increase = (delta?: number): void => {
    if (typeof delta !== "undefined") {
      count.value += delta;
    } else {
      count.value += 1;
    }
  };
  const multiple = computed(() => count.value * 2);

  const decrease = (delta?: number): void => {
    if (typeof delta !== "undefined") {
      count.value -= delta;
    } else {
      count.value -= 1;
    }
  };

  return {
    count,
    multiple,
    increase,
    decrease,
  };
}


<template>
  <p>count: {{ count }}</p>
  <p>倍数: {{ multiple }}</p>
  <div>
    <button @click="increase()">加1</button>
    <button @click="decrease()">减一</button>
  </div>
</template>

<script lang="ts">
import useCount from "../hooks/useCount";
 setup() {
    const { count, multiple, increase, decrease } = useCount(10);
        return {
            count,
            multiple,
            increase,
            decrease,
        };
    },
</script>


24. npm发包管理

  1. 组件库项目改造
|-- examples      // 原 src 目录,改成 examples 用作示例展示
|-- packages      // 新增 packages 用于编写存放组件

2.vue.config.js的配置文件

// vue-config.js
module.exports = {
  // 修改 src 目录 为 examples 目录
  pages: {
    index: {
      // page 的入口
      entry: 'examples/main.js',   // 把src 修改为examples
      // 模板来源
      template: 'public/index.html',
      // 在 dist/index.html 的输出
      filename: 'index.html'
    }
  },
  // 扩展 webpack 配置,使 packages 加入编译
  /* chainWebpack 是一个函数,会接收一个基于 webpack-chain 的 ChainableConfig 实例。允许对内部的 webpack 配置进行更细粒度的修改。 */
  chainWebpack: config => {
    config.module
      .rule('js')
      .include
      .add(__dirname + 'packages')  // 注意这里需要绝对路径,所有要拼接__dirname
      .end()
      .use('babel')
      .loader('babel-loader')
      .tap(options => {
        // 修改它的选项...
        return options
      })
  }
}
  1. 编写组件
|——
|——packages
|   |——index.js
|   |——ChanFuEmpty
|      |——index.js
|      |——src
|         |——chanfu-empty.vue
|——
<template>
  <div class="empty">
    <div class="image">
      <img :src="imgUrl" alt="" />
    </div>
    <div class="desc">{{ desc }}</div>
    <slot></slot>
  </div>
</template>
<script>
export default {
  name: "ChanFuEmpty",
  props: {
    desc: {
      type: String,
      default: "暂无数据",
    }
  },
  data() {
    return {};
  },
};
</script>

ChanFuEmpty文件夹内的index.js

import ChanFuEmpty from './src/chanfu-empty.vue'
// 为组件提供 install 安装方法,供按需引入
ChanFuEmpty.install = function (Vue) {
    Vue.component(ChanFuEmpty.name, ChanFuEmpty)
}

// 默认导出组件
export default ChanFuEmpty
  1. packages 文件夹内的index.js
import ChanFuEmpty from './ChanFuEmpty'
import ChanFuFooter from './ChanFuFooter'
// 存储组件列表
const components = [
    ChanFuEmpty,
    ChanFuFooter
]
/* 
  定义install 方法,接收Vue作为参数,如果使用use注册插件,则所有的组件都将被注册
*/
const install = function (Vue) {
    // 判断是否安装
    if (install.installed) { return }
    // 遍历所有组件
    components.map(item => {
        Vue.component(item.name, item)
    })
}
// 判断是否引入文件
if (typeof window !== 'undefined' && window.Vue) {
    install(window.Vue)
}
export default {
    install,
    ChanFuEmpty,
    ChanFuFooter
}

export {
    ChanFuEmpty,
    ChanFuFooter
}

  1. 测试引用
//main.js
import ChanFuComps from "./../packages/index";
Vue.use(ChanFuComps)

//app.vue
    <ChanFuFooter />
  1. package.json 中新增一条编译为库的命令
"scripts": {
    // ...
    "lib": "vue-cli-service build --target lib --name vcolorpicker --dest lib packages/index.js"
}
  1. 执行编译库命令
npm run lib
  1. 配置 package.json 文件中发布到 npm 的字段
name: 包名,该名字是唯一的。可在 npm 官网搜索名字,如果存在则需换个名字。
version: 版本号,每次发布至 npm 需要修改版本号,不能和历史版本号相同。
description: 描述。
main: 入口文件,该字段需指向我们最终编译后的包文件。
keyword:关键字,以空格分离希望用户最终搜索的词。
author:作者
private:是否私有,需要修改为 false 才能发布到 npm
license: 开源协议
  1. 登录npm
npm config set registry https://registry.npmjs.org 
npm login
  1. 发布到npm
npm publish
  1. 项目 安装引用
https://www.npmjs.com/package/chanfu-components

25. 深浅拷贝

  1. 数据类型的存储方式:
  1. 不同类型的复制方式
  1. 深拷贝:在堆中重新分配内存,不同的地址,相同的值,互不影响
    如果将一个引用数据类型 实现为深拷贝

function deepCopy(obj) {
  if (!obj && typeof obj !== 'object') {
    throw new Error('error arguments');
  }
  // const targetObj = obj.constructor === Array ? [] : {};
  const targetObj = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    
    //只对对象自有属性进行拷贝
    if (obj.hasOwnProperty(key)) {
      if (obj[key] && typeof obj[key] === 'object') {
        targetObj[key] = deepCopy(obj[key]);
      } else {
        targetObj[key] = obj[key];
      }
    }
  }
  return targetObj;
}

27. webpack打包优化

  1. webpack打包速度分析
npm install --save-dev webpack-bundle-analyzer
//vue.config.js
const {BundleAnalyzerPlugin} = require("webpack-bundle-analyzer")
 configureWebpack: {
    plugins:[
      new BundleAnalyzerPlugin({
        generateStatsFile: true 
      })
    ]
  }
// 生成stats.json文件上传此网站进行分析 http://webpack.github.io/analyse/#warnings
  1. gzip压缩
    // gzip压缩
npm install compression-webpack-plugin@6.1.0 --save-dev      cli4用这个版本
const CompressionWebpackPlugin = require('compression-webpack-plugin')
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i
new CompressionWebpackPlugin({
        filename: "[path].gz[query]", //目标资源名称
        algorithm: "gzip",
        test: productionGzipExtensions, //处理所有匹配此 {RegExp} 的资源
        threshold: 10240,//只处理比这个值大的资源。按字节计算(楼主设置10K以上进行压缩)
        minRatio: 0.8 //只有压缩率比这个值小的资源才会被处理
      })
// nginx也需要开启gzip设置浏览器解析.gz文件

异步编程方案

六种异步方案, 重点是 Promise、Async、发布 / 订阅原理实现-白鹤资源网 (wcrane.cn)

vue源码原理

网络相关

前端工程化知识

Lerna的Monorepo,微前端
微前端qiankun+vue - 简书 (jianshu.com)
目标是最完善的微前端解决方案 - qiankun 2.0 - 知乎 (zhihu.com)

25. typescript

// 1.泛型
type Generics<T> = {
    name: string
    age: number
    sex: T
}

const my: Generics<'nan'> = {
  name: '1',
  age: 1,
  sex: 'nan'
}
// 2. 接口
interface CatInfo {
  age: number;
  breed: string;
}
function fun ( obj: CatInfo) {
}
fun({
    age: 1,
    breed: '1'
})
// 3.Record  将一个类型的属性值映射到某一个值上
type CatName = "miffy" | "boris" | "mordred";
const cats: Record<CatName, CatInfo> = {
  miffy: { age: 10, breed: "Persian" },
  boris: { age: 5, breed: "Maine Coon" },
  mordred: { age: 16, breed: "British Shorthair" },
};
// 4. Pick | Omit
interface Todo {
  title: string;
  description: string;
  completed: boolean;
}
type TodoPreview1 = Pick<Todo, "title" | "completed">;   // 选择包含的key来构造出新的类型
type TodoPreview2 = Omit<Todo, "title" | "completed">;   // Omit忽略删除选中的key
const todo: TodoPreview1 = {
  title: "Clean room",
  completed: false,
};
// 5.不知道key是什么,但是知道key与value的类型
interface StringArray {
  [index: number]: string;
}
// 6.不知道属性的长度,用[propName:string]: string | null 联合类型来处理剩余属性,剩余属性必须包含前面所有的属性类型
interface PropArray {
  id: number;
  [propName: string]: string | number;
}
const t1: PropArray = {
  name: 'a',
  id: 123,
  a: 123
}

// 7.interface继承
interface BasicAddress {
  name?: string;
  street: string;
  city: string;
  country: string;
  postalCode: string;
}
 
interface AddressWithUnit extends BasicAddress {
  unit: string;
}
// 8.合并   interface 与type

  interface Colorful {
    color: string;
  }
  interface Circle {
    radius: number;
  }
  interface ColorfulCircle extends Colorful, Circle {}
  type ColorfulCircle = Colorful & Circle;

  const cc: ColorfulCircle = {
    color: "red",
    radius: 42,
  };

// 9.不确定类型unknown
interface Box {
  contents: unknown;
}
 // 10.联合类型
interface T1 {
  name: string | number
}
const a: T1 = {
  name: 1
}
a.name = a.name + ''

26. vue.store

const user = {
  state: {
    token: getToken(),
    name: '',
    avatar: '',
    roles: [],
    permissions: []
  },

  mutations: {
    SET_TOKEN: (state, token) => {
      state.token = token
    },
    SET_NAME: (state, name) => {
      state.name = name
    },
    SET_AVATAR: (state, avatar) => {
      state.avatar = avatar
    },
    SET_ROLES: (state, roles) => {
      state.roles = roles
    },
    SET_PERMISSIONS: (state, permissions) => {
      state.permissions = permissions
    }
  },

  actions: {
    // 登录
    Login({ commit }, userInfo) {
      const username = userInfo.username.trim()
      const password = userInfo.password
      const code = userInfo.code
      const uuid = userInfo.uuid
      return new Promise((resolve, reject) => {
        login(username, password, code, uuid).then(res => {
          setToken(res.token)
          commit('SET_TOKEN', res.token)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },

    // 获取用户信息
    GetInfo({ commit, state }) {
      return new Promise((resolve, reject) => {
        getInfo().then(res => {
          const user = res.user
          const avatar = (user.avatar == "" || user.avatar == null) ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar;
          if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组
            commit('SET_ROLES', res.roles)
            commit('SET_PERMISSIONS', res.permissions)
          } else {
            commit('SET_ROLES', ['ROLE_DEFAULT'])
          }
          commit('SET_NAME', user.userName)
          commit('SET_AVATAR', avatar)
          resolve(res)
        }).catch(error => {
          reject(error)
        })
      })
    },

    // 退出系统
    LogOut({ commit, state }) {
      return new Promise((resolve, reject) => {
        logout(state.token).then(() => {
          commit('SET_TOKEN', '')
          commit('SET_ROLES', [])
          commit('SET_PERMISSIONS', [])
          removeToken()
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },

    // 前端 登出
    FedLogOut({ commit }) {
      return new Promise(resolve => {
        commit('SET_TOKEN', '')
        removeToken()
        resolve()
      })
    }
  }
}

export default user

 this.$store.dispatch("Login", this.loginForm)
            .then(() => {
              this.$router.push({ path: this.redirect || "/" }).catch(() => {});
            })
            .catch(() => {
              this.loading = false;
              if (this.captchaOnOff) {
                this.getCode();
              }
            });
上一篇下一篇

猜你喜欢

热点阅读