1.为什么要选vue?与其它框架对比的优势和劣势?
(1)vue:
优点:
1.双向数据绑定
2.组件化开发
3.采用virtual DOM
4.轻量高效
5.动画系统
Virtual DOM则是虚拟DOM的英文,简单来说,他就是一种可以预先通过JavaScript进行各种计算,把最终的DOM操作计算出来并优化,由于这个DOM操作属于预处理操作,并没有真实的操作DOM,所以叫做虚拟DOM。最后在计算完毕才真正将DOM操作提交,将DOM操作变化反映到DOM树上。
缺点:
1.不支持IE8及以下版本
2.生态不太成熟,例如编辑器中的语法提示不太完善
3.社区无法与angular和react相比
(2)0angular:
相同点:
1.都支持指令,内置指令和自定义指令
2.都支持过滤器,内置过滤器和自定义过滤器
3.都支持双向数据绑定,
4.都不支持低端浏览器
不同点:
1.Angular的学习成本较高,二vue.js本提供的api就比较简单.直观
2.从性能上来说: AngularJS依赖对数据做脏检查.Vue.js使用基于依赖追踪的观察并且使用异步队列更新。所有的数据都是独立触发的。
(3)react:
相同点:
1.react采用特殊的jsx语法,vue进行组件化编写,采用.vue特殊文件格式,两者都需用编译后使用.
2.中心思想相同:都是组件化开发,组件实例之间可进行嵌套
3.都提供了合理的钩子函数,可让开发者定制化的处理需求
4.都没有内置ajax,Route等核心包,而是以插件的方式加载.
不同点:
1.React采用的Virtual DOM会对渲染出来的结果做脏检查
2.Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作DOM。react没有
2.mvvm框架是什么?它和其它框架(jquery)的区别是什么?哪些场景适合?
(1)mvvm框架是什么?
MVVM是Model-View-ViewModel的简写。
Model:模型
View:视图
ViewModel:视图模型,连接view和model的桥梁
通常要实现一个observer观察者,当数据发生变化,ViewModel能够监听到数据的这种变化,然后通知到对应的视图做自动更新,而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定。
(2)它和其它框架(jquery)的区别是什么
概念上:
vue:前端js库,是一个精简的MVVM,它专注于MVVM模型的viewModel层,通过双向数据绑定把view和model层连接起来,通过对数据的操作就可以完成对页面视图的渲染。
jquery:轻量级的js库
在操作思想上:
vue是使用数据驱动的方式,通过vue对象将数据和view完全分离开,对数据操作,不在引用相应的DOM对象,通过vue对象,将数据和相应的DOM对象相互绑定起来;主要是操作数据 基于一种MVVM模式。
jQuery是使用选择器($)选取DOM对象,并对其进行赋值、取值、事件绑定等操作,主要是操作DOM
(3)哪些场景适合?应用场景的区别:
vue适用的场景:复杂数据操作的后台页面,表单填写页面
jquery适用的场景:比如说一些html5的动画页面,一些需要js来操作页面样式的页面。
二者也是可以结合起来一起使用的,vue侧重数据绑定,jquery侧重样式操作,动画效果等,则会更加高效率的完成业务
3.vue单页面应用及其优缺点有哪些?
原生页面:实现页面之间跳转,就是真实的页面跳转(N个.html)
单页面:实现页面跳转,通过路由实现.
优点:
1.用于体验更优,用户跳转页面时,基本通过ajax请求数据
2.做前后端分离.后端提供http协议接口,前端通过api请求数据.
缺点:
1.不利于SEO优化.因为使用单页面应用之后,所有的资源文件(eg:css,js,img)统一放在一个文件中,一旦文件非常大时,页面加载速度会变得非常慢.
2.首屏加载速度慢.
4.说出至少4种vue当中的指令和它的用法?
(1){{}} 、v-html 和v-text ==》 非表单元素
{{}}:以{{data的属性名}}的方式直接使用在标签之间
例如: <div>{{name}}</div>
1.{{}}不能解析data中属性值中的标签
2.当vue.js没有加载出来时,页面中显示{{}}一类的数据,不利于用户体验
3.解决闪屏问题:通过指令v-cloak实现:v-cloak绑定在作用于vue实例的标签上,当vue.js没有加载完成时,设置[v-cloak]的样式为:diplay:none,当vue.js在家完成后,将[v-cloak]作用的元素样式改为:display:block
<style>
[v-cloak]{
display: none;
}
</style>
V-html:以标签的属性形式使用
1.v-html写在标签中,当做属性展示
2.v-html的值是data的属性名
3.标签中的内容不再浏览器体现.
4.v-text可以解析data中属性值中的标签
5.当vue.js没有加载出来时,页面中不展示任何数据
V-text:同样以标签属性的形式使用
1.v-text写在标签中,当做属性展示
2.v-text的值是data的属性名
3.标签中的内容不再浏览器体现.
4.v-text不能解析data中属性值中的标签
5.当vue.js没有加载出来时,页面中不展示任何数据
(2)v-model双向数据绑定指令 ==》 表单元素
1.v-model的值是data的属性名
2.input的框的值是data的属性名对应的值,value属性在这里不起任何作用
(3)V-bind指令:绑定属性 ==》 媒体元素
1.v-bind指令:一般绑定的是属性(将标签原有的属性与data的属性进行绑定)
2.书写形式: v-bind:属性名="data中的属性名"
3. v-bind:简写形式: :属性名="data中的属性名"
(4)v-if和v-show 指令都是用于控制元素的隐藏与显示
使用的时候同样是当做标签的属性进行使用
<div v-if="true">春花秋月何时了</div>
<div v-show="false">南来北往</div>
相同点:都是控制着元素的显示和隐藏
不同点:当表达式的值为false,v-if采用的惰性模式,v-show通过样式中的属性display:none来控制
在实际应用中:
1.v-if:一般使用在页面一旦加载完成,几乎不再修改,可以使用
2.v-show:使用在元素切换频率比较高的情况下(eg:选项卡切换)
(5)v-for指令:遍历
1.遍历数组
2.遍历数值
3.遍历字符串
4.遍历对象
数组:
v-for="(item,index) in 数组名称"
v-for="(item,index) of 数组名称"
item:指数组的每一项
index:指数组下标
<ul>
<li v-for="(item,index) in arr">{{index}}==={{item}}</li>
</ul>
对象:
v-for="(item,key,index) in 对象名称"
item:指对象中的每一项值
key:对象的键
index:对象的下标
(6)v-once指令 作为标签的属性进行使用
v-once:指当前元素和它的所有子级首次在页面显示完成之后,不会再进行修改
<div v-once>
<p>{{num}}</p>
</div>
5.常用的事件修饰符都有哪些?分别说明它们的作用。
.prevent .stop .capture .up .down .enter .13 .left .right
表单修饰符
lazy
失去焦点时,获取数据
<div>name:{{user.username}}</div>
<div>
用户名: <input type="text" v-model.lazy="user.username" value="root" />
</div>
number
将数据类型修改为number
<div>price:{{user.username}}</div>
<div>
用户名: <input type="text" v-model.number="user.username" value="root" />
</div>
trim
去掉字符串两边的空格
<div>trim:{{user.username}}</div>
<div>
用户名: <input type="text" v-model.trim="user.username" value="root" />
</div>
事件修饰符
- 执行一次
once
<button @click.once="add">按钮</button>
add(){
console.log('只执行一次');
}
- 阻止默认事件
prevent
<!-- prevent阻止默认事件 -->
<button @contextmenu.prevent="add1">阻止默认事件</button>
<textarea @keydown.enter.prevent="enter" id="" cols="30" rows="10"></textarea>
add1(){
console.log('阻止默认事件');
},
enter(){
console.log('回车了');
}
- 阻止事件传播
stop
<!-- stop阻止事件传播 -->
<div class="outer" @click="outer">
<div class="inner" @click.stop="inner"></div>
</div>
outer(){
console.log('outer');
},
inner(){
console.log('inner');
}
- 阻止自己身上的冒泡行为
self
<!-- 案例 -->
<button @click="isShow = true">删除</button>
<div class="main" v-if="isShow" @click.self="isShow=false">
<div class="con">
<h2>确定要删除吗?</h2>
<div>
<button class="btn" @click="confirm">确定</button>
<button class="btn" @click="isShow=false">取消</button>
</div>
</div>
</div>
- 捕获
capture
添加事件侦听器时使用事件捕获模式 : 用捕获的模式来触发
<!-- capture捕获改变触发事件的顺序 -->
<div class="outer" @click.capture="outer1">
<div class="inner" @click="inner1"></div>
</div>
按键修饰符
- .enter => enter键
- .tab => tab键
- .delete (捕获“删除”和“退格”按键) => 删除键
- .esc => 取消键
- .space => 空格键
- .up => 上键
- .down => 下键
- .left => 左键
- .right => 右键
<!-- 键盘事件 @keydown-->
<input type="text" @keydown.enter="enter" @keydown.13="enter" @keydown.left="left" @keydown.right="right" @keydown.up="up" @keydown.down="down">
6.什么是Vue的生命周期?
Vue生命周期是指vue实例对象从创建之初到销毁的过程,vue所有功能的实现都是围绕其生命周期进行的,在生命周期的不同阶段调用对应的钩子函数可以实现组件数据管理和DOM渲染两大重要功能
Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。
7.解析Vue生命周期中各个钩子函数分别在什么场景下执行。
1、beforeCreate:创建之前:所有的都是undefined
2、created创建完成:el还是undefined,此时数据已经存在,组件实例创建完成,属性已绑定,但DOM还未生成,$el属性还不存在
3、beforeMount挂载之前:找到挂载点,但是数据还没有被解析
4、mounted挂载完成:找到挂载点,数据被解析,渲染页面完成.到此处就可以开启轮播图,计时器.延时器.发送ajax请求.
5、beforeUpdate更新之前:数据已经是最新的,此处指的是页面再次渲染之前.
6、updated更新完成:数据已经是最新的,此处指的是页面再次渲染完成.
7、beforeDestroy销毁之前
8、destroyed销毁完成
9、for keep-alive ,组件被激活时调用
10 、for keep-alive,组件被移除时调用
8.说明watch和computed的作用与区别
watch中的函数是不需要调用的
computed内部的函数调用的时候不需要加()
watch 属性监听 监听属性的变化,需要在数据变化时执行异步或开销较大的操作时使用
computed:计算属性通过属性计算而得来的属性,属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用;
watch擅长处理的场景:一个数据影响多个数据;
computed擅长处理的场景:一个数据受多个数据影响。
9.说明watch和methods的作用与区别
watch .是观察的动作,自动执行
methods 是方法,主动调用
10.Vue中过滤器如何定义和使用?
定义:
vue过滤器主要用于对渲染出来的数据进行格式化处理。
使用场景
例如:后台返回的数据性别用0和1表示,但渲染到页面上不能是0和1我得转换为“男“和”女”或是商品价
使用:
(1)全局过滤器
// 全局过滤器
/**
* 1.参数一:过滤器的名称,自定义
* 2.参数二:回调函数,回调函数中有一个系统自动注入的参数
* 参数值为:要过滤的值
*/
Vue.filter('过滤器的名称',(e)=>{
return e.slice(0,4)
})
(2)局部过滤器
new Vue({
// 局部过滤器
filters:{
过滤器名称:function(e){
return e.toFixed(2)
}
}
});
11.使用过滤器实现实现日期的格式化,只显示年月日。(提示:使用时间戳)
12.过渡动画在什么场景下使用?有哪几个内置的类名?
使用场景:
企业官网等
当插入,修改或者删除元素的时,需要动画效果使得操作变得非常优美
原生写法
提供了6个自动注入的类名:
.v-enter: 出现之前
.v-enter-active:出现过程
.v-enter-to:出现完成
.v-leave:离开之前
.v-leave-active:离开过程
.v-leave-to:离开结束
需要结合transition标签使用,默认没有name属性时,类名前缀为v-, 有name属性时,类名前缀为name属性的值.
.v-enter{
left:0;
opacity: 0.1;
transform: scale(0.1,0.1);
}
.v-enter-active,.v-leave-active{
transition:all 3s;
}
.v-enter-to{
left:100px;
opacity: 1;
transform:scale(1,1);
}
.v-leave{
left:100px;
opacity: 1;
transform:scale(1,1);
}
.v-leave-to{
left:0;
opacity: 0.1;
transform: scale(0.1,0.1);
}
<div id="app">
<button @click="isShow=!isShow">切换</button>
<transition name="aa">
<div class="box" v-if="isShow"></div>
</transition>
</div>
animate.css
1.下载安装模块
cnpm i animate.css --save
2.引入
<link rel="stylesheet" href="./node_modules/_animate.css@4.1.1@animate.css/animate.css">
3.使用
<div id="app">
<button @click="isShow=!isShow">切换</button>
<transition enter-active-class="animate__animated animate__fadeInLeftBig"
leave-active-class="animate__animated animate__bounceOutDown">
<div class="box" v-if="isShow"></div>
</transition>
</div>
注意:
enter-active-class:进入动画
leave-active-class:离开动画
添加类名的时候,需要添加基类,比如:animate__animated
需要结合transition标签使用,默认没有name属性时,类名前缀为v-, 有name属性时,类名前缀为name属性的值.
13.vue中遇到bug?
1.如果使用{{}},首屏会出现闪屏,用v-text解决
2.使用深度监听,可能会造成页面卡顿。解决:转成简单类型,进行监听
3.在vue中,不推荐v-for和v-if同时使用。如果需要同时使用,记得使用computed解决
4.数组或者json变了,页面不渲染。解决:Vue.set() vm.$set() ,如果是数组,还可以使用splice
14.字符串方法
<script>
ength://字符串的长度,每个字符都会占一个长度。字符串的下标从0开始,到length-1
charAt(下标)://返回下标对应的字符
charCodeAt(下标)://获取对应下标的字符编码 0:48 A:65 a:97
indexOf(str[,index])://返回某个指定的字符串在目标字符串中首次出现的位置。找不到就返回-1。
lastIndexOf()://返回某个指定的字符串在目标字符串中最后一次出现的位置。找不到就返回-1。
split(分隔符[,数组的长度])://把字符串使用指定的分隔符切割成数组,可以指定返回的数组的长度。
toLowerCase():// 小写
toUpperCase(): //大写
replace()://字符串的替换,接受两个参数,第一个参数是将要被替换的内容,第二个参数是替换的新内容
trim(): //去掉字符串的左右空格,不兼容IE8及以下
substring(start, stop):// 截取字符串,参数可选,从start位置截取到stop的位置,不包括stop位置 slice(start,stop): 用法与substring一致
substr(start, length):// 从start开始截取,截取length个
</script>
15.时间对象
Date
获取时间的方式
// 创建时间对象
var d = new Date();
console.log(d);
// 获取年份
console.log(d.getFullYear());
// 获取月份 从0开始
console.log(d.getMonth());
// 获取日期
console.log(d.getDate());
// 获取星期 从0开始,0表示周日
console.log(d.getDay());
// 获取小时
console.log(d.getHours());
// 获取分钟
console.log(d.getMinutes());
// 获取秒
console.log(d.getSeconds());
// 获取时间戳
console.log(d.getTime());
创建时间的方式(设置)
// var d = new Date();
// // 设置
// d.setFullYear(2021);
// d.setMonth(11); // 月份从0开始
// d.setDate(12);
// console.log(d);
// var d = new Date(2020,11,12);
// var d = new Date(2020,11,12,10,0,0);
// var d = new Date('2020,12,12,10:00:00'); // 时间字符串(正常的时间)
var d = new Date(1607702400000); // 时间戳
console.log(d);
时间格式
var d = new Date();
console.log(d); // Tue Dec 08 2020 16:22:55 GMT+0800 (中国标准时间)
console.log(d.toDateString()); // Tue Dec 08 2020
console.log(d.toLocaleDateString()); // 2020/12/8
console.log(d.toTimeString()); // 16:23:52 GMT+0800 (中国标准时间)
console.log(d.toLocaleTimeString()); // 下午4:24:06
16.数组方法
<script>
var arr = [];
arr.push();//在数组的末尾添加元素
item = arr.pop();//删除数组最后一个元素,并返回被删除的元素
arr.unshift();//添加到数组的最前面
item = arr.shift();//删除数组的第一个元素,并返回被删除的元素
arr.splice(开始的位置下标,删除的个数,替换的多个元素);//删除、添加、替换
arr.sort();//按照字符串形式升序排序
arr.join("分隔符");//将数组拼接成字符串
newArr = arr.concat(数组1,数组2,...);//拼接数组成新的数组
arr.reverse();//翻转数组的项
arr.indexOf(查找的内容,查找的起始位置);//从前往后查找,找不到返回-1
arr.lastIndexOf(查找的内容,查找的起始位置);//从后往前查找,找不到返回-1
arr.slice(起始下标,结束下标);//截取数组并返回
迭代方法:
(有返回值的需要自己写return)
//every:针对数组元素做出判断并返回,如果结果都是true,就返回true
//some:针对数组元素做出判断,只要有一个结果不是true,返回的结果就是false
//filter:针对数组进行判断,满足条件的元素,会组成一个新的数组,并返回这个新的数组
//map:迭代数组中的每一项,进行自定义操作,返回一个数组
//forEach:沒有返回值,就是一个简单的循环
// item : 数组中的每一项
// index :数组的下标
// array :数组本身
let ev = arr.every((item,index,array)=>{
return item == "1";
});
let s = arr.some((item,index)=>{
return item <= 0 ;
});
let arr1 = arr.filter((item,index)=>{
return item > 9;
});
let arr1 = arr.map((item,index)=>{
let num = 9;
return item * num;
});
let arr1 = arr.forEach((item,index)=>{
console.log(item);
});
</script>
17.列举出在vue中组件的定义方式有哪几种?
方式一:全局定义
<!-- 作用域 -->
<div id="box">
<v-hesder></v-hesder>
</div>
<!-- 模板 -->
<template id="header">
<div class="red">
<p>header</p>
<p>{{title}}</p>
</div>
</template>
<script>
// 全局注册组件
Vue.component("vMain", { // 两个参数:组件名(自定义),一个对象(存放属性)
template: "#main", //挂载点
data() { //数据 写成函数 并return数据
return {
title: "主体部分"
}
},
});
</script>
方式二:局部定义
<!-- 作用域 -->
<div id="box">
<v-main></v-main>
</div>
<template id="main">
<div class="blue">
<p>main</p>
<p>{{title}}</p>
</div>
</template>
<script>
new Vue({
el: "#box",
// 局部注册组件
components: {
vHesder: { //组件名: vHesder
template: "#header", //挂载点
data() { //数据 写为函数形式 并return
return {
title: "头部"
}
},
},
}
});
</script>
18.组件中的data为什么必须是函数?
答案:组件是可复用的vue实例,一个组件被创建好之后,就可能被用在各个地方,而组件不管被复用了多少次,
组件中的data数据都应该是相互隔离,互不影响的,基于这一理念,组件每复用一次,data数据就应该被复制一次,之后,当某一处复用的地方组件内data数据被改变时,其他复用地方组件的data数据不受影响。
组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,
类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。
而单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。
19.vue-cli中怎样定义和使用组件?
(1)定义:
子组件:
在src/assets/components下新建vue文档,在文档中进行代码书写,各个组件的引用:
import 组件名 from “相对路径” 进行建立关系
根组件:
根组件是App.vue文档
(2)使用
注册:局部注册:在vue文档中script标签中使用components属性进行注册;全局注册在main.js中进行注册
引入:全局组件在main.js中引入,局部组件在要引入的vue文档中引入;
20.请说出vue-cli项目中src目录每个文件夹和文件的用法?
-build #webpack的项目配置文件
-config #项目的配置文件
-node_modules # 项目的依赖包
-src #你的项目代码
-assets: #静态资源文件(img js css )
1.assets中的静态资源文件在main.js入口文件中引入
2.assets中的静态资源文件参与压缩打包
-components:#局部组件
-common #公共组件(自己添加的)
-utils #工具类(自己添加的)
-store #状态管理(自己添加的)
-page #我自己的代码(自己添加的)
App.vue #根组件
main.js #唯一的入口文件
-static #静态资源文件(img js css )
1.static中的静态资源文件在index.html中引入
2.static中的静态资源文件不参与压缩打包
.babelrc #es6转es5的配置文件
.editorconfig #编辑器的配置项
.gitignore #上传到git上需要忽略的文件
.postcssrc.js #css的配置项
index.html #唯一的页面
package.json #项目的相关信息及依赖包的相关版本
README.md #项目启动信息
21.vue中的 ref是什么?如何使用ref?
ref是用来获取元素或者子组件的句柄。
引用信息将会注册在父组件的 r e f s 上 , 所 以 使 用 时 配 合 refs上,所以使用时配合 refs上,所以使用时配合refs一起使用
使用在普通元素的时候:用于获取该元素
使用:在标签中当做自定义属性使用
在
<template>
<!--在普通元素上有一个ref属性,ref属性的值是自定义的 -->
<div ref="自定义名myDiv"></div>
</template>
//这时this.$refs.myDiv就是这个元素
使用在子组件时:获取组件句柄
父组件中:
<template>
<!-- 在子组件上有一个ref属性,ref属性值是自定义 -->
<button @click="change1">one</button>
//这是子组件
<v-one ref="myOne"></v-one>
</template>
//this.$refs.myOne就是这个子组件的组件句柄,可以通过
//this.$refs.myOne.方法名或属性名
//调用子组件的方法或属性,
22.vue中如何使用jquery?
在安装好jQuery的前提下,先引入,后使用
(1)全局引入与使用
在main.js文档中进行引入
// 引入jquery
import $ from 'jquery'
Vue.prototype.$ = $;
//在组件中使用
this.$("选择器").事件(执行事件的函数);
(2)局部引入与使用
// 在哪里使用就在哪里引入
import $ from 'jquery'
$("选择器").事件(执行事件的函数);//正常使用
23.说说你对 slot 的理解有多少?slot 使用场景有哪些?
slot是槽接口的意思,
匿名槽口:
在子组件中留有插槽
<template>
<div>
<!-- 匿名插槽 -->
<p>今夕何夕</p>
<slot></slot>
</div>
</template>
父组件:
<v-two>
<div>要插入的元素</div>
</v-two>
具名槽口
在子组件中设置槽口的名字
<template>
<div>
<!-- 具名插槽 -->
<slot name="man"></slot>
<p>今天星期五</p>
<slot name="women"></slot>
</div>
</template>
父组件中使用具名插槽
<v-two>
<ul slot="man">
<li>刘劲</li>
<li>杨一</li>
<li>刘泽松</li>
<li>王达生</li>
</ul>
<ol slot="women">
<li>杨延琴</li>
<li>陶甜也</li>
<li>田文渊</li>
<li>苟燕</li>
</ol>
</v-two>
24.vue的is这个属性你有用过吗?主要用在哪些方面?
作用:is
用来解决标签固定搭配问题
<template>
<div>
<ul>
<li :is="comName"></li>
</ul>
</div>
</template>
comName为组件
25.props数据和data数据的区别
props数据来自外部
如果props数据类型是基本数据类型(String,Number,Boolean),那么不能重写
如果props数据类型是引用数据类型(Array,Object),那么可以重写
data数据是组件内部的数据
data数据可读可写
注意:props和data数据名不能相同.
26.React有哪些优缺点?
优点:
(1)react是基于组件进行开发。因为一切都是component,所以代码更加模块化,重用代码更容易,可维护性高。
(2)能够很好的和现有的代码结合。React只是MVC中的View层,对于其他的部分并没有硬性要求。意味着很多公司在选择用Angular全部重构和用React部分重构的时候,选择了React部分重构
(3)同构、纯粹的javascript:因为搜索引擎的爬虫程序依赖的是服务端响应而不是JavaScript的执行,预渲染你的应用有助于搜索引擎优化。
(4)JSX语言:允许js和html的混写。
(5)虚拟dom节点:DOM diff算法 ,它可以极大提高网页的性能表现
(6)跨浏览器兼容:虚拟DOM帮助我们解决了跨浏览器问题,它为我们提供了标准化的API,甚至在IE8中都是没问题的。
缺点:
(1)react中没有数据双向绑定。需要手动数据双向绑定,容易出现bug。
(2)组件没有独立的css样式。react关于css样式问题没有同意的解决 方式,有几十种不同的解决方案,上百个不同的库;相比Vue通过在.vue文件中编写<style> <style>
标签来编写自己的样式;
(3)react没有规范系统的文件与模块。react中没有基本指令,计算属性,过滤器,监听器等等;
27.React解决了什么问题?
答案:
组件化:这是react的核心
模块化:基于webpack,可以使用ES6或者commonJS的写法实现模块化
开发效率:react代码基本就是组件的组合,只用关心一个render函数,不用关心视图局部的修改
运行效率:react实现了虚拟dom,相比于其他框架具有更优的效率
可维护性:react基于flux或者redux的架构设计,确定定的store很容易定位问题
28.React、vue、angular有什么区别?
开发者 | 数据绑定 | 依赖标准 | 渲染页面 | 模式 | |
---|---|---|---|---|---|
vue | 尤雨溪 | 双向数据绑定 | ES5/es6 | 模板+脚本+样式 | MVVM |
react | 单向数据绑定 | es6 | JSX | 不是MVVM ,只是v | |
angular | 谷歌 | 双向数据绑定 | typescript | 模板 | MVC(1)/MVVM(2…) |
29.react diff 原理?
答案:当你使用react的时候,在某个时间点render函数创建了一颗react元素树,在下一个state或者props更新的时候,
react函数将创建一颗新的react树,react将对比两棵树的不同之处,计算出如何高效的更新UI(值更新变化的地方)
30.JSX是什么?浏览器怎么解析JSX?
答案:JSX 将 HTML 语法直接加入到 JavaScript 代码中,再通过翻译器转换到纯 JavaScript 后由浏览器执行。
浏览器中通过给script标签添加type="text/bable"属性来解析jsx
31.react组件如何定义?
- 函数式定义的
无状态组件
- es5原生方式
React.createClass
定义的组件 - es6形式的
extends React.Component
定义的组件
32.函数定义和类定义的区别?
首先函数声明可以理解为一个特殊的普通函数,其本质与ES5中创建的构造函数差不多,但是该函数里面并没有定义或者继承react的一些其他特性。而class声明的组件可以理解为ES6的声明类,声明方式为:class Welcome extends React.Component,可以看到其中的extends继承了React的Component,所以通过class声明的组件继承了react的特性,比如生命周期。
所以简单来说函数定义的组件本质上就是返回了一个react的dom,而类定义则是继承了react的组件特性的。
33.state如何设置初始值并进行改变?
在React的组件中可以在两个位置来初始化state
:(1)在组件的constructor
中;(2)直接在class
中利用属性赋值的方式
(1)在组件的constructor
中;
在construcot
中可以来初始化所有值,包括state
,需要提醒自己调用super(props)
。class实例在内存中已经被创建,所以可以使用this
来为state
赋值;
要注意的是,在constructor
中可以不使用this.setState
来为state
直接赋值,除此之外其他位置都不能这样做,只有通过setState
才能通知React,我们修改了数据,React需要重新渲染组件。
(2)直接在class
中利用属性赋值的方式
class App extends React.Component {
state = {
loggedIn: false,
currentState: "not-panic",
someDefaultThing: this.props.whatever
}
没有定义constructor
state属性是直接引用的,并不是通过this.state来引用的
state的作用域是在Class内部,并不是一个方法的内部
仍然可以使用this.props和this.context
state是class的实例属性,并不是静态属性,不需要添加static关键字(就像为static propTypes {...})
34.React中如何进行事件绑定?
(1)on+首字母大写的事件名={自定义的事件函数名};
注意:自定义事件函数名调用时,后面不能加(), 如果写了就会自动被触发
<button className="btn btn-success" onClick={this.hander}>点击</button>
(2)on+首字母大写的事件名={function(){ 自定义的事件函数体 }}
注意: (a)将调用的自定义事件函数放入一个方法体中.
(b)同时需要通过bind函数改变this指向
<button className="btn btn-info" onClick={function(){this.hander1('刘劲')}.bind(this)}>传参按钮</button>
(3)on+首字母大写的事件名={()=> { 自定义的事件函数体 }}
<button className="btn btn-primary" onClick={()=>this.hander1('陶甜也')}>传参按钮1</button>
35.使用箭头函数(arrow functions)的优点是什么?
- 使用箭头函数比普通函数少些动词,如:
function
或return
- 重要的是
this
提前定义,从上下文可以捕获this
。 - 在react中使用箭头函数时,不用再改变this的指向。
36.(组件的)状态(state)和属性(props)之间有何不同?
答案:state是一种数据结构,用于组件挂载时定义数据的默认值。修改state使用setState,会触发render函数执行,渲染页面。
props是由父组件传递给子组件的。对于子组件而言,props是不可变的。
37.类组件和函数式组件之间有何不同?
答案:函数组件无state和生命周期,传值需要用props
类组件有state和生命周期,传值需要this.props
38.(在构造函数中)调用 super(props) 的目的是什么?
在组件的constructor
中,使用super(props)来调用父类的constructor。默认的constructor(当创建一个class时,如果我们没有显式的声明constructor,JS会默认提供一个)会自动调用super,将将所有的参数传入。
39.react 生命周期函数有哪些?
周期函数 | 何时调用 | 特点 | 调用 |
---|---|---|---|
componentWillMount() | 组件将要挂载 | 可以操作数据;不能操作dom; | 调用1次 |
render() | jsx模板渲染(将jsx模板渲染给虚拟DOM) | 可以操作数据;不能操作dom | 调用1次 |
componentDidMount() | 组件挂载完成 | 可以操作数据;可以操作dom节点(做其他操作: 开发轮播图 发起ajax请求 延时器 计时器) | 调用1次 |
ShouldComponentUpdate(object nextProps, object nextState) | 应该更新组件吗 | 必须有返回值 如果返回true: 表示更新组件 如果返回false:表示不更新 在实际开发中false用的比较多. 1.有时不希望客户端看到最新更新的数据. 2.性能调优 参数一: nextProp: 没有获取到最新的props数据 参数二: nextState: 获取到最新的state数据 | 调用>=0次 |
componentWillUpdate(object nextProps, object nextState) | 组件将要更新 | 获取state数据是更新之前的数据 获取dom节点文本内容是更新之前的数据 参数一: nextProp: 没有获取到最新的props数据 参数二: nextState: 获取到最新的state数据 | 调用>=0次 |
render() | 渲染jsx模板 | 获取state数据是更新之后的数据 获取dom节点文本内容是更新之后的数据 | 调用>=1次 |
componentWillReceiveProps(object nextProps, object nextState) | 组件将要接收props数据 | 参数一: nextProp: 获取到最新的props数据 参数二: nextState: 没有获取到最新的state数据 | 调用>=0次 |
componentDidUpdate(object prevProps, object prevState) | 组件更新完成 | 获取state数据是更新之后的数据 获取dom节点文本内容是更新之后的数据 参数一: preProp: 没有获取到更新之前的props数据 参数二: preState: 获取到更新之前的state数据 | 调用>=0次 |
componentWillUnmount() | 组件将要销毁 | 调用1次 |
40.shouldComponentUpdate 是做什么的?
答案:
第一个 不存在 数据正常更新 。
第二个 存在 数据被拦截
按照你自己的需求去返回true 或者false,这个函数存在必须要返回相关的布尔值, 否则报错 。
①如果是true的时候
生命周期的顺序是
shouldComponentUpdate是否要更新-》componentWillUpdate将要更新=》
render渲染-》componentDidUpdate更新
②如果是false 就结束了
只走了shouldComponentUpdate-----是否要更新
41.应该在 React 组件的何处发起 Ajax 请求?
在 React 组件中,应该在 componentDidMount 中发起网络请求。这个方法会在组件第一次“挂载”(被添加到 DOM)时执行,在组件的生命周期中仅会执行一次。在 componentDidMount 中发起网络请求将保证这有一个组件可以更新了。
42.在React中,refs的作用是什么?
Refs 是 React 提供给我们的安全访问 DOM 元素或者某个组件实例的句柄。
我们可以为元素添加 ref 属性然后在回调函数中接受该元素在 DOM 树中的句柄,
该值会作为回调函数的第一个参数返回。
用于对 render() 返回的特定元素或组件的引用。
当需要进行 DOM 测量或向组件添加方法时,它们会派上用场。
43.react router和常规路由有何不同?
答案:
参与的页面:
reactRouter:只涉及单个HTML页面;
常规路由:每个视图对应一个新文件。
URL更改:
reactRouter:仅更改历史记录属性
常规路由:http请求被发送到服务器并且接收相应的html页面
体验:
reactRouter:用户认为自己正在不同的页面间切换
常规路由:用户实际在每个视图的不同页面切换
44.当你调用setState的时候,发生了什么事?
答案:
当调用 setState 时,React会做的第一件事情是将传递给 setState 的对象合并到组件的当前状态。这将启动一个称为和解的过程。和解的最终目标是以最有效的方式,根据这个新的状态来更新UI。 为此,React将构建一个新的 React 元素树(您可以将其视为 UI 的对象表示)。
一旦有了这个树,为了弄清 UI 如何响应新的状态而改变,React 会将这个新树与上一个元素树相比较( diff )。
通过这样做, React 将会知道发生的确切变化,并且通过了解发生什么变化,只需在绝对必要的情况下进行更新即可最小化 UI 的占用空间。
45。在 React 当中 Element 和 Component 有何区别?
答案:
一个 React element 描述了你想在屏幕上看到什么。换个说法就是,一个 React element 是一些 UI 的对象表示
一个 React Component 是一个函数或一个类,它可以接受输入并返回一个 React element
46.React中路由有哪些常用组件?说明它们的作用?
答案:
BrowserRouter,在需要使用路由的页面中引入;
Switch,路由选择器
Route,路由配置规则
Redirect,路由重定向
Link,路由导航
NavLink,带activeClass的路由导航
WithRouter 使用路由规则
47.为什么虚拟 dom 会提高性能?
答案:虚拟DOM其实就是一个JavaScript对象。通过这个JavaScript对象来描述真实DOM。
为什么用虚拟dom?真实DOM的操作,一般都会对某块元素的整体重新渲染。采用虚拟DOM的话,当数据变化的时候,只需要局部刷新变化的位置就好了。
48.在 React 中,refs 的作用是什么?
答案:Refs 是 React 提供给我们的安全访问 DOM 元素或者某个组件实例的句柄。我们可以为元素添加 ref 属性然后在回调函数中接受该元素在 DOM 树中的句柄,该值会作为回调函数的第一个参数返回。 用于对 render() 返回的特定元素或组件的引用。当需要进行 DOM 测量或向组件添加方法时,它们会派上用场。
49.(组件的)状态(state)和属性(props)之间有何不同?
答案:state是一种数据结构,用于组件挂载时定义数据的默认值。修改state使用setState,会触发render函数执行,渲染页面。
props是由父组件传递给子组件的。对于子组件而言,props是不可变的。
50.(在构造函数中)调用 super(props) 的目的是什么?
答案:在super被调用之前,子类是不能使用this的,在ES5中,子类必须在constructor中调用super().
传递props给super()的原因则是便于子类能在constructor中访问this.props