Compiled some frequently asked interview questions

interview questions

Array articles

What are the methods for deduplication of arrays, and how does native js use for loops to achieve it?

1. Use the Set method in ES6 to deduplicate (Array.from is to convert the set object to an array)

1      let arr = [1,0,0,2,9,8,3,1];
2           function unique(arr) {
3                 return Array.from(new Set(arr))
4           }
5           console.log(unique(arr));   // [1,0,2,9,8,3]
  or
6      console.log(...new Set(arr)); // [1,0,2,9,8,3]
复制代码

2. Use the indexOf method of the array to deduplicate

Note: array.indexOf(item, statt) returns the position of a specified element in the array, otherwise -1

 1      var arr =[1,-5,-4,0,-4,7,7,3];
 2                 function unique(arr){
 3                    var arr1 = [];       // 新建一个数组来存放arr中的值
 4                    for(var i=0,len=arr.length;i<len;i++){
 5                        if(arr1.indexOf(arr[i]) === -1){
 6                            arr1.push(arr[i]);
 7                        }
 8                    }
 9                    return arr1;
10                 }
11                 console.log(unique(arr));    // 1, -5, -4, 0, 7, 3
复制代码

3. Use the sort method of the array to deduplicate (adjacent element comparison method)

Note: array.sort( function ) parameter must be a function, optional, default ascending order

        var arr =  [5,7,1,8,1,8,3,4,9,7];
                function unique( arr ){
                    arr = arr.sort();
                    console.log(arr);
​
                    var arr1 = [arr[0]];
                    for(var i=1,len=arr.length;i<len;i++){
                        if(arr[i] !== arr[i-1]){
                            arr1.push(arr[i]);
                        }
                    }
                    return arr1;
                }
                console.log(unique(arr))l;   //  1, 1, 3, 4, 5, 7, 7, 8, 8, 9
复制代码

4. Use the includes of the array to deduplicate

Note: arr.includes (specified element (required), specified index value (optional, the default value is 0)), returns true if there is a value, false if not

 1          var arr = [-1,0,8,-3,-1,5,5,7];
 2                 function unique( arr ){
 3                     var arr1 = [];
 4                     for(var i=0,len=arr.length;i<len;i++){
 5                         if( !arr1.includes( arr[i] ) ){      // 检索arr1中是否含有arr中的值
 6                             arr1.push(arr[i]);
 7                         }
 8                     }
 9                     return arr1;
10                 }
11                 console.log(unique(arr));      //  -1, 0, 8, -3, 5, 7
复制代码

5. Use the filter method of the array to deduplicate

Note: The filter() method creates a new array, and the elements in the new array are checked by checking all the elements in the specified array that meet the conditions, array.filter(function(currentValue,index,arr), thisValue)

    currentValue: the value of the current element (required parameter), index: the index value of the current element (optional), arr: the array object to which the current element belongs (optional), thisValue: the object is used as the execution callback and passed to the function , used as the value of "this", default undefined (optional)

 1              var arr = [1,2,8,9,5,8,4,0,4];
 2                 /*
 3                     模拟: 原始数组:[1,2,8,9,5,8,4,0,4]
 4                             索引值:0,1,2,3,4,5,6,7,8
 5                           伪新数组:[1,2,8,9,5,8,4,0,4]
 6                     使用indexOf方法找到数组中的元素在元素在中第一次出现的索引值
 7                             索引值:0,1,2,3,4,2,6,7,6
 8                         返回前后索引值相同的元素:
 9                           新数组:[1,2,8,9,5,4,0]        
10                 */
11                 function unique( arr ){
12                     // 如果新数组的当前元素的索引值 == 该元素在原始数组中的第一个索引,则返回当前元素
13                     return arr.filter(function(item,index){
14                         return arr.indexOf(item,0) === index;
15                     });
16                 }
17                 console.log(unique(arr));    //  1, 2, 8, 9, 5, 4, 0
复制代码

6. Use function recursion to deduplicate

 1           var arr = [1,1,5,6,0,9,3,0,6]
 2                  function unique( arr ){
 3                      var arr1 = arr;
 4                       var len = arr1.length;
 5                       arr1.sort((a,b)=>{
 6                           return a-b
 7                       })
 8                       function loop(index){
 9                           if(index >= 1){
10                              if(arr1[index] === arr1[index-1] ){
11                                  arr1.splice(index,1);
12                             }
13                              loop(index - 1);  // 递归loop,然后数组去重
14                         }
15                     }
16                     loop(len-1);   
17                      return arr1
18                  }
19                  console.log(unique(arr));    //   0, 1, 3, 5, 6, 9
复制代码

7. Use the Map method in ES6 to deduplicate

 1              /*
 2                   创建一个空Map数据结构,遍历需要去重的数组,把数组的每一个元素作为key存到Map中。由于Map中不会出现相同的key值,所以最终得到的就是去重后的结果。
 3                 */
 4      let arr = [1, 0, 8, 3, -9, 1, 0, -9, 7]
 5            function unique(arr) {
 6                 let map = new Map();
 7                 console.log(map)
 8                 //let arr1 = new Array();      // 数组用于返回结果
 9                 let arr1 = []
10                     for (let i = 0, len = arr.length; i < len; i++) {
11                         if (map.has(arr[i])) {      // 判断是否存在该key值
12                             map.set(arr[i], true);
13                         }
14                         else {
15                             map.set(arr[i], false);
16                             arr1.push(arr[i]);
17                         }
18                     }
19                     return arr1;
20                 }
21          console.log(unique(arr)); // 1, 0, 8, 3, -9, 7
复制代码

8. Double for loop + splice()

let arr = [1, 5, 3, 3, 5]
for (let i = 0; i < arr.length; i++) {
    for (let j = i + 1; j < i + arr.length; j++) {
        if (arr[i] === arr[j]) {
          // 第一个等同于第二个,splice方法删除第二个
            arr.splice(j, 1)
            j--
        }
    }
​
}
console.log(arr);  // [1, 5, 3]
复制代码

9. js double for loop

var arr=[1,2,2,3,5,4,5]
let result=[]
for(let i=0;i<arr.length;i++){
  // console.log(i); 每个数的下标
  for(var j=0;j<result.length;j++){
    // 如果arr的下标的数与result的数相等,那就退出循环
    if(arr[i]===result[j]){
      break
    }
  }
  console.log(j);
  // 如果j===result.length相等,就把对应的元素添加到result数组里
  if(j===result.length){
    result.push(arr[i])
  }
}
console.log(result); // [ 1, 2, 3, 5, 4 ]
复制代码

Difference between Set/Map

Set类似于数组,但是它里面每一项的值是唯一的,没有重复的值,Set是一个构造函数,用来生成set的数据结构 .数组去重(利用扩展运算符)

Map对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。构造函数Map可以接受一个数组作为参数,数组的成员是一个个表示键值对的数组。注意Map里面也不可以放重复的项。

综上所述,主要有一下几个区别

1.Map是键值对,Set是值的集合,当然键和值可以是任何的值

2.Map可以通过get方法获取值,而set不能因为它只有值;

3.都能通过迭代器进行for…of遍历;

4.Set的值是唯一的可以做数组去重,Map由于没有格式限制,可以做数据存储

5.map和set都是stl中的关联容器,map以键值对的形式存储,key=value组成pair,是一组映射关系。set只有值,可以认为只有一个数据,并且set中元素不可以重复且自动排序。

ES6的理解

0.ES6是ECMAScript 6的缩写简称,2015 年 6 月,ECMAScript 6 正式通过,

1.变量声明let与const (1).变量不会提升 (2).有块级作用域

2.解构赋值语法 : 其实就是变量赋值语法的简写形式 (取出 对象的属性 赋值 给变量)

3.箭头函数 其实是 function 关键字的简写形式

4.拓展运算符: ... ( 作用:类似于 对象遍历的一种简写形式 )

5.数组迭代方法

数组排序

1.sort():对数组的元素进行从小到大来排序(会改变原来的数组) 默认排序顺序是在将元素转换为字符串按照Unicode 编码,从小到大进行排序

//一维数组排序
var arr=[1,5,7,9,16,2,4];
arr.sort(function(a,b){
    return b-a;  //降序排列,return a-b; —>升序排列
})  //括号里不写回调函数,则默认按照字母逐位升序排列,结果为[1,16,2,4,5,7,9]
复制代码

2.冒泡排序(每一趟找出最大的)

两个相邻的数比较大小,将两个数中较大的数往右边放,小的往左边放

//性能一般
let arr=[1,5,7,9,16,2,4];
//冒泡排序,每一趟找出最大的,总共比较次数为arr.length-1次,每次的比较次数为arr.length-1次,依次递减
let len = arr.length;
for(let k = 0; k < len - 1; k++) {
    for(let m = 0; m < len - k - 1; m++) {
        if(arr[m] > arr[m+1]){
            let val = arr[m];
            arr[m] = arr[m+1];
            arr[m+1] = val;
        }
    }
}
 
console.log(arr)
复制代码

3.插入排序

var arr=[45,1,32,21,56,87,43,12,34,45];
    for(var i=0;i<arr.length;i++){
    var n=i;
    while(arr[n]>arr[n+1] && n>=0){
        var temp=arr[n];
        arr[n]=arr[n+1];
        arr[n+1]=temp;
        n--;
    }
}
复制代码

4.希尔排序(性能最好的排序)

function xier(arr){
    var interval = parseInt(arr.length / 2);  //分组间隔设置
    while(interval > 0){
        for(var i = 0 ; i < arr.length ; i ++){
            var n = i;
            while(arr[n] < arr[n - interval] && n > 0){
                var temp = arr[n];
                arr[n] = arr[n - interval];
                arr[n - interval] = temp;
                n = n - interval;
            }
        }
        interval = parseInt(interval / 2);
    }
    return arr;
}
xier([12,9,38,44,7,98,35,59,49,88,38]);
复制代码

数组合并说出最少三种方法

1.es6 利用 展开运算符 “…”

2.利用 数组方法 concat,合并两个或多个数组 (会造成内存浪费,不能处理嵌套数组) **

改变原数组

        var arr1 = [0, 1, 2];
        var arr2 = [3, 4, 5];
        arr1 = arr1.concat(arr2)
​
复制代码

不改变原数组

    var arr1 = [0, 1, 2];
    var arr2 = [3, 4, 5];
    var arr3 = arr1.concat(arr2)
复制代码

使用扩展操作符或array.concat()执行的合并将创建一个新数组。但是,有时不想创建一个新数组,而是想将它合并到一些现有的数组中。下面的方法执行一种可变的合并方法。

3.使用array.push()方法进行合并

array.push(item)方法将一个项加入到数组的末尾,改变了调用该方法的数组:

const heroes = ['Batman'];
​
heroes.push('Superman');
​
heroes; // ['Batman', 'Superman']
​
复制代码

数组 push ,pop , map, unshift?

1.push: 数组尾部添加 push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度

2.pop:数组尾部删除 pop() 方法用于删除并返回数组的最后一个元素

3.unshift数组头部添加 unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度

4.map:map()方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。

vue篇

Vue2 中 v-for 和 v-if 为什么不建议放一行?为什么?怎么处理?Vue3 呢

官网回答:vuejs.bootcss.com/style-guide…

为什么 :当 Vue 处理指令时,v-forv-if 具有更高的优先级,这意味着 v-if 将分别重复运行于 每个 v-for 循环中,即先运行 v-for 的循环,然后在每一个 v-for 的循环中,再进行 v-if 的条件对比,而v-if是通过创建和销毁dom元素来控制元素的显示与隐藏,所以就会不停的去创建和销毁元素,会造成性能问题,影响速度

处理: 为了避免这个问题,可以用计算属性代替.样只会在users发生改变时才会执行这段遍历的逻辑,和之前相比,避免了不必要的性能浪费。( 或者:在v-for的外层或内层包裹一个元素来使用v-if ) 如果条件出现再循环内部,可通过计算属性 computed 提前过滤掉那些不需要显示的项

好处: 过滤后的列表只会在 users 数组发生相关变化时才被重新运算,过滤更高效。

使用 v-for="user in activeUsers" 之后,我们在渲染的时候只遍历活跃用户,渲染更高效。

解耦渲染层的逻辑,可维护性 (对逻辑的更改和扩展) 更强。

vue3: vue3中v-if的优先级高于v-for,如果写在同一个标签中会先使用v-if,而v-if的数据来自v-for的循环子项会导致出错,因为数据还未声明.

Vue 中的 data 为什么要求是一个函数?

多个组件复用时,每次调用data函数的时候都会return一个新的对象,它们的内存地址都是不一样的,这样就不会相互影响。为了保证组件的独立性和可复用性

computed 和 watch 的区别

computed:计算属性为了简化计算复杂度,具有缓存不能执行异步代码,必须同步执行,适用于计算比较消耗性能的计算场景、必须要有一个返回值

watch: 侦听器,检测属性值,只要属性值改变,就会触发监听。

echarts怎么挂载

一、安装并全局引入

1、通过npm获取echarts

npm install echarts --save
复制代码

2、在 main.js 中全局配置

首先在main.js中引入echarts,将其绑定到vue原型上:

  1. import echarts from 'echarts'
  2. Vue.prototype.$echarts = echarts;

3.创建一个dom容器

<div id="main" style="width: 750px; height: 400px"></div>
复制代码

// 基于准备好的dom,初始化echarts实例

var myChart = echarts.init(document.getElementById("main"));

组件传值

1.父子组件传值:

父--->子 : 通过props 传递,子组件接收

子---->父 : 通过一个自定义事件,然后this.$emit传递给父组件

2.兄弟组件传值 : eventBus事件总线

在全局挂载enentBus,创建一个谁都能找到的事件总线, 通过$emit 和 $on进行传递和接收。

  1. 后代组件传值 : 通过provide 和 inject。爷爷定义一个属性 provide,是一个函数,用来给后代接收。 孙子用 inject 接收。

组件缓存

keep-alive:

语法:两个属性: include 和 exclude

1.先给对应组件设置name属性名,

2.再把名字写到 include/exclude位置

include==包含--缓存

exclude==不包含--不缓存

js篇

闭包

闭包(closure):指有权访问另外一个函数作用域中的变量的函数。简单的说就是,一个作用域可以访问另外一个函数内部的局部变量。函数+上下文

function fn() {
    var num = 10;
    function fun() {
        console.log(num); 
    }
    return fun;
}
var f = fn(); 
f();
复制代码

作用:延长变量作用域、在函数的外部可以访问函数内部的局部变量,容易造成内层泄露,因为闭包中的局部变量永远不会被回收. 在实际开发中,闭包最大的作用就是用来 变量私有

深拷贝,浅拷贝

浅拷贝:基本数据类型拷贝的值,引用数据类型拷贝的是内存地址。原对象和拷贝对象还是会互相影响。两个对象指向同一内存地址。

如何实现:1.Object.assign

2.数组的 slice 和 concat 方法 Array.prototype.concat(),Array.prototype.slice()

3.扩展运算符

4.函数库Lodash的_.clone方法

深拷贝:深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存,拷贝前后两个对象互不影响

如何实现:

1.一行代码: 用 JSON.stringify 把对象转换成字符串,再用 JSON.parse 把字符串转换成新的对象。 但是这种方式存在弊端,会忽略undefinedsymbol函数 ;NaNInfinity-Infinity 会被序列化为 null;

const newObj = JSON.parse(JSON.stringify(obj))
复制代码
  1. Lodash.cloneDeep 实现深拷贝
  2. 使用递归的方式实现深拷贝

作用域

作用域链

js 在执⾏过程中会创建一个个的可执⾏上下⽂ 每个可执⾏上下⽂的词法环境中包含了对外部词法环境的引⽤

简而言之: 函数内部 可以访问到 函数外部作用域的变量, 而外部函数还可以访问到全局作用域的变量,

函数内访问变量时,优先使用自己内部声明的变量;如果没有,就访问外部函数作用域的变量,如果也没有,则继续往外找。。直到找到全局。

垃圾回收

垃圾回收:使用完毕,由垃圾回收自动回收不再使用的内存===( 释放不在使用的内存 )

全局变量一般不会回收, 一般局部变量的的值, 不用了, 会被自动回收掉

两种常见的浏览器垃圾回收算法: 引用计数( IE ) 和 标记清除法

标记清除法: 从js根部,如法访问到,无法触及(谁都找不到这块空间),这块空间就是垃圾,需要被回收。

原型链

每一个实例对象上有一个proto属性,指向的构造函数的原型对象,构造函数的原型

对象也是一个对象,也有proto属性,通过这个属性可以访问对象的原型,这样一层一层往上找的过程就形成了原型链。

判断是否是数组

方法一: 使用 toString 方法 :Object.prototype.toString.call(arr)

方法二: 使用 ES6 新增的 Array.isArray 方法 : Array.isArray(arr)

this的指向

1,普通函数,定时器自调用函数中的this指向window.

2.、事件中的this指向事件的调用者 ==谁调用我,我就指向谁.

3.、 构造函数中this和原型对象中的this,都是指向构造函数new 出来实例对象

4 . 箭头函数没有this

Promise

Promise 是异步编程的一种解决方案,它可以解决回调地狱的问题。Promise 是一个对象,可以从该对象获取异步操作的消息。

promise的三个状态: pending(默认) fulfilled(成功) rejected(失败)

如何识别数组和对象

1.通过constructor ==访问构造函数,我们可通过这个属性判断变量的数据类型

2.通过Object.prototype.toString.call()

3.通过instanceof

4.ES5特地新增isArray()检测变量是否是数组

new都做了那些事

1.创建一个空对象

2.this指向这个对象 (指向了构造函数的prototype属性)

3.给这个对象赋值

4.返回这个对象

防抖和节流

1.防抖:指在一段时间内,无论触发了多少次回调,都只执行最后一次。

原理:利用定时器,函数在第一次执行时设定一个定时器,并且通过闭包缓存起来,之后调用时发现已经设定过定时器就清空之前的定时器,并重新设定一个新的定时器,如果存在没有被清空的定时器,当定时器计时结束后触发函数执行。

/*
 * 防抖函数
 * @param fn 事件触发的操作
 * @param delay 多少毫秒内连续触发事件,不会执行
 * @returns {Function}
*/
function debounce(fn,delay) {
    let timer = null; //通过闭包缓存了一个定时器
    return function () {
        const args = [...arguments];
        const that = this
        timer && clearTimeout(timer);
        timer = setTimeout(function () {
            fn.apply(that,args);
        },delay);
    }
}
window.onscroll = debounce(function () {
    let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
    console.log('滚动条位置:' + scrollTop);
},200)
​
​
复制代码

2.节流:在一定时间间隔内,只执行第一次。函数节流非常适用于函数被频繁调用的场景,例如:window.onresize() 事件、mousemove 事件、上传进度等情况

原理: 实现原理就是通过一个布尔类型变量来判断是否可执行回调,当变量为true时,生成一个定时器,同时将变量取反通过闭包保存起来,当定时器执行完回调后,再将变量变为true,在变量为false期间,调用节流函数不会生成定时器。

​
/**
 * 节流函数
 * @param fn 事件触发的操作
 * @param delay 间隔多少毫秒需要触发一次事件
 * @returns {Function}
 */
function throttle(fn, delay) {
    let flag = true;
    return function () {
        if (!flag) {
            return;
        }
        const that = this
        const args = [...arguments];
        flag = false;
        setTimeout(() => {
            fn.apply(that, args);
            flag = true;
        }, delay);
    }
}
window.onscroll = debounce(function () {
    let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
    console.log('滚动条位置:' + scrollTop);
},200)
​
复制代码

使用场景:1.滚动事件 2.输入的模糊搜索 3.轮播图切换 4.点击操作

事件循环机制 Eventloop

JavaScript是一个单线程的脚本语言。异步任务交给浏览器处理,

微任务(Microtasks)、宏任务(task)皆是异步任务,执行顺序如下:

同步任务===>执行单个宏任务===>先执行宏任务里的微任务===>宏任务

宏任务: 1.主线程上的执行栈中所有的代码块

2.setTimeout

3.setInterval

4.Ajax

5.事件

微任务: 1.Promise.then

2.process.nextTick(Node.js 环境)

arguments

1.什么是arguments?

在函数调用的时候,浏览器每次都会传递进两个隐式参数:

一个是函数的上下文对象this,另一个则是封装实参的类数组对象arguments。arguments 是一个类数组对象,是函数实参的集合,是一个伪数组。

2.arguments方法:

一:转数组 Array.from() , [...arguments]

function fun2() {
 let len = arguments.length;
 let newArr = Array.from(arguments);
 newArr.push(1);
 console.log(newArr)
 }
fun2("a", 0, { name: "cao" });
输出:['a',0,{ foo: "Hello, arguments" },1]
​
复制代码
function fun2() {
 let newArr = [...arguments];
 newArr.push(1)
 console.log(newArr)
}
fun2("a", 0, { name: "cao" });
输出:['a',0,{ foo: "Hello, arguments" },1]
​
复制代码

二:调用原型方法: Array.prototype.slice.call(arguments) ,[].slice.call(arguments)

function fun2() {
 let len = arguments.length;
 let newArr = Array.prototype.slice.call(arguments);//用的数组原型
 newArr.push(1)
 console.log(newArr)
}
fun2("a", 0, { name: "cao" });
输出:['a',0,{ foo: "Hello, arguments" },1]
​
复制代码
function fun2() {
  let len = arguments.length;
  let newArr = [].slice.call(arguments);//用的数组
  newArr.push(1);
  console.log(newArr)
}
fun2("a", 0, { name: "cao" });
输出:['a',0,{ foo: "Hello, arguments" },1]
​
复制代码

3.箭头函数没有arguments。 使用剩余参数表示法...rest

Html

水平垂直居中

一: 绝对定位和负magin值

二: 绝对定位 + transform

三: flex布局

内联元素居中布局:

  1. 水平居中
  • 行内元素可设置:text-align: center;
  • flex布局设置父元素:display: flex; justify-content: center;
  1. 垂直居中
  • 单行文本父元素确认高度:height === line-height
  • 多行文本父元素确认高度:disaply: table-cell; vertical-align: middle;

块级元素居中布局

  1. 水平居中
  • 定宽: margin: 0 auto;
  • 不定宽: 参考上诉例子中不定宽高例子。
  1. 垂直居中
  • position: absolute设置left、top、margin-left、margin-to(定高);
  • position: fixed设置margin: auto(定高);
  • display: table-cell;
  • transform: translate(x, y);
  • flex(不定高,不定宽);
  • grid(不定高,不定宽),兼容性相对比较差;

绝对定位和相对定位的区别

相对定位: 是相对于它本身所在的文档流的位置进行定位,不会脱离文档流,定位前的位置依然保留。

绝对定位: 相对于它最近的设置过position某些属性(如:relative、obsolute、fixed、sticky )的父级结点来进行定位。如果祖先节点中没有设置,默认相对于浏览器窗口定位。会脱离文档流,文档中不会保留其定位前的位置

  1. relation 相对定位,相对于自己的文档流的位置定位,不会脱离文档流
  2. absolute 绝对定位,相对于具有relative、obsolute、fixed、sticky 的最近的父容器来定位,会脱离文档流
  3. fixed 绝对定位(通常叫做:固定定位),相对于window位置定位,会脱离文档流

http

http的缓存

HTTP 缓存分为 2 种,一种是强缓存,另一种是协商缓存。主要作用是可以加快资源获取速度,提升用户体验,减少网络传输,缓解服务端的压力。

强缓存 (验证缓存是否过期) :(进行判断缓存是否有效, 就是判断资源是否过期, 如果未过期, 直接用缓存)

协商缓存:若未命中强缓存(强缓存过期了),则浏览器会将请求发送至服务器。

服务器根据http头信息中的Last-Modify/If-Modify-SinceEtag/If-None-Match来判断是否命中协商缓存。

如果命中,则http返回码为304 (你本地之前加载的资源是有效的),浏览器从缓存中加载资源。

css

css怎么做动画

css 实现动画的三种方式总结:

  1. transition 过渡
  2. transform 变形 。
  3. animation 关键帧动画

1.transition 过渡动画:

1. 语法:
     1. transition: 属性是个复合属性 。
     2. transition: property duration timing-function delay
     3. 默认值为: transition: all 0 ease 0;
​
2. 属性介绍:
     1. transition-property: 规定设置过渡效果的 css 属性名称 。
     2. transition-duration: 规定完成过渡效果需要多少秒或毫秒 。
     3. transition-timing-function: 指定过渡函数, 规定速度效果的速度曲线 。
     4. transition-delay: 指定开始出现的延迟时间 。
   
3. 子属性详解:
     1. transition-property: none |all |property;
        1. 值为 none 时, 没有属性会获得过渡效果
        2. 值为 all 时, 所有属性都将获得过渡效果
        3. 值为指定的 css 属性应用过渡效果, 多个属性用逗号隔开
        4. css 属性实际使用时的设置:
           1. color: background-color, border-color, color, outline-color ;
           2. length: 真实的数字 如:word-spacing,width,vertical-align,top,right,bottom,left,padding,outline-width,margin,min-width,min-height,max-width,max-height,line-height,height,border-width,border-spacing,
           3. integer: 离散步骤(整个数字), 在真实的数字空间, 以及使用 floor() 转换为整数时发生 如: outline-offset,z-index 。
           4. number: 真实的(浮点型)数值, 如:zoom, opacity, font-weight 。
           5. rectangle: 通过 x, y, width 和 height(转为数值)变换,如: crop 。
           6. visibility: 离散步骤, 在0到1数字范围之内, 0表示“隐藏”, 1表示完全"显示"; 如: visibility 。
           7. shadow: 作用于 color, x, y 和 blur(模糊)属性; 如:text-shadow 。
           8. background-image: 通过每次停止时的位置和颜色进行变化 。 它们必须有相同的类型(放射状的或是线性的)和相同的停止数值以便执行动画 。
​
     2. transition-duration
        1. transition-duration: time;
        2. 该属性主要用来设置一个属性过渡到另一个属性所需的时间, 也就是从旧属性过渡到新属性花费的时间长度, 俗称持续时间
​
     3. transition-timing-function: linear| ease| ease-in| ease-out| ease-in-out| cubic-bezier(n,n,n,n);
        1. 该属性指的是过渡的 “缓动函数” 。 主要用来指定浏览器的过渡速度, 以及过渡期间的操作进展情况 。
        2.  注意: 值 cubic-bezier(n,n,n,n) 可以定义自己的值, 如 cubic-bezier(0.42,0,0.58,1) 。
        3. 各个子属性详细解析:
                 1. linear: 匀速 (约等于)== cubic-bezier(0,0,1,1) 。
                 2. ease: 慢快慢  (约等于)== cubic-bezier(0.25,0.1,0.25,0.1) 。
                 3. ease-in: 慢速开始的过渡 (约等于)== cubic-bezier(0.45,0.,1,1) 。
                 4. ease-out: 慢速结束的过渡 (约等于)== cubic-bezier(0,0.,0.58,1) 。
                 5. ease-in-out: 慢速开始和结束的过渡 (约等于)== cubic-bezier(0.45,0.,0.58,1) 。
                 6. cubic-bezier(n,n,n,n): 在 cubic-bezier 函数中定义自己的值; 可能的值是0~1之间的数值 。
            
        4. transition-delay
            1. 这个属性没什么说的了, 就是过渡效果开始前的延迟时间, 单位秒或者毫秒
​
​
复制代码

2.transform 变形

1. 可以利用 transform 功能来实现文字或图像的 旋转、缩放、倾斜、移动 这四种类型的变形处理
     1. 旋转 rotate
            1. 用法: transform: rotate(45deg);
            2. 提供一个参数 “角度”, 单位 deg 为度的意思, 正数为顺时针旋转, 负数为逆时针旋转, 上述代码作用是顺时针旋转45度
​
     2. 缩放 scale
            1. 用法: transform: scale(0.5)  或者  transform: scale(0.5, 2);
            2. 一个参数时: 表示水平和垂直同时缩放该倍率
            3. 两个参数时: 第一个参数指定水平方向的缩放倍率, 第二个参数指定垂直方向的缩放倍率 。
​
     3. 倾斜 skew
            1. 用法: transform: skew(30deg)  或者 transform: skew(30deg, 30deg);
            2. 一个参数时: 表示水平方向的倾斜角度 。
            3. 两个参数时: 第一个参数表示水平方向的倾斜角度, 第二个参数表示垂直方向的倾斜角度 。
            4. skew 的默认原点 transform-origin 是这个物件的中心点
​
     4. 移动 translate
            1. 用法: transform: translate(45px)  或者 transform: translate(45px, 150px);
            2. 一个参数时: 表示水平方向的移动距离;
            3. 两个参数时: 第一个参数表示水平方向的移动距离, 第二个参数表示垂直方向的移动距离 。
​
2. 基准点 transform-origin
     1. 在使用 transform 方法进行文字或图像的变形时, 是以元素的中心点为基准点进行的 。 使用 transform-origin 属性, 可以改变变形的基准点 
     2. 用法: transform-origin: 10px 10px;
     3. 表示相对左上角原点的距离, 单位 px, 第一个参数表示相对左上角原点水平方向的距离, 第二个参数表示相对左上角原点垂直方向的距离;
     4. 两个参数除了可以设置为具体的像素值, 其中第一个参数可以指定为 left、center、right, 第二个参数可以指定为 top、center、bottom。
​
3. 多方法组合变形
     1. 用法: transform: rotate(45deg) scale(0.5) skew(30deg, 30deg) translate(100px, 100px);
     2. 这四种变形方法顺序可以随意, 但不同的顺序导致变形结果不同, 原因是变形的顺序是从左到右依次进行
​
​
复制代码

3.animation 关键帧动画

1. 在 CSS3 中创建动画, 您需要学习 @keyframes 规则 。
​
2. @keyframes 规则用于创建动画 。 在 @keyframes 中规定某项 CSS 样式, 就能创建由当前样式逐渐改为新样式的动画效果 。
​
3. 必须定义动画的名称和时长 。 如果忽略时长, 则动画不会允许, 因为默认值是 0。
​
4. 请用百分比来规定变化发生的时间, 或用关键词 "from" 和 "to", 等同于 0% 和 100% 。
​
5. 语法: animation: name duration timing-function delay iteration-count direction;
     1. animation-name    规定需要绑定到选择器的 keyframe 名称*
     2. animation-duration   规定动画完成一个周期所花费的秒或毫秒。默认是 0。
     3. animation-timing-function    规定动画的速度曲线。 默认是 "ease"。
        1. linear   动画从头到尾的速度是相同的。
        2. ease 默认。动画以低速开始,然后加快,在结束前变慢。
        3. ease-in  动画以低速开始。
        4. ease-out 动画以低速结束。
        5. ease-in-out  动画以低速开始和结束。
        6. cubic-bezier(n,n,n,n)    在 cubic-bezier 函数中自己的值。可能的值是从 0 到 1 的数值。
     4. animation-delay    规定动画何时开始 。 默认是 0。
     5. animation-iteration-count    规定动画被播放的次数 (from到to算作一次, to到from算作一次; 注意计算方式) 。
        1. 默认是 1 。
        2. infinite规定动画应该无限次播放。
     6. animation-direction    规定动画是否在下一周期逆向地播放 。 默认是 "normal"; alternate (轮流),。
        1. normal   默认值。动画按正常播放。
        2. reverse  动画反向播放。
        3. alternate    动画在奇数次(1、3、5...)正向播放,在偶数次(2、4、6...)反向播放。
        4. alternate-reverse    动画在奇数次(1、3、5...)反向播放,在偶数次(2、4、6...)正向播放。
        5. initial  设置该属性为它的默认值 。
​
6. 子属性详解
     1. alternate(轮流):
            1. alternate (轮流): 动画播放在第偶数次向前播放, 第奇数次向反方向播放 (animation-iteration-count 取值大于1时设置有效
            2. 语法: animation-direction: alternate;
​
     2. animation-play-state 规定动画是否正在运行或暂停 。 默认是 "running" 播放; paused 暂停播放 。
            1. 语法: animation-play-state: paused;
                                                    
     3. animation-fill-mode   属性规定动画在播放之前或之后, 其动画效果是否可见; 规定对象动画时间之外的状态; none | forwards | backwards | both 。
            1. none:       不改变默认行为 (默认, 回到动画没开始时的状态) 。
            2. forwards:   当动画完成后,保持最后一个属性值(在最后一个关键帧中定义) (动画结束后动画停留在结束状态) 。
            3. backwards:  在 animation-delay 所指定的一段时间内, 在动画显示之前, 应用开始属性值 (在第一个关键帧中定义) (动画回到第一帧的状态)。
            4. both:       向前和向后填充模式都被应用 (根据 animation-direction 轮流应用 forwards 和 backwords 规则)。
            5. 语法:        animation-fill-mode: forwards
               1. 0% 是动画的开始, 100% 是动画的完成。
​
​
复制代码

移动端rem适配

Vant 中的样式默认使用 px 作为单位,如果需要使用 rem 单位,推荐使用以下两个工具:

一、使用 lib-flexible 动态设置 REM 基准值(html 标签的字体大小)

1、安装

# yarn add amfe-flexible
npm i amfe-flexible
复制代码

2、然后在 main.js 中加载执行该模块

import 'amfe-flexible'
复制代码

最后测试:在浏览器中切换不同的手机设备尺寸,观察 html 标签 font-size 的变化。

二、使用 postcss-pxtorempx 转为 rem

1、安装

# yarn add -D postcss-pxtorem
# -D 是 --save-dev 的简写
npm install postcss-pxtorem -D
复制代码

2、然后在项目根目录中创建 .postcssrc.js 文件

module.exports = {
  plugins: {
    'autoprefixer': {
      browsers: ['Android >= 4.0', 'iOS >= 8']
    },
    'postcss-pxtorem': {
      rootValue: 37.5,
      propList: ['*']
    }
  }
}
​
复制代码

3、配置完毕,重新启动服务

最后测试:刷新浏览器页面,审查元素的样式查看是否已将 px 转换为 rem

(1)PostCSS 介绍

PostCSS 是一个处理 CSS 的处理工具,本身功能比较单一,它主要负责解析 CSS 代码,再交由插件来进行处理,它的插件体系非常强大,所能进行的操作是多种多样的,例如:

目前 PostCSS 已经有 200 多个功能各异的插件。开发人员也可以根据项目的需要,开发出自己的 PostCSS 插件。

Guess you like

Origin juejin.im/post/7100196601058525192