1.分别说说vue和react有什么优点?
1.vue的优点为:简单易学、双向数据绑定、轻量级、组件化、虚拟DOM、运行速度更快等。 2.react的优点:速度快、跨浏览器兼容、一切都是component、单向数据流、兼容性好等。 3.React和Vue的区别:1、React是一个适合数据经常变化以及构建大型项目的复杂组件;2、Vue是一个更小更灵活适合用来开发单页面程序的简单化组件;3、React Native是一个成熟且广泛使用的本机渲染应用程序平台等等。
2.flex的布局特点
1、块级布局侧重垂直方向、行内布局侧重水平方向,flex布局是与方向无关的。 2、flex布局可以实现空间自动分配,自动对齐(flexible:弹性、灵活) 3、flex适用于简单的线性布局,更复杂的布局要交给grid布局
3.在redux里为什么要返回一个全新的state出来?
原因是处于性能考虑,如果改变了某个属性,redux还需要去一个个对比是哪个属性发生了变化,而对于一个大型的数据结构来说,做深度检查是及其好性能的,所以redux选择了返回一个新的对象的方式。(创建一个对象的方式比做深度的对比性能要开销的小的多)。
4.原型与原型链
原型: ①所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象 ②所有函数都有一个prototype(原型)属性,属性值是一个普通的对象 ③所有引用类型的__proto__属性指向它构造函数的prototype 原型链: 当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。
5.谈谈什么是ajax
1.ajax是指一种建立交互式网页应用的开发技术,改善用户体验,实现无刷效果 2.优势:不须要插件的支持,优秀的用户体验,提升web程序性能,减轻服务器和带宽的负担ajax 3.缺点:破环浏览器的“前进”,“后退”按钮的正常功能,是能够经过简单的插件弥补json 4.原生ajax有四个步骤:创建XMLHttpRequest对象(xhr)、设置请求方式(xhr.open('get',url,true))、发送请求(xhr.send())、获取响应数据(xhr.onreadystatechange=function(){if(xhr.readyState===4&&xhr.status===200){console.log(JSON.parse(xhr.responseText).result.data)}}) 5.解决跨域的三种方法:代理、jsonp、后端设置cors允许跨域
6.谈谈jquery
1.首先jQuery提供了强大的元素选择器 2.jQuery出色的DOM操作的封装,极大的简化了javascript的对dom节点的增删改查操作,让我们可以使用一种更加简洁的方法来操作节点 3.第四点就是jQuery还是一个为事件处理特点设计的框架,提供了静态绑定事件和动态绑定事件,完善了事件的处理机制。 4.第四点就是jQuery还是一个为事件处理特点设计的框架,提供了静态绑定事件和动态绑定事件,完善了事件的处理机制。 5.jQuery极大的简化ajax编程,提供了一种更加简洁,统一的编程方式。 6.jQuery内置了一些简单有用的内置动画,像常见的slideDown/slideUp,hide/show,fadeIn/fadeOut等,还支持基于定位机制使用animate来自定义动画效果
7.什么是axios
1.Axios其实就是一个用于发送ajax请求的HTTP库,本质上是对AJAX的封装。而且Axios支持 Promise操作, 让我们无需再使用传统callback方式来进行异步编程。(Promise 是JS中进行异步编程的一种解决方案。)
8.vuex
1.Vuex 是Vue的一种状态管理模式,专门为Vue设计的,集中式组件管理状态,我们通常不会这么做,通常使用的是子父传值,父子传值,兄弟传值,父直接用子,子直接用父,当组件之间的传值满足不了需求,来自不同视图需要变更同一个状态,会使用状态管理器,通俗的来讲就是你觉得你现有的功能满足不了项目需求,需要使用那么就使用,如果不需要使用那么就不使用,使用它并没有绝对的条件。 2.state=>相当于vue里面的data,getters=>相当于vue里面的计算属性,modlues=>将store分割成模块 mutations=>定义修改state里面的数据的方法,actions=>类似于vue中的method,掉接口(异步的)
9.call与aplay的区别
call()和apply()的区别就是接收参数的方式不同。 apply接收两个参数,一个是this,另一个是参数数组,即将其他所有参数放在一个数组里。 call()接收的参数第一个是this,其他参数必须用逗号隔开。
10.vue计算属性和watch的区别有哪些?
1、计算属性在调用时需要在模板中渲染,修改计算所依赖元数据;watch在调用时只需修改元数据。 2、计算属性默认深度依赖,watch默认浅度观测。 3、计算属性适合做筛选,不可异步;watch适合做执行异步或开销较大的操作
11.浏览器缓存有哪几种?
熟悉的有: cookie:一般通过http请求中在头部一起发送到服务器端, localstorage:html5的一种新的本地缓存方案,目前用的比较多,一般用来存储ajax返回的数 据,加快下次页面打开时的渲染速度 sessionStorage:浏览器关闭则会全部删除,api和localstorage相同,实际项目中使用较 少。 了解的有:http缓存、websql、indexDB、application cache、cacheStorage、flash缓存
12.数组去重的方法
1.用sort方法: function qc(arr){ var arr = arr.sort(); var arrs = [arr[0]]; for(var i=1;i<arr.length;i++){ if(arr[i]!==arr[i-1]){ arrs.push(arr[i]) } } return arrs; } 2.用sort和splice方法 function qc(arr){ var arr = arr.sort(); var arrs = []; for(var i=0;i<arr.length;i++){ if(arr[i]==arr[i+1]){ arr.splice(i,1); i--; arrs = arr; } } return arrs; } 3.用indexOf方法 function qc(arr){ var arrs = []; for(var i=0;i<arr.length;i++){ if(arrs.indexOf(arr[i])===-1){ arrs.push(arr[i]); } } return arrs; } 4.用includes方法(返回的是布尔值) function qc(arr){ var arr=arr.sort(); var arrs=[]; for(var i=0;i<arr.length;i++){ if(!arrs.includes(arr[i])){ arrs.push(arr[i]) } } return arrs; } 5.ES6 Set(Array.from(new Set(arr))=>数组与集合之间的转换) function qc(arr){ return Array.from(new Set(arr)) }
-
for in 与 for of 的区别:
1.推荐在循环对象属性的时候使用 for...in,在遍历数组的时候的时候使用 for...of 2.for...in 循环出的是 key,for...of 循环出的是 value 3.注意,for...of 是 ES6 新引入的特性。修复了 ES5 引入的 for...in 的不足 4.for...of 不能循环普通的对象(如通过构造函数创造的),需要通过和 Object.keys()搭配使用
-
手动释放变量,怎么改动,如何操作?(详细说明步骤,例如如何删除)
1.delete 不能删除var 关键字声明的全局变量 例如:var 声明的 全局变量“a” 在使用 “delete a” 后 输出值依然为 “1” var a = 1; delete a; console.log(a) // 1 2.delete 能删除未使用var 关键字声明的全局变量 //例如:未使用var 声明的全局变量“b” 成为了 “window”的属性,在使用 “delete b” 后 输出 报错 “b is not defined” b = 1; delete b; console.log(b) // VM82:1 Uncaught ReferenceError: b is not defined at <anonymous>:1:13 3.delete 能删除对象中的可读写属性 // 在对象或者 构造器中的 变量,在使用 “delete” 后输出 “undefined” var fun= function (argument) { this.c = 3; } var d = new fun(); delete d.c; console.log(d.c); // undefined // 对象object中的属性,在使用 “delete” 后输出 “undefined” var e = {"f" : 4}; console.log(e.f); // undefined
15.跨域是什么?以及解决方案
1.当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域 解决跨域问题:1.jsonp:网页通过添加一个<script>元素,向服务器请求 JSON 数据,服务器收到请求 后,将数据放在一个指定名字的回调函数的参数位置传回来。 2.cors:a.普通跨域请求:只需服务器端设置Access-Control-Allow-Origin b.带cookie跨域请求:前后端都需要进行设置 3.通过nginx代理配置可以解决跨域
16.vue中如何对对象和数组进行监听(深度监听)
watch: { obj: { handler(newName, oldName) { console.log(‘obj.a changed’); }, immediate: true, deep: true } }
17.字符串与数组的相互转换
1.字符串转数组 let text = 'afddgfga'; 方法一:let arr1 = text.split(''); 方法二:let arr2 = [...text]; 方法三:let arr3 = Array.from(text) 2.数组转字符串 let arr = ['a','e','y','w']; 方法一:let string1 = arr.join(''); 方法二:let string2 = arr.toString(); 方法三:let string3 = arr.toLocaleString()
18.useEffect和useLayoutEffect的区别
1.不同点就是useEffect是异步执行,而useLayoutEffect是同步执行的。 2.useEffect异步执行的优点是:react渲染组件不必等待useEffect函数执行完毕,造成阻塞。 3.当函数组件刷新(渲染)时,包含useEffect的组件整个运行过程如下: 1.触发组件重新渲染(通过改变组件state或者组件的父组件重新渲染,导致子节点渲染)。 2.组件函数执行。 3.组件渲染后呈现到屏幕上。 4.useEffect hook执行。 4.当函数组件刷新(渲染)时,包含useLayoutEffect的组件整个运行过程如下: 1.触发组件重新渲染(通过改变组件state或者组件的父组件重新渲染,导致子组件渲染)。 2.组件函数执行。 3.useLayoutEffect hook执行, React等待useLayoutEffect的函数执行完毕。 4.组件渲染后呈现到屏幕上。
19.redux
1.三大基本原则: 1.单一数据源 2.state是只读的 3.使用纯函数来执行修改 2.优点 1.Redux轻量,生态丰富,可以结合流行的redux-thunk、redux-saga等进行使用 2.Redux的写法比较固定,团队应用中风格比较稳定,提高协作中的可维护性 3.因为Redux中的reducer更新时,每次return的都是不可变对象,所以时间旅行操作相对容易 3.缺点 1.每一次的dispatch都会从根reducer到子reducer嵌套递归的执行,所以效率相对较低; 2.Redux核心是不可变对象,在Reducer中的操作都要比较小心,注意不能修改到state的属性 3.Redux中写法固定,模板代码较多
20.cookie、localStorage和sessionStorage三者的区别
一、存储的时间有效期不同 1、cookie的有效期是可以设置的,默认的情况下是关闭浏览器后失效 2、sessionStorage的有效期是仅保持在当前页面,关闭当前会话页或者浏览器后就会失效 3、localStorage的有效期是在不进行手动删除的情况下是一直有效的 二、存储的大小不同 1、cookie的存储是4kb左右,存储量较小,一般页面最多存储20条左右信息 2、localStorage和sessionStorage的存储容量是5Mb(官方介绍,可能和浏览器有部分差异性) 三、与服务端的通信 1、cookie会参与到与服务端的通信中,一般会携带在http请求的头部中,例如一些关键密匙验证等。 2、localStorage和sessionStorage是单纯的前端存储,不参与与服务端的通信 五、对于浏览器的支持 1、cookie出现的时间较早,目前见到的浏览器都支持 2、localStorage和sessionStorage出现的时间较晚,对于版本较低的浏览器不支持(比如IE8版本以下的都不支持)
21.promise
1.Promise是异步编程的一中解决方案,最早是由社区提出的,es6中正式的将其纳入,他是一个对象,可以获取到异步的操作,他相比传统的回调函数,更加的强大和合理,避免了回调地狱 2.Promise的优点: - 对象的状态不受外界的影响,只有异步的操作结果才能改变他的状态。 - 一旦状态改变就不会在变,任何时候都可以得到这个结果,就如他的名字一样promise(承诺)。 3.Promise的缺点: - 无法去取消promise,只要创建就会执行,无法中途去终止。 - 如果不设置回调函数去接受,promise内部会报错,不会映射到外部 - 处在pending(进行中)时 ,外部无法得知进展到那一步 4.当要处理某个任务的时候,promise的状态是pending,任务完成是状态就变成了resolved,任务失败状态就变成了rejected。
22.什么是深拷贝和浅拷贝
1.浅拷贝:创建一个新的对象,这个对象有着原始对象属性值的一份精确拷贝,如果属性是基本类型,就拷贝基本类型的值,如果属性是引用对象,那拷贝的就是内存地址,如果其中一个改变了,那么另外一个也会收到影响 2.深拷贝:深拷贝会拷贝所以属性,并拷贝属性所指向的动态分配的内存,当对象和它引用的对象一起拷贝是即深拷贝,深拷贝相较于浅拷贝花销较大且速度慢,拷贝前后两个对象互不影响
23.webpack的运行机制
Webpack 启动后,会根据我们的配置,找到项目中的某个指定文件(一般这个文件都会是一个 JS 文件)作为入口。然后顺着入口文件中的代码,根据代码中出现的 import(ES Modules)或者是 require(CommonJS)之类的语句,解析推断出来这个文件所依赖的资源模块,然后再分别去解析每个资源模块的依赖,周而复始,最后形成整个项目中所有用到的文件之间的依赖关系树有了这个依赖关系树过后, Webpack 会遍历(递归)这个依赖树,找到每个节点对应的资源文件,然后根据配置选项中的 Loader 配置,交给对应的 Loader 去加载这个模块,最后将加载的结果放入 bundle.js(打包结果)中,从而实现整个项目的打包
-
那讲一下你如何使用webpack搭建一个react环境
1.建一个新文件夹(项目配置文件夹---webpack-app) 2.初始化:npm init -y (产生package.json package-lock.json(锁定版本号) 文件) 3.安装webpack@5:`npm install webpack webpack-cli --save-dev` 4.webpack配置文件=>项目根目录=>创建配置文件 webpack.config.js里面使用comonjs的语法规范 5.package.json 配置开启命令: "script":{"start":"webpack --config webpack.config.js"}` //代替 `npx webpack` 命令 //使用:`npm start` webpack有五个模块 : 入口(entry) -----设置入口文件路径 输出(output) -----设置打包后的文件存放路径以及文件名 loader加载器(module) -----一般用于css文件的打包 插件(plugin) -----可以设置一个html模板插件 模式(mode) -----设置打包模式(一般在开发阶段使用webpack,一般不在产品阶段打包) 另外还有 source-map -----文件映射,文件出错时提示源文件位置 webpack-dev-server -----webpack开发服务器
-
什么是 Node.js?我们在哪里使用它?
1.是什么:Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。是一个让 JavaScript 运行在服务器端的开发平台,它让 JavaScript 的触角伸到了服务器端。但与 PHP、JSP、.net 等相比,Node.js 跳过了 Apache、Naginx、Tomcat、IIS 等 HTTP 服务器,它不需要建设在任何服务器软件之上。 2.在哪里使用:Web 全栈开发、聊天室、Web 爬虫等 (?,不确定) 3.特点:单线程、事件驱动、非阻塞 I/O 4.优点(为什么要用nodejs):执行快速、永远不会阻滞、异步处理机制、避免并行所带来的问题
-
react-redux的用法
//user.js /*方法一*/ /*方法二*/ const UserSlice = createSlice({ name:'user', initialState:{}, reducers:{ addCount(state,action) state.count = state.count+action.payload; } } }) export const {login} UserSlice.actions; export UserSlice.reducer; //store.js /*方法一*/ // 导入redux里面的创建仓库的方法 import {createStore} from 'redux'; // 定义state的初始值 const initState = { num:10, age:200 } // 书写一个关联state和actions的函数 // 这个函数就做reducer const store = createStore((state=initState,actions)=>{ switch(actions.type){ case 'addNum': // 生成一个新的state return {...state,num:state.num+actions.payload}; case 'cutNum': // 生成一个新的state return {...state,num:state.num-1}; case 'addAge': // 生成一个新的state return {...state,age:state.age+10}; case 'cutAge': // 生成一个新的state return {...state,age:state.age-10} default: // 生成一个新的state return {...state} } }) /*方法二*/ export default configureStore({ reducer:{ user:UserReducer, msg:MsgReducer } }) //index.js <BrowserRouter>//路由 <Provider store={store}> <Routes> {/* 不是按照书写顺序匹配,是按照最佳路径匹配路由 */} <Route path='/' element={<Panel/>}> {/* index 自动匹配这个子路由组件 */} <Route index element={<Userlist/>}></Route> <Route path='my' element={<My/>}></Route> <Route path='msglist' element={<Msglist/>}></Route> </Route> }></Route> </Routes> </Provider> </BrowserRouter> //my.jsx /*方法一*/ import {dispatch,useState,getState,subScript} from 'react' const [age,setAge] = useState(store.getState().age) setNum(store.getState().num) /*方法二*/ import {useSelector,useDispatch} from 'react-redux' const num = useSelector(state=>state.num) const age = useSelector(state=>state.age) const dispatch = useDispatch() dispatch(addNum())
27.http状态码
100-199 用于指定客户端应相应的某些动作。 200-299 用于表示请求成功。 200(成功)服务器已成功处理了请求。 300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息。 301,永久性重定向,表示资源已被分配了新的 URL 302,临时性重定向,表示资源临时被分配了新的 URL 303,表示资源存在另一个URL,用GET方法获取资源 304,(未修改)自从上次请求后,请求网页未修改过。服务器返回此响应时,不会返回网页内容 400-499 用于指出客户端的错误。 400(错误请求)服务器不理解请求的语法 401表示发送的请求需要有通过HTTP认证的认证信息 403(禁止)服务器拒绝请求 404(未找到)服务器找不到请求网页 500-599 用于支持服务器错误。 500,(服务器内部错误)服务器遇到错误,无法完成请求 503,表示服务器处于停机维护或超负载,无法处理请求
28.防抖和节流
1.节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效=>单位时间内,频繁触发同一个操作,只会触发 1 次。 2.防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时=>频繁触发某个操作时,只执行最后一次
29.react新增useReducer
1.是什么:useReducer 是用于提高应用性能的,当更新逻辑比较复杂时,我们应该考虑使用useReducer 2.useReducer 和 redux 的区别 useReducer 是 useState的代替方案,用于 state 复杂变化 useReducer 是单个组件状态管理,组件通讯还需要 props redux 是全局状态管理,多组件共享数据 3.语法: const [state, dispatch] = useReducer(reducer, initState); 第一个参数:reducer函数 4.用法: const initState = { name: '', pwd: '', isLoading: false, error: '', isLoggedIn: false, } function loginReducer(state, action) { switch(action.type) { case 'login': return { ...state, isLoading: true, error: '', } case 'success': return { ...state, isLoggedIn: true, isLoading: false, } case 'error': return { ...state, error: action.payload.error, name: '', pwd: '', isLoading: false, } default: return state; } } function LoginPage() { const [state, dispatch] = useReducer(loginReducer, initState); const { name, pwd, isLoading, error, isLoggedIn } = state; const login = (event) => { event.preventDefault(); dispatch({ type: 'login' }); login({ name, pwd }) .then(() => { dispatch({ type: 'success' }); }) .catch((error) => { dispatch({ type: 'error' payload: { error: error.message } }); }); } return ( // 返回页面JSX Element ) }
30.Axios 拦截分为请求拦截和响应拦截。
1.请求拦截就是(开启loading,并且给每个请求体上的header添加token) 在你请求的时候会进行触发!只要是你发送一个 axios 请求就会触发!所以我们主要用它做我们的loading加载和数据的权限验证,包括我们所有的数据预加载也可以实现。 2.响应拦截主要是(关闭loading,对响应数据进行一个处理并返回给前端) 我们在 loading加载,和做所有数据加载需要整体的结束,这个时候的结束就需要在数据马上发给前端的时候进行隐藏和结束,包括我们的请求头的设置,后端数据已经发送过来的时候,我们为了确保请求头的传递就必须在看看header里面是否有你需要的请求,如果有的话,再次进行设置!
31.ES6新增语法
1.const和let let: let声明的变量只在所处于的块级有效 在业务逻辑比较复杂时,能够防止内层变量覆盖外层变量 拥有块级作用域的变量还有一个好处 防止循环变量变成全局变量 不存在变量提升 只能先声明再使用 暂时性死区 在块级作用域内使用let关键字声明的变量会被整体绑定在这个块级区 域不再受外部代码影响 2.let、const、var的区别: 1.使用var声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象,函数级作 用域,值可更改 2.使用let声明的变量,其作用域为该语句所在的代码块内,不存在变量提升,块级作用 域,值可更改 3.使用const声明的是常量,在后面出现的代码中不能再修改该常量的值,块级作用域,值 不可更改 2.解构赋值 数组解构: let [a, d, c] = [1, 2, 3]; console.log(a); // 1 console.log(b); // 2 对象解构: let person = {name: 'zhangsan', age: 20}; //方法1 let {name, age} = person; console.log(name); // 'zhangsan' //方法二: let {name: myName, age: myAge} = person; // myName myAge属于别名 console.log(myName); // 'zhangsan' console.log(myAge); // 20 3.箭头函数 4. 剩余参数 ... 当函数实参个数大于形参个数时,我们可以将剩余的实参放到一个数组中 剩余参数语法允许我们将一个不定数量的参数表示为一个数组 function sum (first, ...args) { console.log(first); // 10 console.log(args); // [20, 30] } sum(10, 20, 30); // 剩余参数和解构配合使用 let students = ['wangwu', 'zhangsan', 'lisi']; let [s1, ...s2] = students; console.log(s1); // 'wangwu' console.log(s2); // ['zhangsan', 'lisi'] 5. 扩展运算符(展开语法) ...