Keys 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。javascript
render () {
return (
<ul>
{this.state.todoItems.map(
({item, key}) => {
return <li key={key}>{item}</li>
})
}
</ul>
)}
复制代码
在开发过程当中,咱们须要保证某个元素的 key 在其同级元素中具备惟一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近建立的仍是被移动而来的元素,从而减小没必要要的元素重渲染。此外,React 还须要借助 Key 值来判断元素与本地状态的关联关系,所以咱们毫不可忽视转换函数中 Key 的重要性。css
// 手机号码
function checkPhone(phone){
if(!(/^1[3456789]\d{9}$/.test(phone))){
alert("手机号码有误,请重填");
return false;
}
}
// 判断字符串以字母开头,后面能够是数字,下划线,字母,长度为6-30
function checout(str){
var reg=/^[a-zA-Z]\w{5,29}$/;
if(str && reg.test(str)){
alert('正确')
}
}
// 写一个function,清除字符串先后的空格。
function trim(str) {
if (str & typeof str === "string") {
return str.replace(/(^s*)|(s*)$/g,"");
}
}
复制代码
string,boolean,number,undefined,function,objecthtml
答案:强制(parseInt,parseFloat,number) 隐式(== ===)前端
答案:前者是将字符串切割成数组的形式,后者是将数组转换成字符串vue
相同点:改变函数的this指向java
var obj = {name: 'lisi'}
function fn() {
console.log(this)
}
fn.call(null) //this指向window
fn.apply(null) //this指向window
fn.call(obj) //this指向obj
fn.apply(obj) //this指向obj
复制代码
不一样点: call传参形式是,从第二个开始一个一个传,apply的第二个参数为数组,数组的每一项为函数的参数react
Object.call(this,obj1,obj2,obj3)
Object.apply(this,arguments)
复制代码
利用事件冒泡的原理,让本身的所触发的事件,让他的父元素代替执行!git
***闭包***就是可以读取其余函数内部变量的函数,使得函数不被GC回收,若是过多使用闭包,容易致使内存泄露(再也不用到的内存,没有及时释放,就叫作内存泄漏) 闭包的好处 但愿一个变量长期驻扎在内存当中(不被垃圾回收机制回收), 避免全局变量的污染,私有成员的存在,安全性提升 闭包使用场景: 函数做为返回值;函数做为参数传递;闭包实际应用中主要用于封装变量,收敛权限;web
阻止事件冒泡:ev.stopPropagation();何阻止默认事件: (1)return false;(2) ev.preventDefault();面试
动态建立script标签,回调函数,Ajax是页面无刷新请求数据操做
前者会自动转换类型,再判断是否相等,后者不会自动类型转换,直接去比较
在Javscript中,解析器在向执行环境中加载数据时,对函数声明和函数表达式并不是是一视同仁的,解析器会率先读取函数声明,并使其在执行任何代码以前可用(能够访问),至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解析执行。
// 函数声明
function add(){}
// 函数表达式
var del = function del(){} // 命名函数函数表达式
var update= function(){} // 命名函数函数表达式
function(){} // 匿名函数表达式
复制代码
函数表达式能够直接在函数定义后面加小括号执行,而函数声明则不行
var mult = function(x,y){ return(x*y); }();//正常
function div(x,y){ return(x/y); }()//报错
复制代码
var User = {
count: 1,
getCount: function() {
return this.count;
}
};
console.log(User.getCount()); // what?
var func = User.getCount;
console.log(func()); // what?
复制代码
问两处console输出什么?为何? 答案:是1和undefined。 func是在window的上下文中被执行的,因此不会访问到count属性。
for(var i = 1; i <= 3; i++){ //建议使用let 可正常输出i的值
setTimeout(function(){
console.log(i);
},0);
};
复制代码
答案:4 4 4。 缘由:Javascript事件处理器在线程空闲以前不会运行。
事件代理
var a = null;
alert(typeof a);
答案:object
复制代码
解释:null是一个只有一个值的数据类型,这个值就是null。表示一个空指针对象,因此用typeof检测会返回”object”。
<script>
var a = 100;
function test(){
alert(a);
a = 10; //去掉了var 就变成定义了全局变量了
alert(a);
}
test();
alert(a);
</script>
复制代码
正确答案是: 100, 10, 10
var oldObject ="sdf";
var newObject = JSON.parse(JSON.stringify(oldObject));
console.log(newObject);
复制代码
function(url, fn) {
// XMLHttpRequest对象用于在后台与服务器交换数据
var obj = new XMLHttpRequest();
obj.open('GET', url, true);
obj.onreadystatechange = function() {
if(obj.readyState == 4 && obj.status == 200||obj.status == 304){
loading.style.display = "none"
} else {
alert("不能点击,哈哈哈!");
}
};
obj.send(null);
}
复制代码
// 建立一个1-10000的数组集合
var arr = new Array(10000).fill('').map((item, index) => {
return index + 1
}
)
// 筛选出了全部带0的数字
var nerArrrr = arr.filter(item => /0/.test(item))
var length = nerArrrr.reduce((count, item) => {
return count + (String(item).match(/0/g)).length
}, 0)
console.log(length)
复制代码
var arr = [[0,1,2,3], [4,5,6,7], [8,9,0,1], [2,3,4,5]];
// 方法一
var result = [];
for(var i=0;i<arr.length;i++){
for(var j=0;j<arr[i].length;j++){
result.push(arr[i][j]);
}
}
// 方法二
var result = [];
for(var i=0;i<arr.length;i++){
result = result.concat(arr[i]);
}
// 方法三
function Jw(obj){
return Array.prototype.concat.apply([],obj);
}
Jw(arr);
复制代码
function getUrlDic(){
var queryDec = window.location.search.substring(1).split("&")
var decObect = {}
for(var i = 0; i < queryDec.length; i++){
var searchHash = queryDec[i].split("=")
var key = decodeURIComponent(searchHash[0])
var value = decodeURIComponent(searchHash[1])
decObect[key] = value
}
console.log(decObect)
}
getUrlDic()
复制代码
let str = 'asfjasiofoivnoi';
function count(str){
let obj = {},
arr = str.split('');
//遍历数组
arr.forEach(function(val,index){
//将数组的元素存入对象,初始值为1,若是后面遍历的元素以前已存在就+1
if(obj[val]){
obj[val]+=1;
}else{
obj[val]=1
}
})
//遍历对象中的属性(字符),值(出现的次数)
let num=0
for(let key in obj){
if(num < obj[key]){
//将最多的次数赋给num
num = obj[key];
}
}
for(let key in obj){
if(num == obj[key]){
console.log('最多的字符串是'+key+', 出现次数是'+num);
}
}
}
count(str);
复制代码
一、首先看一个判断题:null和undefined 是否相等
console.log(null==undefined)//true
console.log(null===undefined)//false
typeof null; // "object"
typeof undefined; // "undefined"
复制代码
二、那到底何时是null,何时是undefined呢?null表示"没有对象",即该处不该该有值。典型用法是
做为函数的参数,表示该函数的参数不是对象。
做为对象原型链的终点。
undefined表示"缺乏值",就是此处应该有一个值,可是尚未定义。典型用法是:
咱们知道 new 运算符是用来实例化一个类,从而在内存中分配一个实例对象。
new共通过了4几个阶段 一、建立一个空对象
var obj=new Object();
复制代码
二、设置原型链
obj.__proto__= Base.prototype;
复制代码
三、让Base中的this指向obj,并执行Base的函数体。
var result =Base.call(obj);
复制代码
四、判断Base的返回值类型:若是是值类型,返回obj。若是是引用类型,就返回这个引用类型的对象。
if (typeof(result) == "object"){
Base=result;
}
else{
Base=obj;;
}
复制代码
defer和async都是可选的,且只对外部脚本文件有效
<script src="main.js"></script>
复制代码
浏览器会当即加载并执行指定的脚本,“当即”指在渲染该script标签之下的文档元素以前,也就是说不等待后续载入的文档元素,读到就加载并执行。
<script async src="main.js"></script>
复制代码
浏览器会当即下载脚本,但不妨碍页面中的其余操做,好比下载其余资源或等待加载其余脚本。加载和渲染后续文档元素的过程和main.js的加载与执行并行进行(异步)。
async不保证按照脚本出现的前后顺序执行,所以,确保二者以前互不依赖很是重要,指定async属性的目的是不让页面等待两个脚本的下载和执行,从而异步加载页面其余内容,建议异步脚本不要在加载期间修改DOM。
异步脚本必定会在页面的load事件前执行,但可能会在DOMContentLoaded事件触发以前或以后执行。
<script defer="defer" src="main1.js"></script>
<script defer="defer" src="main2.js"></script>
复制代码
表示脚本会被延迟到文档彻底被解析和显示以后再执行,加载后续文档元素的过程将和main.js的加载并行进行(异步)。HTML5规范要求脚本按照它们出现的前后顺序执行,所以第一个延迟脚本会先于第二个延迟脚本执行,而这两个脚本会先于DOMContentLoaded事件。在现实当中,延迟脚本并不必定会按照顺序执行,也不必定会在DOMContentLoaded事件触发前执行,所以***最好只包含一个延迟脚本。***
defer和async、动态建立DOM方式(建立script,插入到DOM中,加载完毕后callBack)、按需异步载入js
首先传输对象的双向数据绑定 Object.defineProperty(target, key, decription),在decription中设置get和set属性(此时应注意description中get和set不能与描述属性共存) 数组的实现与对象不一样。
let obj = {}
let input = document.getElementById('input')
let span = document.getElementById('span')
Object.defineProperty(obj, 'text', {
configurable: true,
enumerable: true,
get() {
console.log('获取数据了')
},
set(newVal) {
console.log('数据更新了')
input.value = newVal
span.innerHTML = newVal
}
})
input.addEventListener('keyup', function(e) {
obj.text = e.target.value
})
复制代码
同时运用观察者模式实现wather, 完成用户数据和view视图的更新
function getQueryVariable(variable)
{
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == variable){return pair[1];}
}
return(false);
}
复制代码
setState() 将老是触发一次重绘,除非在 shouldComponentUpdate() 中实现了条件渲染逻辑。若是可变对象被使用了,但又不能在 shouldComponentUpdate() 中实现这种逻辑,仅在新 state 和以前的 state 存在差别的时候调用 setState() 能够避免没必要要的从新渲染。
react setState后:
setState—常规状况:在同一个方法中屡次setState是会被合并的,而且对相同属性的设置只保留最后一次的设置 参考详情
初始化阶段,这是组件即将开始其生命之旅并进入 DOM 的阶段。
getDefaultProps:获取实例的默认属性
getInitialState:获取每一个实例的初始化状态
componentWillMount:组件即将被装载、渲染到页面上,在渲染以前执行,在客户端和服务器端都会执行
render:组件在这里生成虚拟的 DOM 节点
componentDidMount:仅在第一次渲染后在客户端执行,组件真正在被装载以后(请求数据)
运行中状态;一旦组件被添加到 DOM,它只有在 prop 或状态发生变化时才可能更新和从新渲染。这些只发生在这个阶段。
componentWillReceiveProps:经过父组件修props改时候调用,当从父类接收到 props 而且在调用另外一个渲染器以前调用。
shouldComponentUpdate:(nextProps及nextState)组件接受到新属性或者新状态的时候(能够返回 false,接收数据后不更新,阻止 render 调用,后面的函数不会被继续执行了)
componentWillUpdate:在 DOM 中进行渲染以前调用,组件即将更新不能修改属性和状态
render:组件从新描绘
componentDidUpdate:在渲染发生后当即调用,组件已经更新
销毁阶段,这是组件生命周期的最后阶段,组件被销毁并从 DOM 中删除
componentWillUnmount:组件被卸载的时候调用。在此方法中执行任何须要的清理,通常在componentDidMount里面注册的事件须要在这里删除,例如使计时器无效、取消网络请求或清除在组件,清理内存空间
Cookies就是服务器暂存放在你的电脑里的文本文件,好让服务器用来辨认你的计算机。当你在浏览网站的时候,Web服务器会先送一小小资料放在你的计算机上,Cookies 会帮你在网站上所打的文字或是一些选择都记录下来。当下次你再访问同一个网站,Web服务器会先看看有没有它上次留下的Cookies资料,有的话,就会依据Cookie里的内容来判断使用者,送出特定的网页内容给你。
方法一:Array.from()方法能够将Set结构转化为数组结构
function unique(array) {
return Array.from(new Set(array));
}
unique([1,2,3,3]);
复制代码
方法二:扩展运算符(…)内部使用for…of循环
let arr = [1,2,3,3];
let unique = [...new Set(arr)];
复制代码
方法三
function unique(arr){
var isRepeated, result = [];
for(var i=0; i<arr.length; i++){
isRepeated = false;
for(var j=0; j<result.length; j++){
if(arr[i] === result[j]){
isRepeated = true;
break;
}
}
if(!isRepeated){
result.push(arr[i]);
}
}
return result;
}
var arr = [1,2,3,4,3,2,1,2,3];
console.log(unique(arr));
复制代码
对内:模块模式
对外:继承
代码重用
避免全局变量(命名空间,封闭空间,模块化mvc..)
拆分函数避免函数过于臃肿
注释
子构造函数中执行父构造函数,并用call\apply改变this 克隆父构造函数原型上的方法
react总体是函数式的思想,把组件设计成纯组件,状态和逻辑经过参数传入,因此在react中,是单向数据流,推崇结合immutable来实现数据不可变。react在setState以后会从新走渲染的流程,若是shouldComponentUpdate返回的是true,就继续渲染,若是返回了false,就不会从新渲染,PureComponent就是重写了shouldComponentUpdate,而后在里面做了props和state的浅层对比。
而vue的思想是响应式的,也就是基因而数据可变的,经过对每个属性创建Watcher来监听,当属性变化的时候,响应式的更新对应的虚拟dom。
总之,react的性能优化须要手动去作,而vue的性能优化是自动的,可是vue的响应式机制也有问题,就是当state特别多的时候,Watcher也会不少,会致使卡顿,因此大型应用(状态特别多的)通常用react,更加可控。
// 第一种
#container{
position:relative;
}
#center{
width:100px;
height:100px;
position:absolute;
top:50%;
left:50%;
transform: translate(-50%,-50%);
}
// 第二种
#container{
position:relative;
}
#center{
width:100px;
height:100px;
position:absolute;
top:50%;
left:50%;
margin:-50px 0 0 -50px;
}
// 第三种
#container{
position:relative;
}
#center{
position:absolute;
margin:auto;
top:0;
bottom:0;
left:0;
right:0;
}
// 第四种 flex
#container{
display:flex;
justify-content:center;
align-items: center;
}
复制代码
JSON.stringify(obj)==JSON.stringify(obj);//true
复制代码
router-link
router.go(1)
router.push('/')
复制代码
router 是 hash 改变
location.href 是页面跳转,刷新页面
复制代码
部分渲染树(或者整个渲染树)须要从新分析而且节点尺寸须要从新计算。这被称为重排。注意这里至少会有一次重排-初始化页面布局。 因为节点的几何属性发生改变或者因为样式发生改变,例如改变元素背景色时,屏幕上的部份内容须要更新。这样的更新被称为重绘。
git stash //将本次修改存到暂存区(紧急切换分支时)
git stash list
git stash pop //将全部暂存区的内容取出来
复制代码
git add # 将工做区的修改提交到暂存区
git commit # 将暂存区的修改提交到当前分支
git reset # 回退到某一个版本
git stash # 保存某次修改
git pull # 从远程更新代码
git push # 将本地代码更新到远程分支上
git reflog # 查看历史命令
git status # 查看当前仓库的状态
git diff # 查看修改
git log # 查看提交历史
git revert # 回退某个修改
复制代码
html文件是自上而下的执行方式,但引入的css和javascript的顺序有所不一样,css引入执行加载时,程序仍然往下执行,而执行到script脚本是则中断线程,待该script脚本执行结束以后程序才继续往下执行。 因此,大部分网上讨论是将script脚本放在body以后,那样dom的生成就不会由于长时间执行script脚本而延迟阻塞,加快了页面的加载速度。 但又不能将全部的script放在body以后,由于有一些页面的效果的实现,是须要预先动态的加载一些js脚本。因此这些脚本应该放在body以前。 其次,不能将须要访问dom元素的js放在body以前,由于此时尚未开始生成dom,因此在body以前的访问dom元素的js会出错,或者无效 script放置位置的原则“页面效果实现类的js应该放在body以前,动做,交互,事件驱动,须要访问dom属性的js均可以放在body以后
npm install
npm run dev
npm run build
安装模块;
-save-dev 是指将包信息添加到 package.json 里的 devDependencies节点,表示开发时依赖的包。
npm install --save-dev
-save 是指将包信息添加到 package.json 里的dependencies节点,表示发布时依赖的包。
npm install --save
复制代码
keep-alive是Vue.js的一个内置组件。它可以把不活动的组件实例保存在内存中,而不是直接将其销毁,它是一个抽象组件,不会被渲染到真实DOM中,也不会出如今父组件链中。 它提供了include与exclude两个属性,容许组件有条件地进行缓存。
(1)域名解析 在浏览器地址栏输入URL,浏览器查看缓存,判断请求资源是否新鲜,浏览器解析URL获取协议,主机,端口,path。浏览器组装一个HTTP(GET)请求报文,浏览器获取主机ip地址(从缓存、hosts、路由、DNS解析等)
(2)TCP链接HTTP协议是使用TCP协议做为其传输层协议的,在拿到服务器的IP地址后,浏览器客户端会与服务器创建TCP链接。该过程包括三次握手
第一次握手:创建链接时,客户端向服务端发送请求报文 第二次握手:服务器收到请求报文后,如赞成链接,则向客户端发送确认报文 第三次握手,客户端收到服务器的确认后,再次向服务器给出确认报文,完成链接。
三次握手主要是为了防止已经失效的请求报文字段发送给服务器,浪费资源。 **(3)浏览器发送HTTP请求 浏览器构建http请求报文,并经过TCP协议传送到服务器的指定端口。http请求报文一共包括三个部分: 请求行:指定http请求的方法、url、http协议版本等 请求头:描述浏览器的相关信息,语言、编码等,是否包含缓存验证信息若是验证缓存新鲜,返回304 请求正文:当发送POST,PUT等请求时,一般须要向服务器传递数据。这些数据就储存在请求正文中。
(4)浏览器接受相应
而后根据状况选择关闭TCP链接或者保留重用; 若是资源可缓存,进行缓存; 对响应进行解码(例如gzip压缩); 根据资源类型决定如何处理(假设资源为HTML文档);
(6)浏览器页面渲染 解析HTML文档,构件DOM树,下载资源,构造CSSOM树,执行js脚本,这些操做没有严格的前后顺序,如下分别解释 构建DOM树: 根据HTML规范将字符流解析为标记 词法分析将标记转换为对象并定义属性和规则 根据HTML标记关系将对象组成DOM树 解析过程当中遇到图片、样式表、js文件,启动下载 构建CSSOM树: 字符流转换为标记流 根据标记建立节点 节点建立CSSOM树 根据DOM树和CSSOM树构建渲染树: 从DOM树的根节点遍历全部可见节点,不可见节点包括:
- script,meta这样自己不可见的标签
- 被css隐藏的节点,如display: none
复制代码
对每个可见节点,找到恰当的CSSOM规则并应用 发布可视节点的内容和计算样式
js解析以下:
浏览器建立Document对象并解析HTML,将解析到的元素和文本节点添加到文档中,此时document.readystate为loading HTML解析器遇到没有async和defer的script时,将他们添加到文档中,而后执行行内或外部脚本。这些脚本会同步执行,而且在脚本下载和执行时解析器会暂停。这样就能够用document.write()把文本插入到输入流中。同步脚本常常简单定义函数和注册事件处理程序,他们能够遍历和操做script和他们以前的文档内容 当解析器遇到设置了async属性的script时,开始下载脚本并继续解析文档。脚本会在它下载完成后尽快执行,可是解析器不会停下来等它下载。异步脚本禁止使用document.write(),它们能够访问本身script和以前的文档元素 当文档完成解析,document.readState变成interactive 全部defer脚本会按照在文档出现的顺序执行,延迟脚本能访问完整文档树,禁止使用document.write() 浏览器在Document对象上触发DOMContentLoaded事件 此时文档彻底解析完成,浏览器可能还在等待如图片等内容加载,等这些内容完成载入而且全部异步脚本完成载入和执行,document.readState变为complete,window触发load事件 显示页面(HTML解析过程当中会逐步显示页面)
引入JsBridge(安卓)或WebViewJavascriptBridge(iOS)库的方案,首先安卓、iOS、web前端三方要在一块儿定义好须要使用的接口的方法名及传递的参数,三方统一,定义好各个方法及传递的方式
redux中间件中间件提供第三方插件的模式,自定义拦截 action -> reducer 的过程。变为 action -> middlewares -> reducer 。这种机制可让咱们改变数据流,实现如异步 action ,action 过滤,日志输出,异常报告等功能。常见的中间件:
根据组件的职责一般把组件分为UI组件和容器组件。UI 组件负责 UI 的呈现,容器组件负责管理数据和逻辑。二者经过React-Redux 提供connect方法联系起来。、
虚拟dom至关于在js和真实dom中间加了一个缓存,利用dom diff算法避免了没有必要的dom操做,从而提升性能。
具体实现步骤以下:用 JavaScript 对象结构表示 DOM 树的结构;而后用这个树构建一个真正的 DOM 树,插到文档当中当状态变动的时候,从新构造一棵新的对象树。而后用新的树和旧的树进行比较,记录两棵树差别把2所记录的差别应用到步骤1所构建的真正的DOM树上,视图就更新了。
把树形结构按照层级分解,只比较同级元素。给列表结构的每一个单元添加惟一的key属性,方便比较。React 只会匹配相同class的component (这里面的class指的是组件的名字)合并操做,调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每个事件循环结束, React 检查全部标记 dirty 的component从新绘制.选择性子树渲染。开发人员能够重写shouldComponentUpdate提升diff的性能。