@
语义化的主要目的可以概括为用正确的标签做正确的事
HTMl语义化可以让页面的内容结构化,以便于浏览器解析和搜索引擎解析,
并且提高了代码的可读性便于代码维护,
Canvas绘图以及SVG绘图。
拖放(Drag and drop)API
语义化标签(header、nav、footer、article、section)
音频、视频(audio、video)API
地理定位(Geolocation)
本地离线存储(localStorage),长期存储数据,关闭浏览器后不丢失。
会话储存(sessionStorage),数据在关闭浏览器后自动删除。
表单控件(calendar、date、time、email、url、search)
保存方式
cookie存放在客户的浏览器上。
session都在客户端中保存,不参与服务器通讯。
生命周期
cookie可设置失效时间
localStorage除非手动清除否则永久保存
sessionStorage关闭当前页面或浏览器后失效
存储的大小
cookie 4kb左右
session 5M
易用性
cookie需自己封装
session可以接受原生接口
因为cookie每次请求都会携带在http请求中,所以它的主要用来识别用户登录,localStorage可以用
来跨页面传参,sessionStorage可以用来保留一些临时数据。
id选择器 => #myId {}
类选择器 => .myClass {}
标签选择器 => p,h1 {}
后代选择器 => div h1 {}
子选择器 => div>h1 {}
兄弟选择器(所有的兄弟) => ul~h1 {}
相邻兄弟选择器 => ul+h1 {}
属性选择器 => li[name='sss'] {}
伪类选择器 => h1:hover {}
伪元素选择器 => h1::before{}
通配符选择器* => * {}
!important>内联样式(非选择器)>ID选择器>类选择器>标签选择器>通配符选择器(*)
块元素:div、h1~h6、ul、li、table、p、br、form。
特征:独占一行,换行显示,可以设置宽高,可以嵌套块和行
行内元素:span、a、img、textarea、select、option、input。
特征:只有在行内显示,内容撑开宽、高,不可以设置宽、高(img、input、textarea等除外)。
父级div定义overflow:hidden(如果父级元素有定位元素超出父级,超出部分会隐藏,)
给浮动元素父级增加标签(由于新增标签会造成不必要的渲染,不建议使用)
伪元素清除浮动:给浮动元素父级增加 .clearfix::after(content: ‘’; display: table;
clear: both;)(不会新增标签,不会有其他影响,)
圆角(border-radius)
阴影(box-shadow)
文字特效(text-shadow)
线性渐变(gradient)
变换(transform)
更多的CSS选择器
更多背景设置(background)
色彩模式(rgba)
伪元素(::selection)
媒体查询(@media)
多栏布局(column)
图片边框(border-image)
绝对长度单位:px
百分比: %
相对父元素字体大小单位: em
相对于根元素字体大小的单位: rem
相对于视口*宽度的百分比(100vw即视窗宽度的100%): vw
相对于视口*高度的百分比(100vh即视窗高度的100%): vh
display:none:隐藏元素,在文档布局中不在给它分配空间(从文档中移除),会引起回流(重排)
visibility:hidden: 隐藏元素,但是在文档布局中仍保留原来的空间(还在文档中),
不会引起回流(重绘)
某个dom节点的颜色,背景颜色变了,字体大小,只影响自己,不影响其他元素。
注意:table及其内部元素可能需要多次计算才能确定好其在渲染树中节点的属性,比同等元素要多花两倍时间,这就是我们尽量避免使用table布局页面的原因之一。
某个dom节点的宽高,布局,隐藏等发生改变,不仅自身发生了改变,而且其他元素也会受到影响随之发生改变。每个页面最少一次回流,就是页面第一次加载的时候。
页面初始化渲染(无可避免)
添加或删除可见的DOM元素
元素尺寸的改变------大小,外边距;边框
浏览器窗口尺寸的变化
填充内容的改变,比如文本的改变或图片大小改变而引起的计算值宽度和高度的改变
读取某些元素属性:(offsetLeft/Top/Height/Width, clientTop/Left/Width/Height,
scrollTop/Left/Width/Height, width/height, getComputedStyle(),
currentStyle(IE) )
1.重绘不一定重排,但是重排一定会重绘
2.重绘和重排的成本都是非常高的,要尽量减少dom的增删改
不要直接操作样式,先设置好class,然后修改DOM的className;
position:absolute 与flex 不会导致重排
不要把DOM 节点的属性放在一个循环当成循环的变量;
需要动画的元素脱离文档流;
不使用table 布局,
尽量不修改影响范围比较大的DOM;
如果要多次添加DOM,先使用 document.createDocumentFragment() 创建一个盒子,
完盒子里面先添加子元素,添加完成在插入元素中;
link属于html标签,而@import是css提供的。
页面被加载时,link会同时被加载,而@import引用的css会等到页面被加载完再加载的。
兼容性问题:@import只在IE5以上才能识别,而link是html标签,无兼容性问题。
权重问题:@import的权重要高于link。
DOM操作:DOM可以操作link中的样式,而不可以操作@import中的样式。
<!-- html 文件 -->
<!-- link 方式,推荐 -->
<link rel="stylesheet" type="text/css" href="style.css" media="screen" />
<!-- @import 方式 -->
<style type="text/css" media="screen">
@import url(style.css);
</style>
将当前组件的<style>修改为<style scoped>。
常见的:
原型链继承
借用构造函数继承
原型链+借用构造函数的组合继承(使用 call 或 applay 方法)
ES6中class 的继承(class可以通过extends关键字实现继承)
面向对象是基于万物皆对象这个哲学观点. 把一个对象抽象成类,具体上就是把一个对象的静态特征和动态特征抽象成属性和方法,也就是把一类事物的算法和数据结构封装在一个类之中,程序就是多个对象和互相之间的通信组成的。
面向对象具有封装性,继承性,多态性。
封装:隐蔽了对象内部不需要暴露的细节,使得内部细节的变动跟外界脱离,只依靠接口进行通信.封装性降低了编程的复杂性。
继承:使得新建一个类变得容易,一个类从派生类那里获得其非私有的方法和公用属性的繁琐工作交给了编译器。
多态:继承和实现接口和运行时的类型绑定机制所产生的多态,使得不同的类所产生的对象能够对相同的消息作出不同的反应,极大地提高了代码的通用性.。
定义: 虚拟DOM就是普通的js对象。用来描述真实dom结构的js对象,因为它不是真实的dom,所以才叫做虚拟dom。
作用: 虚拟dom可以很好地跟踪当前dom状态,因为它会根据当前数据生成一个描述当前dom结构的虚拟dom,然后数据发生变化时,有生成一个新的虚拟dom,而两个虚拟dom恰好保存了变化前后的状态。然后通过diff算法,计算出当前两个虚拟dom之间的差异,得出一个更好的替换方案。
冒泡排序:比较所有相邻元素,如果第一个比第二个大,则交换它们。
选择排序:找到数组中的最小值,选中它并将其放置在第一位。
插入排序:从第二个数开始往前比,比它大就往后排。
归并排序:把数组劈成两半,再递归地对数组进行“分”操作,直到分成一个个单独的数。
快速排序:从数组中任意选择一个基准,所有比基准小的元素放到基准前面,比基准大的元素放到
基准的后面。
会改变:push(),pop(),shift(),unshift() ,splice(),sort(),reverse()。
不变:concat(),split(),slice()。
js中substr()、substring()、slice()、splice()、split()的区别与作用
typeof:判断基本数据类型,对于引用数据类型除了function返回’function‘,其余全部
返回’object’。
instanceof:区分引用数据类型,检测方法是检测的类型在当前实例的原型链上,用其检测出来的
结果都是true,不太适合用于简单数据类型的检测,检测过程繁琐且对于简单数据类
型中的undefined, null, symbol检测不出来。
constructor:检测引用数据类型,检测方法是获取实例的构造函数判断和某个类是否相同,如果
相同就说明该数据是符合那个数据类型的,这种方法不会把原型链上的其他类也加入
进来,避免了原型链的干扰。
Object.prototype.toString.call():适用于所有类型的判断检测,检测方法是
Object.prototype.toString.call(数据) 返回的是该数据类型的字符串。
(举例:字符串返回的是[object String])
instanceof的实现原理:验证当前类的原型prototype是否会出现在实例的原型链__proto__上,只要在它的原型链上,则结果都为true。因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,找到返回true,未找到返回false。
Object.prototype.toString.call原理:Object.prototype.toString 表示一个返回对象类型的字符串,call()方法可以改变this的指向,那么把Object.prototype.toString()方法指向不同的数据类型上面,返回不同的结果
null和undefined 区别为:undefined是表示变量声明过但并未赋过值,它是所有未赋值变量默认值;null表示一个变量将来可能指向一个对象,一般用于主动释放指向对象的引用。
共同点: 都是原始类型,保存在栈中变量本地
不同点:
(1)undefined——表示变量声明过但并未赋过值。
它是所有未赋值变量默认值。
例如:var a; //a自动被赋值为undefined
(2)null——表示一个变量将来可能指向一个对象。
一般用于主动释放指向对象的引用。
2、何时使用null?
当使用完一个比较大的对象时,需要对其进行释放内存时,设置为null
3、定义
(1)undefined:是所有没有赋值变量的默认值,自动赋值
(2)null:主动释放一个变量引用的对象,表示一个变量不再指向任何对象地址
新增块级作用域let定义变量和const定义常量
变量的解构赋值
模板字符串 (‘${}’)
默认参数(key=value)
箭头函数(=>)
扩展运算符(…)
模块(import/export)
类(class/extends)
Promise
Proxy
Symbol
含义: 异步编程的一种解决方案,用来解决回调地狱。
三种状态: pending(进行中)、fulfilled(已成功)和rejected(已失败) (Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。)
resolved函数作用: 将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved)。
reject函数的作用: 将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected)。
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。
then: Promise 实例添加状态改变时的回调函数。可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。
缺点: 无法取消Promise,一旦新建它就会立即执行,无法中途取消。如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
HTTP:客户端与服务器之间数据传输的格式规范,表示“超文本传输协议”。
HTTPS:在HTTP与TCP之间添加的安全协议层。
默认端口号:HTTP:80,HTTPS:443。
传输方式:http是明文传输,https则是具有安全性的ssl加密传输协议。
连接方式:http的是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证
的网络协议,比http协议安全。
TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接。
TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的
每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
TCP首部开销20字节;UDP的首部开销小,只有8个字节。
TCP提供可靠的服务。UDP适用于一次只传少量数据、对可靠要求不高的环境。
100,接受的请求正在处理,信息类状态码
2xx(成功)表示成功处理了请求的状态码
200(成功)服务器已成功处理了请求。
3xx(重定向)表示要完成请求,需要进一步操作。通常这些状态代码用来重定向。
301,永久性重定向,表示资源已被分配了新的 URL
302,临时性重定向,表示资源临时被分配了新的 URL
303,表示资源存在另一个URL,用GET方法获取资源
304,(未修改)自从上次请求后,请求网页未修改过。服务器返回此响应时,不会返回网页内容
4xx(请求错误)这些状态码表示请求可能出错,妨碍了服务器的处理
400(错误请求)服务器不理解请求的语法
401表示发送的请求需要有通过HTTP认证的认证信息
403(禁止)服务器拒绝请求
404(未找到)服务器找不到请求网页
5xx(服务器错误)这些状态码表示服务器在尝试处理请求时发生内部错误。这些错误可能是服务器
本身的错误,而不是请求的错误
500,(服务器内部错误)服务器遇到错误,无法完成请求
503,表示服务器处于停机维护或超负载,无法处理请求
1、浏览器的地址栏输入URL并按下回车。
2、浏览器查找当前URL是否存在缓存,并比较缓存是否过期。
3、DNS解析URL对应的IP。
4、根据IP建立TCP连接(三次握手)。
5、HTTP发起请求。
6、服务器处理请求,浏览器接收HTTP响应。
7、渲染页面,构建DOM树。
8、关闭TCP连接(四次挥手)。
含义:从建立连接到断开连接一共七个步骤,就是三次招手四次挥手
TCP 建立连接
浏览器发送请求命令
浏览器发送请求头
服务器应答
服务器回应信息
服务器发送数据
断开TCP连接
浏览器解析html源码,将HTML转换成dom树,
将CSS样式转换成stylesheet(CSS规则树),
浏览器会将CSS规则树附着在DOM树上,并结合两者生成渲染树(Render Tree)
生成布局(flow),浏览器通过解析计算出每一个渲染树节点的位置和大小,在屏幕上画出渲染树的
所有节点
合成绘制生成页面。
减少http请求次数
减少DNS查找
避免重定向
使用Ajax缓存
少用全局变量、减少DOM操作的使用
优化图片大小,通过CSS Sprites(精灵图)优化图片,
将css放在顶部,将js放在底部
Webpack:把所有依赖打包成一个 bundle.js文件,通过代码分割成单元片段并按需加载。Webpack是以公共JS的形式来书写脚本的,但对AMD/CMD的支持也很全面,方便旧项目进行代码迁移。
把项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。
babel将es6、es7、es8等语法转换成浏览器可识别的es5或es3语法。
SVN是集中式版本控制系统,版本库是集中放在中央服务器的,首先要从中央服务器哪里得到最新的版本,干完活后,需要把自己做完的活推送到中央服务器。集中式版本控制系统是必须联网才能工作(如果在局域网还可以,带宽够大,速度够快,如果在互联网下,如果网速慢的话,就纳闷了)
Git是分布式版本控制系统,没有中央服务器的,每个人的电脑就是一个完整的版本库,这样,工作的时候就不需要联网了,因为版本都是在自己的电脑上。自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,只需把各自的修改推送给对方,就可以互相看到对方的修改了。
webSocket: 可以让服务器主动向客户端发送消息,适合开发聊天室,多人游戏等协作应用。
WebSocket协议是基于TCP的一种新的网络协议。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
调用时间
require运行时调用,理论上可以运用在代码任何地,甚至不需要赋值给某个变量之后再使用。
lmport是编译时候调用,必须放在文件开头,而且使用格式也是确定的。
遵循规范
require 是 AMD规范引入方式
import是es6的一个语法标准,如果要兼容浏览器的话必须转化成es5的语法
本质
require是赋值过程,其实require 的结果就是对象、数字、字符串、函数等,再把require的结果赋值给某个变量。
import是解构过程。
通过require 引入基础数据类型时,属于复制该变量。
通过require 引入复杂数据类型时,数据浅拷贝该对象。
出现模块之间的循环引用时,会输出已经执行的模块,而未执行的模块不输出(比较复杂)。CommonJS模块默认export的是一个对象,即使导出的是基础数据类型。
ES6 模块语法是 JavaScript 模块的标准写法,坚持使用这种写法,取代 Node.js 的 CommonJS 语法。
使用import取代require()。
// CommonJS 的写法
const moduleA = require('moduleA');
const func1 = moduleA.func1;
const func2 = moduleA.func2;
// ES6 的写法
import { func1, func2 } from 'moduleA';
使用export取代module.exports。
// commonJS 的写法
var React = require('react');
var Breadcrumbs = React.createClass({
render() {
return <nav />;
}
});
module.exports = Breadcrumbs;
// ES6 的写法
import React from 'react';
class Breadcrumbs extends React.Component {
render() {
return <nav />;
}
};
export default Breadcrumbs;
原因:JavaScript是单线程,所有任务需要排队,前一个任务结束,才会执行后一个任务。
所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。
同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
异步任务:不进入主线程、而进入"任务队列"的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
同步和异步任务分别进入不同的执行环境, 先执行同步任务,把异步任务放入循环队列当中挂起,等待同步任务执行完,再执行队列中的异步任务。异步任务先执行微观任务,再执行宏观任务。一直这样循环,反复执行。
微任务:Promise.then、catch、finally、async/await。
宏任务:整体代码 Script、UI 渲染、setTimeout、setInterval、Dom事件、ajax事件。
执行顺序:先执行同步代码,遇到异步宏任务则将异步宏任务放入宏任务队列中,遇到异步微任务则将异步微任务放入微任务队列中,当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行,微任务执行完毕后再将异步宏任务从队列中调入主线程执行,一直循环直至所有任务执行完毕。
一个系统只加载一次资源,之后的操作交互、数据交互是通过路由、ajax来进行,页面并没有刷新。
在一个页面上集成多种功能,甚至整个系统就只有一个页面,所有的业务功能都是它的子模块,通过特定的方式挂接到主界面上。
优点:
缺点:
多页面: 一个应用多个页面,页面跳转时整个页面都刷新,每次都请求一个新的页面
有点:SEO效果好
缺点: 页面切换慢,每次切换页面需要选择性的重新加载公共资源
渐进增强(Progressive Enhancement): 一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。
优雅降级(Graceful Degradation): 一开始就构建站点的完整功能,然后针对浏览器测试和修复。
在传统软件开发中,经常会提到向上兼容和向下兼容的概念。渐进增强相当于向上兼容,而优雅降级相当于向下兼容。向下兼容指的是高版本支持低版本的或者说后期开发的版本支持和兼容早期开发的版本,向上兼容的很少。大多数软件都是向下兼容的。
二者区别:
1、优雅降级和渐进增强只是看待同种事物的两种观点。
2、优雅降级观点认为应该针对那些最高级、最完善的浏览器来设计网站。
3、渐进增强观点则认为应关注于内容本身。
M:model(数据模型),V:view(视图),C:controller(逻辑处理),VM:(连接model和view)
MVC:单向通信。必须通过controller来承上启下。
MVVM:数据双向绑定,数据改变视图,视图改变数据。
答:通过数据劫持结合发布—订阅模式,通过Object.defineProperty()为各个属性定义get、set
方法,在数据发生改变时给订阅者发布消息,触发相应的事件回调。
Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。通俗说就是 Vue 实例从创建到销毁的过程,就是生命周期。
其他:
activated:在keep-alive组件激活时调用
deactivated:在keep-alive组件停用时调用
无论v-show的值为true或者false,元素都会存在于html页面中; 而v-if的值为true时,元素才会
存在于html页面中。
v-show指令是通过修改元素的display属性来实现的。
v-if是动态地向DOM树内添加或者删除DOM元素,v-show是通过设置DOM元素的display样式属性控制
显隐的。
v-if是"真正的"条件渲染,因为它会确保在奇幻过程中条件快内的事件监听器和子组件适当的销毁和
重建。
v-if也是惰性的,如果在初始渲染时条件为假,则什么也不做,直到条件第一次变为真时,才开始渲染
条件块。
v-show不管初始条件是什么,元素总会背渲染,并且只是简单地基于css进行切换。
一般来说,v-if有更高的切换开销,而v-show则有更高的初始渲染开销
因此,如果需要非常频繁地切换,使用v-show比较好,如果在运行时条件不会改变时,用v-if比较好
切换时生命周期函数的执行
v-if
初始渲染
初始值为false时,不会渲染(所谓惰性),生命周期函数不会执行
初始值为true时,组件开始渲染,依次执行beforCreate,created,beforeMount,mounted等生命周期
切换时
从false到true:依次执行beforeCreate,created,beforeMount,moynted
从true到false:依次执行beforeDestroy,destroyed
v-show
初始渲染
无论初始状态为true还是false,组件都会渲染,依次执行beforeCreate,created,beforeMount,mounted
切换
基于css进行切换,对生命周期函数无影响.
1、vue-route
2、axios
3、vuex
4、Element UI
5、swiper
6、vue-echarts
7、vue-video-player
8、vue-photo-preview等等
1、hash模式,用URL hash值来做路由,支持所有浏览器;该模式实现的路由,在通过链接后面
添加““#”+路由名字”。
2、history模式,由h5提供的history对象实现,依赖H5 History API和服务器配置。
3、abstract模式,支持所有JS运行环境,如Node服务器端,如果发现没有浏览器的API,路由会
自动强制进入该模式。
子组件通过props来接受数据和通过$emit来触发父组件的自定义事件
建一个公共组件bus.js.。传递方通过事件触发bus.$emit。接收方通过在mounted(){}生命周期
里触发bus.$on。
$attrs(向下)$listeners(向上)<router-link to=`/a/${id}`>routerlink传参</router-link>
this.$router.push({
path: `/getlist/${id}`,
})
this.$router.push({
name: 'Getlist',
params: {
id: id
}
})
this.$router.push({
path: '/getlist',
query: {
id: id
}
})
注意:query有点像ajax中的get请求,而params像post请求。
params在地址栏中不显示参数,刷新页面,参数丢失,
其余方法在地址栏中显示传递的参数,刷新页面,参数不丢失。
原理:Vuex是专门为vue.js应用程序设计的状态管理工具。
1、state 保存vuex中的数据源,通过this.$store.state获取
2、getters 用于监听state中的值的变化,返回计算后的结果。getter的返回值会根据它的依赖
被缓存起来
3、mutations 是修改store中的值得唯一方式 //this.$store.commit('add')
4、action 官方建议提交一个actions,在actions中提交mutations再去修改状态值。
this.$store.dispatch('add')
5、modules 模块化
原因:因为vuex里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,vuex里面的数据就会被清空。
解决方法:将vuex中的数据直接保存到浏览器缓存中。(一般是用sessionStorage)
computed值有缓存、触发条件是依赖值发生更改、 watch无缓存支持异步、监听数据变化
computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生
改变,下一次获取 computed 的值时才会重新计算 computed 的值;
watch: 更多的是观察的作用,支持异步,类似于某些数据的监听回调 ,每当监听的数据变化时都
会执行回调进行后续操作;
computed应用场景:需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以
利用 computed 的缓存特性,避免每次获取值时,都要重新计算;
watch应用场景:需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch
选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结
果前,设置中间状态。这些都是计算属性无法做到的。
vue不能检测以下变动的数组:
1、当你利用索引直接设置一个项时,vm.items[indexOfItem] = newValue
2、当你修改数组的长度时,例如: vm.items.length = newLength
对象属性的添加或删除
由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。
解决办法:
使用 Vue.set(object, key, value) 方法将响应属性添加到嵌套的对象上
Vue.set(vm.someObject, ‘b’, 2) 或者 this.$set(this.someObject,‘b’,2) (这也是全局 Vue.set 方法的别名)
异步更新队列
在最新的项目中遇到了这种情况,数据第一次获取到了,也渲染了,但是第二次之后数据只有在再一次渲染页面的时候更新,并不能实时更新。
Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。
解决办法:
可在数据变化之后立即使用 Vue.nextTick(callback)。这样回调函数在 DOM 更新完成后就会调用
vue组件是可复用的vue实例,一个组件被创建好之后,就可能被用在各个地方,而组件不管被复用了多少次,组件中的data数据都应该是相互隔离,互不影响的.
基于这一理念,组件每复用一次,data数据就会被复制一次,之后,当某一处复用的地方组件内data数据被改变时,其他复用地方组件的data数据不受影响。
如果data是对象的话,每当被复用是,复用的对象和源对象都会指向同一个内存地址(浅拷贝),互相之间相互影响,所以要是函数
首先了解父子组件生命周期执行顺序
加载渲染数据过程
父组件 beforeCreate
父组件 created
父组件 beforeMount
子组件 beforeCreate
子组件 created
子组件 beforeMount
子组件 mounted
父组件 mounted
原因:因为生命周期只会执行一次,数据是要等到异步请求以后才能拿到,那么子组件的mounted钩子执行的时候,还没有拿到父组件传递过来的数据,但是又必须要打印出来结果,那这样的话,就只能去打印props中的默认值空字符串了,所以打印的结果是一个空字符串。
解决办法:
1、使用v-if控制组件渲染的时机
初始还没拿到后端接口的异步数据的时候,不让组件渲染,等拿到的时候再去渲染组件。使用v-if="变量"去控制,初始让这个变量为false,这样的话,子组件就不会去渲染,等拿到数据的时候,再让这个变量变成true,
举例:
data() {
return {
isTrue:false // 初始为false
};
},
monted(){
this.$post.a.b.c.getData(res=>{
if(res.result){
this.isTrue = true
}
})
}
2、使用watch监听数据的变化
举例:
props: {
tableData: {
type: Array,
default: [],
},
},
watch: {
tableData(val){
console.log(val)
}
},
3、使用VueX
router-link 标签跳转
this.$router.push()
this.$router.replace()
this.$router.go(n):(0:当前页,-1上一页,+1下一页,n代表整数)
为了性能优化, 因为vue是虚拟DOM,更新DOM时用diff算法对节点进行一一比对,比如有很多li元素,要在某个位置插入一个li元素,但没有给li上加key,那么在进行运算的时候,就会将所有li元素重新渲染一遍,但是如果有key,那么它就会按照key一一比对li元素,只需要创建新的li元素,插入即可,不需要对其他元素进行修改和重新渲染。
key也不能是li元素的index,因为假设我们给数组前插入一个新元素,它的下标是0,那么和原来的第一个元素重复了,整个数组的key都发生了改变,这样就跟没有key的情况一样了。
路由守卫分为三种 ——分别是:全局路由守卫、组件路由守卫、独享路由守卫。
全局守卫又分为全局前置守卫、和后置守卫
1. router.beforeEach((to,from,next)=>{})
回调函数中的参数,to:进入到哪个路由去,from:从哪个路由离开,next:函数,决定是否展示你要看到的路由页面。
从名字全局前置守卫不难理解,它是全局的,即对 整个单页应用(SPA) 中的所有路由都生效,所以当定义了全局的前置守卫,在进入每一个路由之前都会调用这个回调,那么如果你在回调中对路由的跳转条件判断出错,简单点就是死循环…因为你遗漏了某种路由跳转的情况,守卫会一直执行。所以在使用全局前置守卫的时候一定要判断清楚可能会出现的路由跳转的情况。
2.router.afterEach((to, from) => {})
只有两个参数,to:进入到哪个路由去,from:从哪个路由离。
理解了全局前置守卫,那么全局后置守卫也就那么一回事。全局后置守卫是整个单页应用中每一次路由跳转后都会执行其中的回调。所以多用于路由跳转后的相应页面操作,并不像全局前置守卫那样会在回调中进行页面的重定向或跳转。
组件路由守卫分为到达这个组件时,离开这个组件时
1. beforeRouteEnter:(to,from,next)=>{}——到达
to,from参数与上面使用方法一致。next回调函数略有不同。
2.beforeRouteUpdate:(to,from,next)=>{}——更新
3. beforeRouteLeave:(to,from,next)=>{}——离开
点击其他组件时,判断是否确认离开。确认执行next();取消执行next(false),留在当前页面。
1. beforeEnter:(to,from,next)=>{}
与全局路由守卫用法一致,但是只能针对一个页面使用
.stop:等统⼀JavaScript中的event.stopPropagation(),防⽌事件冒泡
.prevent:等同于JavaScript中的event。preventDefault(),防⽌执⾏预设的⾏为(如果事件可
取消,则取消该事件,⽽不停⽌事件的进⼀步传播);
.capture:与事件冒泡的⽅向相反,事件捕获由外到内
.self:只会触发⾃⼰范围内的事件,不包含⼦元素;
.once:只会触发⼀次。
数据驱动:ViewModel,保证数据和视图的⼀致性
组件系统:应⽤类UI可以看做全部是由组件树构成的
delete只是被删除的元素变成了empty/undefined其他的元素的键值还是不变。
Vue.delete直接删除了数组 改变了数组的键值
Mint UI,element,VUX
react 实例的生命周期,就是react实例从初始化,更新,到销毁的过程
初始化阶段:完成从react组件创建到首次渲染的过程
更新阶段:当调用setState函数时,会引起组件的重新渲染
销毁阶段:完成组件的销毁
constructor
构造函数里,可以做状态的初始化,接收props的传值
componentWillMount: 在渲染前调用,相当于vue中的beforeMount
render
渲染函数,不要在这里修改数据。 vue中也有render函数。
componentDidMount
渲染完毕,在第一次渲染后调用。
当组件的 props 或 state 发生变化时会触发更新(严谨的说,是只要调用了setState()或者改变了props时)。组件更新的生命周期调用顺序如下:
shouldComponentUpdate
是否更新? 需要返回true或者false。如果是false,那么组件就不会继续更新了。
componentWillUpdate
即将更新。
componentWillReceiveProps(nextProps): 在组件接收到一个新的 prop (更新后)时被调用。
这个方法在初始化render时不会被调用。nextProps 是props的新值,而 this.props是旧值。
render
不要在这里修改数据
componentDidUpdate
在组件完成更新后立即调用。在初始化时不会被调用。 相当于vue中的updated
componentWillUnmount()
即将卸载,可以做一些组件相关的清理工作,例如取消计时器、网络请求等
首先,(虚拟DOM是什么) 虚拟DOM就是一个JavaScript对象。通过这个JavaScript对象来描述真实DOM
如:
{
tagName:"p",
style:"width:200px;height: 100px;",
innerHTML:"我是p"
},
其次,操作虚拟DOM,就是在操作javascript对象,所以,并不会引起页面的重绘和重排。而操作真实DOM是会引起页面的重绘和重排的。
传统diff算法
需要遍历整棵树的节点然后进行比较,是一个深度递归的过程,运算复杂度常常是O(n^3)
react diff的优化策略
DOM节点跨层级的操作不做优化,因为很少这么做,这是针对的tree层级的策略;
对于同一个类的组件,会生成相似的树形结构,对于不同类的组件,生成不同的树形结构,这是针对
conponent层级的策略;
对于同一级的子节点,拥有同层唯一的key值,来做删除、插入、移动的操作,这是针对element层级
的策略;
合并state
把传入setState()里的参数对象和当前的state进行(属性)合并。 触发调和过程
(Reconciliation)
重新渲染组件
React 会以相对高效的方式根据新的状态构建 React 元素树并且着手重新渲染整个 UI 界面
React 会自动计算出新的树与老树的节点差异(用diff算法),然后根据差异对界面进行最小化重
渲染
state是组件的状态,也叫组件内部的数据
props是组件的属性,也可以认为是外部给组件传入的数据
setState是异步的。
如果要拿到修改后的状态,需要使用回调函数的方式,如下:
//改变状态后想做一些事情:
this.setState({
属性名:属性值
}, () => {
//一般是用于在setState之后做一些操作
//this.state == 修改之后的state
})
this.state.msg = “hello”;
因为,这样不会引起组件的重新渲染,所以,数据修改后没法 呈现在页面上。
而调用setState()函数,会引起组件的重新渲染,这样更新的数据就会呈现在页面上。
导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri
目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类
3月26日,映宇宙(HK:03700,即“映客”)发布截至2022年12月31日的2022年度业绩财务报告。财报显示,映宇宙2022年的总营收为63.19亿元,较2021年同期的91.76亿元下降31.1%。2022年,映宇宙的经营亏损为4698.7万元,2021年同期则为净利润4.57亿元;期内亏损(净亏损)为1.68亿元,2021年同期的净利润为4.33亿元;非国际财务报告准则经调整净利润为3.88亿元,2021年同期为4.82亿元,同比下降19.6%。 映宇宙在财报中表示,收入减少主要是由于行业竞争加剧,该集团对旗下产品采取更为谨慎的运营策略以应对市场变化。不过,映宇宙的毛利率则有所提升
技术选型1,前端小程序原生MINA框架cssJavaScriptWxml2,管理后台云开发Cms内容管理系统web网页3,数据后台小程序云开发云函数云开发数据库(基于MongoDB)云存储4,人脸识别算法基于百度智能云实现人脸识别一,用户端效果图预览老规矩我们先来看效果图,如果效果图符合你的需求,就继续往下看,如果不符合你的需求,可以跳过。1-1,登录注册页可以看到登录页有注册入口,注册页如下我们的注册,需要管理员审核,审核通过后才可以正常登录使用小程序1-2,个人中心页登录成功以后,我们会进入个人中心页我们在个人中心页可以注册人脸,因为我们做人脸识别签到,需要先注册人脸才可以进行人脸比对,进
在Rails3.x应用程序中,我正在使用net::ssh并向远程pc运行一些命令。我想向用户的浏览器显示实时日志。比如,如果两个命令在net中运行::ssh执行即echo"Hello",echo"Bye"被传递然后"Hello"应该在执行后立即显示在浏览器中。这是代码我在rubyonrails应用程序中使用ssh连接和运行命令Net::SSH.start(@servers['local'],@machine_name,:password=>@machine_pwd,:timeout=>30)do|ssh|ssh.open_channeldo|channel|channel.requ
我正在为Jekyll编写一个转换器插件,需要访问一些页眉(YAML前端)属性。只有内容被传递给主要的转换器方法,似乎无法访问上下文。例子:moduleJekyllclassUpcaseConverter关于如何在转换器插件中访问页眉数据有什么想法吗? 最佳答案 基于Jekyll源代码,无法在转换器中检索YAML前端内容。根据您的情况,我看到了两种可行的解决方案。您的文件扩展名可以具有足够的描述性,以提供您本应包含在前言中的信息。看起来Converter插件的设计就是这么基本的。如果修改Jekyll是一个选项,您可以更改Convert
只是想更新到最新版本的Ruby。在ruby-lang.org/en/documentation/installation/#homebrew上,我发现你应该可以通过自制软件来完成:brewinstallruby但是,当我在“更新”后列出ruby版本(ruby-v)时,它仍然是旧版本2.0.0。Hermes:~Sancho$ruby-vruby2.0.0p481(2014-05-08revision45883)[universal.x86_64-darwin13]我碰巧列出了/usr/local/bin/的内容,我可以看到一个符号链接(symboliclink):ruby->..
一、相关网址1、官网(可以下载,查看文章)https://skywalking.apache.org/downloads/2、github地址:(可提问题寻求帮助)https://github.com/apache/skywalking二、 实验环境操作系统 centos7.9先安装好 elasticsearch7.16.2操作系统安装好jdk8-17,实验机器jdk11java下载地址:https://www.oracle.com/java/technologies/downloads/#java8IP地址为192.168.24.160三、安装skywalking 1、下载skywalkin
?作者主页:静Yu?简介:CSDN全栈优质创作者、华为云享专家、阿里云社区博客专家,前端知识交流社区创建者?社区地址:前端知识交流社区?博主的个人博客:静Yu的个人博客?博主的个人笔记本:前端面试题个人笔记本只记录前端领域的面试题目,项目总结,面试技巧等等。接下来会更新蓝桥杯官方系统基础练习的VIP试题,依然包括解题思路,源代码等等。问题描述:给定当前的时间,请用英文的读法将它读出来。时间用时h和分m表示,在英文的读法中,读一个时间的方法是: 如果m为0,则将时读出来,然后加上“o’clock”,如3:00读作“threeo’clock”。 如果m不为0,则将时读出来,然后将分读出来,如5
如何用IDEA2022创建并初始化一个SpringBoot项目?目录如何用IDEA2022创建并初始化一个SpringBoot项目?0. 环境说明1. 创建SpringBoot项目 2.编写初始化代码0. 环境说明IDEA2022.3.1JDK1.8SpringBoot1. 创建SpringBoot项目 打开IDEA,选择NewProject创建项目。 填写项目名称、项目构建方式、jdk版本,按需要修改项目文件路径等信息。 选择springboot版本以及需要的包,此处只选择了springweb。 此处需特别注意,若你使用的是jdk1