前端笔记
HTML
行内元素、块级元素、空元素有哪些
- 行内元素:span、i、img、input
- 块级元素:div、p、h1~6、header、section、footer
- 空元素:br、hr
元素之间的转换
- 行内元素:inline
- 行内块元素:inline-block
- 块级元素:block
导入样式时,link和@import的区别
- 先有link后有@import,link的兼容性比@import好
- link是标签,@import不是
- 浏览器先加载link,后加载@import
title与h1的区别
定义
- title是网站标题,概括了网站信息,告诉搜索引擎或用户网站的内容主题是什么
- h1是网站内容,告诉搜索引擎网站的主要内容是什么
区别
- title是显示在网页标题上的,h1是显示在网页内容上的
- title比h1重要
b与strong的区别
定义
- b标签是实体标签,用来给文字加粗的
- strong标签是逻辑标签,用来加强字符语气的
区别
- b标签只是加粗,没有实际含义
- strong是强调标签内字符比较重要
- strong更符合CSS3的规范
i与em的区别
定义
- i标签是实体标签,用来做文字倾斜的
- em标签是逻辑标签,用来强调文字内容的
区别
- i标签只是倾斜,没有实际含义
- em是强调标签内字符比较重要
- i更多的用在字体图标上,em更多的用在术语上(医药、生物)
img标签的title和alt的区别
- title是鼠标悬停在图片上显示的提示信息
- alt是图片加载失败时显示的信息
- 为了让搜索引擎更好的搜索到网站,最好每一张图片都加上alt
解释一下png、jpg、gif、webp图片格式,分别在什么时候使用
- png是无损压缩,体积比jpg和jpeg更大,支持透明,适合做小图标
- jpg采用压缩算法,有一点失真,体积比png小,不支持透明,适合做大图片(轮播图)
- gif一般是做动图,较少使用
- 同时支持有损和无损压缩,相同质量的图片,webp具有更小的体积,兼容性较差
CSS
CSS的盒子模型
- 有哪些
- 标准盒子模型:content-box,由margin、border、padding、content组成
- IE盒子模型:border-box,有margin、content(border + padding + content)组成
- 如何转换
- box-sizing
line-height和height的区别
- line-height是每行文字的高,在未设置height时如果文字换行,则整个盒子高度会增大(行数 * line-height)
- height是盒子的高
CSS选择器有哪些
选择器 | 名 |
---|---|
* | 通配符选择器 |
# | id选择器 |
. | 类选择器 |
div、p... | 标签选择器 |
+ | 直接相邻选择器 |
~ | 相邻选择器 |
> | 子代选择器 |
空格 | 后代选择器 |
[属性] | 属性选择器 |
:hover... | 伪类选择器 |
:before... | 伪元素选择器 |
哪些属性可以继承
color、font-size、line-height、text-align...
哪些属性不可继承
border、padding、margin...
CSS优先级(权重)算法
!important:无限大 内联样式:1000 id:0100 class:0010 标签:0001 通配符、继承:0 算法:相加不进位,如十个id应为010000而不是1000,内联的权重仍然更大
用CSS画一个三角形
使用border,宽高为0,保留箭头方向对立方向的border的颜色,其余为透明
一个盒子不给宽高如何水平垂直居中
- 父盒子设置为弹性盒子,align-items: center;justify-content: center;
- 绝对定位 + left: 50%;top: 50%;transform: translate(-50%, -50%);
display有哪些值
- none:元素不被显示且不占用位置
- block:块级元素,占用一整行
- inline:行内元素,无法设置宽高
- inline-block:行内块元素,可以设置宽高
- flex:弹性盒子
- grid:网格布局
对BFC规范的理解
BFC也就是块级格式化上下文,他是页面上的一个隔离的独立容器,容器内的子元素不回影响到外面的元素 比如说div包裹着一个p标签,div下面有一个h1标签,当p标签设置了浮动,就会导致div标签高度塌陷,进而导致h1会跟在p标签后面,在同一行,而BFC就可以解决这一问题
触发方法
- float的值非none
- overflow的值非visible
- display的值为inline-block...
- position的值为absolute
清除浮动有哪些方式
- 触发BFC
- 在最后多创建一个盒子,添加样式:clear: both
- 添加伪元素after,添加样式content: '';display: block;clear: both;
在网页中应该使用奇数还是偶数的字体
偶数,让文字在浏览器上表现更好看
position有哪些值
- absolute:绝对定位,相对于拥有absolute或releavte的父元素定位,若无,则相对于浏览器进行定位,脱离文档
- fixed:固定定位,相对于浏览器进行定位,脱离稳定
- relative:相对定位,相对于自身进行定位,不脱离文档,left会覆盖right,top会覆盖bottom
- static:默认值,没有定位
- sticky:粘性定位,当页面滚动超出目标区域时,相对于fixed,否则相对于relative
什么是CSS reset
reset.css是一个重置CSS样式的文件,但因为性能问题,现在用得比较少,现在主要用normalize.css
CSS sprite(雪碧图)的优缺点
是什么
将多个小图标合并为一张大图片
优点
- 减少向服务器发送请求的次数
缺点
- 改一个小图标就要改整张图,难维护
- 使用麻烦
display: none和visibility: hidden的区别
display: none不占用位置 visibility: hidden占用位置
opacity和rgba的区别
- opactiy作用于整个元素,包括文字颜色,子元素等都会被影响,rgba只作用于背景色
JavaScript
延迟加载JS的方法
- async:在下载js脚本时不暂停HTML的解析,在执行js时暂停HTML的解析,非顺次执行,谁先加载完谁先执行
- defer:在下载js脚本时不暂停HTML的解析,并在HTML解析完毕后再执行,顺次执行js脚本
数据类型有哪些
- 基本类型:string、number、boolean、undefined、null、symbol(ES6)、bigint(有争议)
- 引用类型:object
注意
- undefined 与除字符串外的类型相加,最终都会变成数值类型
- typeof undefined 还是 undefined
- null是一个特殊的对象
null和undefined的区别
- null是一个表示"无"的特殊对象(空白对象指针),转为数值时是 0,在发生错误时不容易被发
- undefined是一个基本类型,转换为数值时是NaN
==和===的区别
- ==会隐式转换
- ===是全等,除了比较值还会比较类型
在转换中
- null == undefined
- string == number --> string转number
- boolean == number --> boolean转number
- object == 基础类型 --> object转基础类型
微任务和宏任务
- js是单线程语言,在同步任务执行完后再执行事件循环(请求、定时器、事件...)
- 事件循环包含微任务和宏任务
- 微任务:promise.then
- 宏任务:setTimeout
- 总流程:同步 -> 微任务 -> 宏任务 -> 微任务 -> (宏任务 -> 微任务)(循环)...
作用域
- 作用域是一个作用范围,有全局作用域和函数作用域,在ES6以前,js 没有块级作用域,只有函数作用域
- 在ES6的跨级作用域中,只有let定义的变量和const定义的常量,外部才无法访问,var定义的变量在外部仍可以访问
- 外部无法访问内部,但内部跨域访问外部
- 若定义变量/常量前无var、let、const,则视为全局变量,如
(function(){
var a = b = 10; => var a = 10; window.b = 10;
})()
- 优先级:变量 > 函数提升 > 参数 > 变量提升
作用域链
从当前作用域逐级向上寻找,子作用域可以访问父作用域的属性,直到寻找到全局作用域,称为作用域链
对象
- 对象是通过new操作符构建出来的,所以对象之间不相等
- 对象是引用类型
- 对象的key都是字符串类型
- 对象寻找属性|方法:对象本身 --> 构造函数 --> 构造函数原型 --> 对象上一层原型
原型
- 什么是原型
- 用于共享属性和方法,函数的内部属性prototype(对象是__proto__)所对应的,就是原型
- 解决的问题
- 对象共享属性和方法
- 谁拥有原型
- 函数:prototype
- 对象:__proto__
原型链
- 什么是原型链 将原型串联起来,最终指向null,形成原型链
- 查找顺序 对象本身 > 构造函数 > 对象的原型 > 构造函数的原型 > 当前原型的原型
判断变量是否为数组
- Array.isArray
- instanceof [Array]
- Obejct.prototype.toString.call(arr)
- Array.protytype.isPrototypeOf(arr)
slice是干嘛的、splice是否会改变原数组
- slice是用来截取的,返回新数组
- splice可以用来插入、删除、替换,返回被删除的元素,会改变原来的数组
数组去重
- new set
var arr = [1,2,3,2,4,1];
console.log(Array.from(new Set(arr)));
console.log([...new Set(arr)])
- indexOf
var arr = [1,2,3,2,4,1];
function unique(arr){
var brr = [];
for(let i = 0;i < arr.length;i++){
if(brr.indexOf() == -1) brr.push(arr[i]);
}
return brr;
}
- sort
var arr = [1,2,3,2,4,1];
function unique(arr){
arr = arr.sort();
var brr = [];
for(let i = 0;i < arr.length;i++){
if(arr[i]!==arr[i-1]){
brr.push(arr[i]);
}
}
return brr;
}
- filter
var arr = [1,2,3,2,4,1];
var brr = arr.filter((item,index)=>{
return arr.indexOf(item) == index;
// 原理:找出item在数组中第一次出现的位置,若是第一次出现,indexOf(item)与index是相对应的,若不是第一次出现,则不相对应
})
给字符串新增方法实现功能
String.prototype.xxx = function(){}
统计字符次数
const str = 'abcffbfffcap';
let obj = {};
for (let i = 0; i < str.length; i++) {
if (!obj[str[i]]) {
obj[str[i]] = 1;
} else {
obj[str[i]] += 1;
}
}
console.log(obj);
出现次数最多的字符
- 正则
let str = 'abcffbfffcap'; // 原始字符串
let index = 0; // 出现的次数
let value = ''; // 出现次数最多的字符
str = str.split('').sort().join('');
str.replace(/(w)1+/g, (val, item) => {
if (index < val.length) {
value = item;
index = val.length;
}
});
console.log(value, index);
- 循环
const str = 'abcffbfffcap';
let obj = {};
for (let i = 0; i < str.length; i++) {
if (!obj[str[i]]) {
obj[str[i]] = 1;
} else {
obj[str[i]] += 1;
}
}
let max = 0;
let val = '';
for(let key in obj){
if(max < obj[key]){
max = obj[key];
val = key;
}
}
console.log(key, max)
new操作符具体做了什么
- 创建了一个空的对象
- 将空对象的原型指向于构造函数的原型
- 将空对象作为构造函数的上下文(改变this指向)
- 对构造函数有返回值的处理判断(如果返回值是基本类型,则忽略,如果是引用类型,则返回)
闭包
- 闭包是什么
- 闭包是一个函数加上到创建函数的作用域的连接,闭包"关闭"了函数的自由变量
- 简单来说就是一个函数内return另一个函数,内部函数称为闭包
- 函数执行完后,变量不会被销毁
- 闭包的优点
- 内部函数可以访问外部函数的局部变量
- 命名冲突
- for循环中,var定义的i的问题
- 闭包的缺点
- 变量会驻留在内存中,造成内存损耗问题,解决方法:把闭包函数设置为空
JS的继承方式
- ES6
class Parent{
constructor(){
this.age = 18;
}
}
class Child extends Parent{
consturctor(){
super();
this.name = '张三';
}
}
let o1 = new Child();
console.log(o1.age);
- 原型链继承,可以共享,但无法向父构造函数传递参数
function Parent(){
this.age = 18;
}
function Child(){
this.name = '张三';
}
Child.prototype = new Parent(); // 将Parent放到Child的prototype中
let o1 = new Child();
console.log(o1.age);
- 借用构造函数,无法共享
function Parent(){
this.age = 18;
}
function Child(){
Parent.call(this); // 将Parent指向当前
this.name = '张三';
}
let o1 = new Child();
console.log(o1.age);
- 组合继承,可以共享
function Parent(){
this.age = 18;
}
function Child(){
Parent.call(this);
this.name = '张三';
}
Child.prototype = new Parent();
let o1 = new Child();
console.log(o1.age);
call、apply、bind的区别
- 功能一致,可以改变函数体内的this的指向
- call、apply会立即执行,bind不会,返回改变this指向后的函数
- call、bind传参方式是多个参数,apply传参方式是数字
- call:调用函数并改变this指向,fn.apply(this指向,参数1,参数2...)
- apply:调用函数并改变this指向,fn.apply(this指向,[参数1,参数2...])
- bind:改变this指向但不调用函数,返回改变this指向后的函数
sort的原理
默认是根据Unicode的编码进行排序
arr.sort((a,b)=>{
return a-b; // 从小到大
return b-a; // 从大到小
})
深拷贝和浅拷贝
- 浅拷贝:只复制引用,而未复制真正的值
- 深拷贝:彻底复制
// 使用JSON.stringify + JSON.parse
let obj2 = JSON.parse(JSON.stringify(obj1));
// 自定义deepCopy
function isObject(obj) {
return typeof obj === 'object' && obj !== null;
}
function deepCopy(source) {
if (!isObject(source)) return source; //如果不是对象的话直接返回
let target = Array.isArray(source) ? [] : {}; //数组兼容
for (var k in source) {
if (source.hasOwnProperty(k)) {
if (typeof source[k] === 'object') {
target[k] = deepCopy(source[k]);
} else {
target[k] = source[k];
}
}
}
return target;
}
H5C3
什么是语义化标签
如header、section、footer等这些标签就是语义化标签,他的
- 易读性和维护性更高
- SEO成分会更好
before和after中双冒号和单冒号的区别
实际效果没有区别,但为了更好的区分伪类和伪元素,伪类会用单冒号,为元素用双冒号 before是在元素的最前面添加一个元素、after是在元素的最后面添加一个元素
如何关闭IOS键盘首字母大写
给input添加autocapitalize="off"
如何让Chrome支持小于12px的文字
- 缩放:transform: scale()
rem和em的区别
- em:相对于父元素的 font-size 进行调整
- rem:相对于 html 标签的 font-size 进行调整
IOS系统中元素被触摸时产生的半透明灰色遮罩如何解决
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
webkit表单输入框placeholder如何修改颜色
input::-webkit-input-placeholder{
color: rgba()
}
禁止IOS长按时触发系统菜单
-webkit-touch-callout: none;
user-select: none;
布局方案
- 响应式布局:一套代码搞定多端,会造成性能变成,数据不多、用户量不大、纯展示类的适用
- 自适应布局:移动端使用
ES6
var、let、const
let定义变量,只在当前代码块中生效 var会变量提升,最终全局可用,let不会变量提升 var可以重复声明同一个变量,let不可以 const与let相同,但const为常量,定义之后不可修改,通常大写
箭头函数和普通函数的区别
- this指向
- 普通函数哪里调用指向哪里,可用call、apply、bind修改
- 箭头函数哪里创建指向哪里,且不可用call、apply、bind修改
- 箭头函数不能new,即不能当作构造函数
- 箭头函数没有prototype、arguments
Promise有几种状态
- pending(进行中)
- fulfilled(已成功)
- rejected(已失败)
find和filter的区别
- filter返回的是新数组;find是返回具体的内容,只返回第一个
some和every的区别
- some只要有一个满足条件就会返回true,every必须全部满足条件才返回true
变量的解构赋值
let [a, b, c] = [10, 20, 30]; => a=10, b=20, c=30 let {a, b} = {a: 10, b: 20}; => a=10, b=20 let [a, b, c] = 'hello'; => a='h', b='e', c='l'
字符串扩展
- 模板字符串
- includes:与indexOf相似,但返回布尔值
- startsWith:文本是否在头部
- endsWitdh:文本是否在尾部
- repeat:将文本重复N次
- padStart:往前补全N位数
- padEnd:往后补全N位数
- trim:去除前后空格
- trimStart:去除前空格
- trimEnd:去除后空格
箭头函数
- 哪里定义指向那里,function,谁调用指向谁
- 不能作为构造函数,即不可new
- 箭头函数内部没有arguments对象
函数扩展
- 函数参数的默认值
- ...操作符:拆分或合并数组
数组扩展
- Array.from:将两类对象转换为数组
- Array.of:将一组数转换为数组
- find:查找,返回满足条件的元素
- findIndex:查找,返回满足条件的元素的下标
- flat:扁平化数组,默认一层
对象扩展
- for...on:可遍历数组和对象
- Object.keys:获取对象的键
- Object.Values:获取对象的值
- Object.entries:获取对象的键值
- Object.is:判断是否相等,主要用于解决==和==的问题
- Object.assign:合并对象,浅拷贝
Class
- 实际上仍是勾走函数,只是看起来更像面向对象
class 类名称{
constructor(形参){
// 指向构造函数
this.属性名 = 属性值
},
// 自定义方法
run(){}
}
let obj = new 类名称(实参)
- 继承
class 子类 extends 父类{
constructor(){
super();
}
}
Symbol
原始数据类型,防止变量名冲突
new Set()
对象,没有重复的值,可用于去重
Module
- 引入:import
- 完全引入
- 按需引入
- 自定义名称
- 抛出:export
Promise
- 对象,异步编程的一种解决方案,写异步代码,同步方式执行
- 三种状态:
- pending:进行中
- fulfilled:已成功
- rejected:已失败
async和await
- 在函数前加async,函数将返回promise对象
- await,需配合async使用,等待当前异步函数执行完成再执行后面的代码
fetch和mock
- 不是ES6
- ajax请求,优点:不需要额外下载依赖;缺点:对低版本浏览器不支持
- 返回promise对象
fetch(url,{
method:'get|post',
params:{
// 请求参数
}
}).then(async res=>{
await res.json();// 将res转换为json格式,因是异步函数,因此要等待转换完成后再操作
});
- fetch-mock:模拟数据,需下载插件
Git
Git常用命令
效果 | 命令 |
---|---|
下载 | git clone gitee/github上的项目链接 |
下载指定分支 | git clone -b 分支名称 gitee/github上的项目链接 |
克隆当前项目 | git pull |
提交代码到中转站 | git add .(.为所有,也可以指定文件) |
提交所有代码到本地仓库 | git commit -m "注释内容" |
提交本地仓库到远程仓库 | git push |
设置用户名 | git config --global user.name "" |
设置邮箱 | git config --global user.email "" |
初始化仓库 | git init |
查看配置 | git config -l |
查看状态 | git status,红色未被管理,绿色已管理 |
查看文件 | git diff 文件名(为空查看全部) |
查看修改历史 | git log 文件名(为空查看全部) |
查看修改历史[简单模式] | git reflog |
回到上一个的版本 | git reset --hard HEAD^ |
回到指定版本 | git reset --hard 版本号 |
创建/查看/删除分支 | git branch -d(可选,删除本地分支) 分支名(为空查看分支)-r(可选,查看远程仓库分支) |
切换分支 | git checkout 分支名 |
本地分支提交到远程仓库 | git push --set-upstream origin 分支名称 |
删除远程仓库分支 | git push origin --delete 分支名 |
合并分支 | git merge 分支名(将指定分支与当前分支合并) |
SVN和Git的区别
- SVN是集中式管理,Git是分布式管理
- SVN在断网时无法提交代码,Git在本地有一个服务,可以先提交在本地上,等待有网后再提交到远程仓库
- 相对来说Git速度更快
Gitflow
- master:用于保存上线版本代码
- develop:用于保存相对稳定版本的代码
- feature:用于开发功能
- release:用于代码上线前的准备(测试,bug修复)
- bugfix:用于修复不紧急bug
- hotfix:用于修复紧急bug
Vue
生命周期
- 有哪些生命周期
- 默认有8个生命周期,加入keep-alive后有10个
- beforeCreate:创建之前
- created:创建之后
- beforeMount:渲染之前
- mounted:渲染之后
- beforeUpdate:更新之前
- updated:更新之后
- beforeDestroy:销毁之前
- destroyed:销毁之后
- activated:进入
- deactivated:离开
- 进入组件或页面,会执行哪些生命周期
- beforeCreate
- created
- beforeMount
- mounted
- 哪个阶段有$el,哪个阶段有$data
- $data是组件的数据,$el是组件的根节点
- 在created阶段有$data
- 在mounted阶段有$el
- 加入keep-alive后,第一次进入页面,会执行哪些生命周期
- beforeCreate
- created
- beforeMount
- mounted
- activated
- 加入keep-alive后,第2~N次,会执行哪些生命周期
- activated
keep-alive
- 什么是keep-alive
- vue系统自带的一个组件,用来缓存组件,提升性能
- 使用场景
- 从列表页进入详情页,如果进入的是同一个详情页(数据未发生变化),需要多次向服务器发起请求,一方面会消耗服务器资源,另一方面也会降低应用的速度,此时加入keep-alive可以将页面缓存起来,如果进入的是同一个详情页,就不需要重复发起请求,如果进入的是不同的详情页,再重新发送请求
v-if和v-show的区别
- 展示形式不同
- v-if是创建和删除节点
- v-show是设置display
- 使用场景不同
- 初次加载v-if性能比v-show好
- 频繁切换v-show性能比v-if好
v-if和v-for的优先级
v-for优先级比v-if优先级高
ref是什么
用来获取dom的
nextTick是什么
获取更新后的dom内容
scoped原理
- 作用:让样式只在本组就中生效,在其他组件中不生效
- 原理:添加自定义属性,CSS选择器添加属性选择器
computed、methods、watch的区别
- computed是有缓存的,如果计算的属性没有发生变化,则执行缓存数据,methods没有
- computed是返回一个数据,当他内部的数据发生变化时触发,watch是数据或路由发生了改变才会执行
- computed的函数名就是返回结果,内部的才是监听的数据,watch的函数头是监听的数据
props和data的优先级
props ==> methods ==> data ==> computed ==> watch
Vue设置代理
// vue.config.js
module.exports {
devServer: {
proxy: '服务端地址'
}
}
打包完成后出现空白页
为什么会出现空白页
js、css等文件引入是/
,改为./
即可
// vue.config.js
module.exports {
publicPath: './'
}
路由模式
- history
- url不带#
- 每次跳转会发生一次请求
- 项目上线后端要设置重定向
- hash
- url带#
- 跳转不发生请求
- 前端测试一般使用hash,使用history可能会出现空白页
模式和环境变量
开发环境
新建文件.env.development
生产环境
新建文件.env.production
SPA
是什么
单页面应用
缺点
- SEO优化不好,解决,服务器预渲染等
- 性能不是特别好
路径传值
// 发送方
// 显示
this.$router.push({
path: '',
query: {
xxx:'',
}
})
// 隐式
this.$router.push({
name: '',
params: {
xxx:'',
}
})
// 接收方
// 显示
this.$route.query.xxx
// 隐式
this.$route.params.xxx
导航守卫有哪些
全局
- beforeEach
- beforeResolve
- afterEach
路由独享
- beforeEnter
组件内
- beforeRouteEnter
- beforeRouteUpdate
- beforeRouteLeave
动态路由
路由内的children
双向绑定原理
通过Object.defineProperty劫持数据发生的改变,如果数据发生了改变,触发update方法进行更新节点内容,从而实现了数据双向绑定
diff算法
功能
- 提升性能
新老节点替换规则
- 如果新老节点不是同一个节点,则直接删除旧的节点,创建插入新的节点
- 只能同级比较,不能跨层比较
实现方法
- 如果是不同的节点,删除旧节点添加新节点
- 如果是相同的节点
- 新节点没有children(即新节点是文本节点),直接替换文本
- 新节点有children
- 旧的有children(diff算法的核心,最难的)
- 旧前新前
- 旧后新后
- 旧前新后
- 旧后新前
- 以上都不满足
- 创建或删除
- 旧的没有children,删除旧的,创建元素添加新的
虚拟dom
把dom数据化
什么是MVVM
MVVM分为M(model)、V(view)、VM(ViewModel) model是数据(data里的数据) view是页面(template里的dom) ViewModel是解析器(就是vue的源码)
Vuex
- state:存放数据
- getters:相当于计算属性
- mutations:存放方法,用于直接修改state,是同步的
- actions:存放方法,无法直接修改state,而是提交mutations,即调用mutations内的方法,可包含任意的异步操作
- modules:将state, getters, mutations, actions分成多个模块
uni-app
生命周期
应用生命周期
只存在与App.vue
函数名 | 说明 |
---|---|
onLaunch | 当uni-app初始化完成时触发,只触发一次 |
onShow | 当uni-app启动或从后台进入前台 |
onHide | 当uni-app从前台进入后台 |
onError | 当uni-app报错时触发 |
页面生命周期
pages下的页面都存在
函数名 | 说明 |
---|---|
onLoad | 当页面初始化完成时触发,只触发一次 |
onShow | 当页面显示时 |
onHide | 当页面隐藏时 |
onReady | 当页面完全加载完毕时 |
onUnload | 当页面卸载时 |
组件生命周期
只存在与组件(compoments)中,与vue相同,但没有keep-alive
条件编译
<!-- #ifdef 平台 -->
<!-- #endif -->
微信小程序
如何自定义头部
// app.json
"window":{
"navigationStyle":"custom",// default为默认,custom为自定义,设置为custom将仅保留两个胶囊按钮
}
如何自定义底部
不配置tabbar即可
不校验URL
工具 --> 详情 --> 本地设置 --> 勾上不校验合法域名(项目上线前需要取消勾选)
性能优化
Vue性能优化
- 使用keep-alive缓存组件
- 路由懒加载(二级页面可以使用懒加载)
- 合理运用v-if和v-show、computed、watch、methods
- Object.freeze(冻结对象,纯展示类的接口数据,冻结即可)
- 使用UI组件按需引入
加载优化
- http请求(尽可能合并)
- 小图标 --> 雪碧图
- script延迟加载
- link引入
图片优化
- 雪碧图
- 响应式图片(img中的srcset)
- 使用webp格式
- 懒加载
- 小图标可以改用字体图标
渲染优化
- 减少重绘回流(触发回流必定触发重绘,触发重绘不一定触发回流)
- 用变量缓存dom样式,不要频繁读取
- 动画元素使用absolute,脱离文档,不影响其他元素,使用transform,减少使用left等
- 动画尽量使用requestAnimationFrame,减少使用定时器
首屏优化
- 懒加载
- 长列表(先放一部分,触底后再放一部分)
- 项目文件的压缩打包
webpack相关
- 不生成.map
// vue.config.js
module.exports = {
productionSourcMap: false, // 不生成.map
}
- 路由分包,若不分包则所有页面操作都打包在app.js,home必在app.js中
// router/index.js
const routes = [
{
path: "",
name: "",
compoent: () => import(/* webpackChunkName: "xxx" */) // 将该页面打包为xxx.js
}
]
- vendors.js分包(项目中的依赖包)
- UI框架的按需引入,使用插件babel-plugin-component(element-ui)、babel-plugin-import(vant)
兼容
- IOS键盘首字母大写
- input添加autocapitalize="off"
- IOS日期转换为NAN
- 日期使用斜杆分割
- 移动端click事件300ms延迟
- 禁止缩放
- fastclick.js
- 移动端touch事件穿透
- 阻止默认行为
- fastclick.js
- 移动端键盘遮挡底部
- 弹出键盘后将底部抬起
- 安卓input的placeholder偏上
- 添加样式line-height: normal;
- HTML5标签兼容低版本浏览器
- 使用html5shiv.js
网络请求
跨域
前端
- jsonp
- vue项目设置代理
后端
- cors
http和https的区别
- http是80端口,https是443端口
- https比http安全,https需要安全证书
web安全
xss攻击
是什么
执行一些js代码
解决
使用正则,将<
、>
等进行转换
sql注入
是什么
传递sql语法以获取数据库信息
解决
使用正则过滤,禁止输入框中有特殊符号
接口安全
做加密
其他
token
- token + cookie:前端判断是否过期
- token + localStorage:后端判断是否过期(返回code码,前端判断code码)
SEO
- 网站一定要多页面
- title、描述、关键字很重要
- 图片、视频、音频的标签属性特别关键
- 网站不能出现死链接
混入和vuex的区别
如何修改computed中的数据
在computed中设置get和set
腾讯IM的接入步骤
- 下载引用依赖,还有demo包,将demo包中的debug包复制到项目中,用于生成userSig
- 在GenerateTestUserSig.js中配置key和密钥
- 在客服页面的created钩子中获取当前用户ID并生成userSig,添加接收事件
- 添加点击发送按钮的发送事件
- 将历史记录存储在localStorage中,用于读取
uni-app如何区分IOS和安卓
uni-app自带getSystemInfo