2024面试题汇总
从浏览器输入到页面展现做了哪些操作
- 在用户输入到展示的几秒钟里面,浏览器做了很多的操作,里面的细节有很多
- 刚开始浏览器会对输入的url进行解析,提取出协议,主机名,路径等信息
- 这里面涉及到http和https的一些概念,
- 如果是https的话,为了安全,会去做一些处理
- 接下来浏览器会将主机名转换成对应的ip,这个过程被称之为dns解析
- 浏览器会首先检查本地的dns缓存,如果有匹配的ip直接进行访问,如果没有的话,会向dns服务器发送请求,来获取对应的IP地址
- 转换成ip之后,浏览器会通过ip地址和端口号来与服务器建立tcp链接,这个过程是通过tcp的三次握手完成的,以确保双方可以正常通信
- 第一次握手,客户端发送syn包到服务器,并且客户端进行syn_send状态,等待服务器确认
- 第二次握手,服务器接收到syn包时,会发送一个syn+ack包给客户端,服务器进入syn_recv状态
- 第三次握手,客户端接收到syn+ack包之后,向服务器发送确认ack的包,至此三次握手结束
- 建立tcp连接之后,客户端与服务器就开始传输数据了
- 首先浏览器会向服务器发送http请求,请求的内容包括方法,请求头部,和请求体等
- 如果是get请求,请求体在url上
- 请求头包括浏览器自带的请求头和自定义的请求头,自定义的请求头可以用于登陆等场景
- 浏览器自带的请求头包括浏览器的一些信息,浏览器可接收的压缩算法,浏览器可接收的数据格式,content-type,accept等等
- 服务器接收到浏览器发送的请求之后,会进行处理,包括读取数据库,处理一些业务逻辑,生成一些动态内容等
- 服务器处理完请求,会对处理结果封装成http响应,包括状态码,响应头部,响应体等
- 浏览器自带的响应头也包含content-type,除此之外还有返回数据的压缩算法格式等,服务器修改cookie时,通过set-cookie修改
- 浏览器接收到服务器的响应后,会对这个响应进行解析,如果响应体是html文档,则会下载其中引用的其他资源,例如js,css,静态文件等
- 响应结束之后,为了更彻底地释放双方的资源,引入了四次挥手
- 四次挥手的时间,看是否设置了keep alive属性
- 第一次挥手,客户端发送终止请求报文段
- 第二次挥手,服务器接收到请求并发送确认报文
- 第三次挥手,客户端收到确认并发送确认报文
- 第四次挥手,服务器接收到确认报文并终止连接
- 解析下载完资源之后,浏览器会将html解析器解析成dom树,然后使用css解析器将css文件解析成样式规则,接着,浏览器根据dom树和样式规则进行渲染,将页面内容显示在浏览器上
- 解析完html和css之后,浏览器开始执行js文件,处理一些业务逻辑,这里也涉及到一些请求响应
- html和css渲染是同步执行的,但中间如果遇到js的操作,不管是下载还是解析,都会阻塞整个html的渲染
- js内部又分为同步任务和异步任务,异步任务又分为宏任务和微任务,像promise就是微任务
- 最后浏览器根据渲染结果将页面呈现给用户
- 在请求和响应的过程中,中间还有一个很重要的步骤,就是浏览器的缓存
- 浏览器的缓存主要包括强制缓存和协商缓存,强制缓存的判断主要在客户端,协商缓存的判断主要在服务端
- 强制缓存主要使用cache-control,浏览器初次请求到服务器时,服务器不止返回资源,还会返回一个cache-control,客户端如果看到有这个标识,会将资源缓存下来,后面请求的时候会看这个标识是否过期,不过期的话就不进行请求
- 协商缓存主要使用last-modified和etag进行标识,服务端会对客户端请求的资源进行判断,如果请求的资源时一样的,就会返回304,否则就会返回200
- http缓存不一定只用一种方式,经常会一起使用,这时候就要了解两种缓存的执行流程
- 发送http请求,一般来说,首先是判断是否命中强制缓存,再判断是否命中协商缓存,如果有强制缓存,但缓存过期,就会进入协商缓存的过程,如果服务端判断缓存不可用,即没有last-modified和etag标识或者标识不一致,就不会命中协商缓存,手动刷新的时候,协商缓存还是有效的,只有强制刷新,才能使两个缓存都失效
vue的双向绑定
- vue的双向绑定,主要是讲数据和视图的双向绑定,当数据变化时,视图可以自动变化,同时用户在视图中进行操作,结果也会反映到数据中,vue的双向绑定原理是通过数据劫持和发布订阅模式进行实现的,在创建vue实例时,vue会对数据对象进行递归遍历,使用object.defineProperty方法对每个属性进行劫持,当数据变化时,会触发相应的getter和setter方法,通知订阅者更新视图,同时vue也会将数据和视图进行绑定,当视图中的表单元素发生变化时,会触发相应的事件,将新的数据同步到数据对象中,这样就完成了双向绑定
NextTick 是做什么的
- $nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM
- 当你修改了data的值然后马上获取这个dom元素的值,是不能获取到更新后的值,你需要使用$nextTick这个回调,让修改后的data值渲染更新到dom元素之后在获取,才能成功。
Vue 组件 data 为什么必须是函数
- 因为js本身的特性带来的,如果 data 是一个对象,那么由于对象本身属于引用类型,当我们修改其中的一个属性时,会影响到所有Vue实例的数据。如果将 data 作为一个函数返回一个对象,那么每一个实例的 data 属性都是独立的,不会相互影响了
对 keep-alive 的了解
- keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染
- 即就是把一些经常使用的页面缓存起来,避免重复做加载渲染
- keep-alive 运用了 LRU 算法,选择最近最久未使用的组件予以淘汰。
简述vue原理
- Vue的模式是m-v-vm模式,即(model-view-modelView),通过modelView作为中间层(即vm的实例),进行双向数据的绑定与变化。
- 通过建立虚拟dom树document.createDocumentFragment(),方法创建虚拟dom树。
- 一旦被监测的数据改变,会通过Object.defineProperty定义的数据拦截,截取到数据的变化。
- 截取到的数据变化,从而通过订阅——发布者模式,触发Watcher(观察者),从而改变虚拟dom的中的具体数据。
- 最后,通过更新虚拟dom的元素值,从而改变最后渲染dom树的值,完成双向绑定
你都做过哪些 Vue 的性能优化?
- 对象层级不要过深,否则性能就会差。
- 不需要响应式的数据不要放在 data 中(可以使用 Object.freeze() 冻结数据)
- v-if 和 v-show 区分使用场景
- computed 和 watch 区分场景使用
- v-for 遍历必须加 key,key最好是id值,且避免同时使用 v-if
- 大数据列表和表格性能优化 - 虚拟列表 / 虚拟表格
- 防止内部泄露,组件销毁后把全局变量和时间销毁
- 图片懒加载
- 路由懒加载
- 异步路由
- 第三方插件的按需加载
- 适当采用 keep-alive 缓存组件
- 防抖、节流的运用
- 服务端渲染 SSR or 预渲染
在原理层面上讲vue2和vue3有什么区别
- 对于vue而言,本质上我们可以将它们分成三大模块,响应性reactivity,运行时runtime,编译器compiler,
- 先说响应性,vue2通过Object.definedProperty()去实现响应性,但是这种方法的核心是用来监听指定对象的指定属性的get、set行为,在这种情况下,就会出现一些问题,比如说在vue2的data中声明了一个对象,那么给这个对象在后期某一个时刻去新增属性的时候,因为js本身的限制,我们没办法监听到这个对象新增的这个属性,这个时候,我们就没办法通过Object.definedProperty()去监听对应的新增属性的行为,所以新增的这个属性就不是响应式的了,vue2为了解决这个问题,提供了vue.$set的方法,这个方法本质上就是把这个属性和对象过了一遍Object.definedProperty(),这种方案从程序设计的理念上看,不是很合理,所以在vue3的时候,他提供了es6新出现的反射和代理的概念,反射指的就是reflect,代理指的就是proxy,他通过proxy来代理了一个复杂的数据类型,通过这样复杂数据类型的代理,我们得到了一个代理对象,就是proxy的实例,然后通过reflect来确定了this上的一个指向,那么此时,vue3中实现这样的一套流程的方法就是我们常见的raactive,对于proxy而言,他只能去监听复杂数据类型的响应式,而没办法监听简单数据类型的响应式,比如基本的string和int,所以vue3里面又提供了ref的方法,ref的方法本质上其实就是把内容分成了两部分,第一部分就是复杂数据类型,在vue内部会直接通过toRective的方法指向reactive,第二部分的简单数据类型,其实在内部会去处理一个refImpl,也就是ref imploment的一个接口,通过这个接口内部,他实现了两个方法,一个叫做get标记的value,一个叫做set标记的value,通过ref这样的形式,当我们去触发.value这个属性的时候,本质上就是在触发他的value方法,这是响应性上的
- 除此之外还涉及到运行时的runtime的行为,runtime其实大部分指的就是所谓的渲染器也就是render,在这个渲染器对象里面,包含了一个我们常见的渲染函数即render函数,这个render函数内部把宿主环境,也就是所谓的浏览器,或者说是uniapp,uniapp可以使用vue进行渲染的原因,本质上就是因为vue在runtime阶段去进行了一个宿主环境和渲染逻辑的分离
- 第三个就是所谓的编辑器,编辑器我们一般情况下分成三个阶段parse阶段,transform阶段,generate阶段,编辑器本质上就是把template,编辑成为了一个render的函数,在vue3中,他将这个阶段进行了系统的划分,我们可以直接通过baseparse把template直接转化成ast,就是动态抽象语法树,然后利用transfrom把js转化为jsast,就是js标记的抽象语法树,然后再通过generator把jsast拼接成一个render的渲染函数
- 在vue3里面,在项目中要用到的,甚至是一些生命周期,都需要import进行动态导入,这样做的目的是为了更好的 Tree-shaking,因此可以更好地剔除不需要的代码
- vue3中可以没有根标签,实际上他会默认将多个根标签包裹在一个fragement虚拟标签中,有利于减少内存
- Vue 3 的代码库已经全面采用 TypeScript 重写,提供了更好的类型推断和类型提示
- 在vue2中v-for的优先级高于v-if,可以放在一起使用,但是不建议这么做,会带来性能上的浪费,在vue3中v-if的优先级高于v-for,一起使用会报错。可以通过在外部添加一个标签,将v-for移到外层
- diff算法不同,vue2中的diff算法,遍历每一个虚拟节点,进行虚拟节点对比,并返回一个patch对象,用来存储两个节点不同的地方。用patch记录的消息去更新dom
- 缺点:比较每一个节点,而对于一些不参与更新的元素,进行比较是有点消耗性能的。
- vue3中的diff算法,在初始化的时候会给每一个虚拟节点添加一个patchFlags,是一种优化的标识。只会比较patchFlags发生变化的节点,进行视图更新。而对于patchFlags没有变化的元素作静态标记,在渲染的时候会直接复用。
- 在使用上,目前使用vue3的话,状态管理从vuex换成了pina,事件总线使用的是mitt
前端性能如何优化
- 前端性能优化主要有两个大方向,一个是让加载更快,一个是让渲染更快
- 加载更快其实就是尽可能地减少网络请求,类似使用雪碧图,代码压缩打包,减少http的请求次数,合并代码,ssr服务端渲染,使用cdn,使用缓存等等
- 让渲染更快,主要就是改变资源的渲染方式或者顺序,类似css放在head,js放在body下面,使用懒加载,对dom查询进行缓存(createDocumentFragment),使用防抖(输入框-频繁输入等一段时间再触发)和节流(拖拽-保持固定频率,一段时间只执行一次)等等
前端的打包工具有了解过吗
- 前端打包工具主要有grunt、glup、webpack、rollup、parcel、vite等
- grunt出现的最早,他使用配置的思想来打包脚本,一切皆可配置,但缺点是只有一个配置文件,配置项太多,如果装很多插件会显得特别乱,不同的插件也会有自己的扩展字段,需要了解各种插件的配置规则和配合方式,学习成本比较高
- glup是基于node的steam流进行打包的,定位是基于任务流的自动化构建工具,优点是写法简单直观,适合多页面的应用开发,缺点是因为是异步的,很难控制他的执行顺序,异常处理比较麻烦,不适用单页面开发,打包方面比较弱,要自己写任务,如果有各种文件,类似图标字体等,需要单独适配,不能像webpack一样一起处理,不适用复杂项目
- webpack主要有四大核心功能,入口、出口、loader(加载器)和插件,webpack是打包工具,gulp和grunt属于构建工具,weboack可以代替他门的一些功能,学习成本比grunt小一些,但比gulp高一些
- rollup最大的亮点是利用es6模块设计,用标准的es6格式写代码,通过减少死代码尽可能缩小包的体积,缺点是对代码拆分、静态资源、commonJs模块支持不太友好,一般对于应用使用webpack,对于类库使用rollup,vite就是使用rollup打包的
- parcel是快速、零配置的web应用程序打包器,内置了常见的构建方案及其依赖,能以html为入口自动检测和打包依赖资源,真正做到开箱即用,但他的缺点也很明显,配置不是很灵活
loader和plugin不同点
- webpack将一切文件视为模块,但webpack原生只能解析js文件,如果要打包其他文件,就要用到loader,所以loader的作用是让webpack拥有加载和解析非js文件的能力
- plugin是插件,可以扩展webpack的功能,在webpack运行的生命周期中会有很多事件,插件可以监听这些事件,在合适的时机通过werbpack提供的api改变输出结果
webpack的热加载原理
- webpack热更新简称hmr,,当代码修改后,webpack将会对代码重新打包,将新的模块发送到浏览器端,浏览器用新的模块替换掉旧的模块,以实现不刷新浏览器的前提下刷新页面
- Webpack-dev-server文件中有一个server类,就是通过实例化这个server类来创建服务的,创建完服务之后,通过server的listen方法传入端口号来启动服务, 在new这个server类的时候,需要将webpack配置文件以参数的形式传入,即webpack.config.js,再通过webpack的方法构建出webpack实例即compiler,这个compiler就是需要传入server类的参数
- 再到server类中,添加webpack-dev-middleware中间件,用来提供编译后产出的静态文件服务
- 再使用sockjs启动websocket服务在服务器和浏览器之间建立一个长链接,不过服务端传递的主要信息还是新模块的hash值,后面主要根据这个hash值来进行模块热替换
- 最后webpack以监听模式开始编译,就实现了热更新即 compiler.watch({}, ()=>{})
web安全基础
- sql注入
- xss攻击
- 标签用特殊字符表示
- xsrf攻击
- 用post请求,并添加验证
简单讲一下js的原型链
- js本身就是基于原型继承的语言,在es6之前,我们只能通过写原型来继承,不像java可以通过class来继承,不过在es6之后,我们也可以通过class来继承,但只是写法上相似,它真正的继承还是原型上的继承,即es6的class本质上是原型链的一种体现
- class的原型本质是每个类都有一个显式原型,每个实例都有一个隐式原型,实例的显式原型指向对应类的隐式原型,即子类显式原型的隐式原型指向父类的显式原型,一层层往上找,就形成了原型链
People.prototype === Student.prototype.__proto__
- 原型链他实际上是js特有的,所有对象都可以共享原型上的方法,他的优势就是可以节省内存,非常方便,像我们应用场景,比如jquery,源码上就可以看到这个$就放在了jquery原型上,当我们使用$的时候,就可以很方便的拿到一些属性,还有就是我们用vue开发的时候,我们axios就放在了vue的实例上,所以我们通过$axios就可以在任何一个文件上使用了
instanceof的工作原理
- 就按照
xialuo instanceof Object
来说- instanceof前面的变量(xialuo),顺着隐式原型,一层层往上找,找到student、people、object的显示原型
- 如果这个隐式原型能对应到object的显示原型,那么
xialuo instanceof Object
成立
- hasOwnProperty可以判断某个属性是否是某个对象的属性
- hasOwnProperty属于object这个原型上的方法,js中object原型链的顶层,所以类的实例都可以使用这个方法
new Object()和Object.create()的区别
- {}等同于
new Object({})
,原型都是Object.prototype
Object.create(null)
没有原型- 他必须传参,可以传对象,也可以传null
- null其实是一个空对象
Object.create({...})
没有原型的原因是他可以指定原型- 传入一个null,就是告诉他不要有原型
- 传入一个对象,就是告诉他去指定原型
- Object.create()传参之后,对象中没有值,只是将参数的对象全部将放在空对象的原型中,这是和{}最大的区别
- Object.create()是创建一个空对象,然后把空对象的原型指向了传入的对象
this的不同应用场景,如何取值
- 当作普通函数被调用
- 指向window
- 谁调用指向谁
- 使用call、apply、bind
- 传入什么,指向什么
- 作为对象方法调用
- 指向对象本身
- class的方法中调用
- 指向当前实例本身
- 箭头函数
- 找上级作用域的值来确定
event loop的过程(详细)
- 同步代码,一行行放在call stack(调用栈)执行,调用栈执行一行,清空一行
- 遇到异步,会先记录下,等待时机(定时、网络请求等)
- 微任务会被放到micro task queue(微任务队列)里面等待时机
- 宏任务会被放到Callback Queue(任务队列)里面等待时机
- 先执行micro task queue(微任务队列)中的微任务
- 尝试DOM渲染
- 时机到了,就移动到Callback Queue(回调函数队列)
- 如果call stack(调用栈)为空(即同步代码执行完),Event Loop开始工作
- 轮询查找回调函数队列,如果有则移动到执行栈执行
- 即执行宏任务
- 然后继续轮询查找(永动机一样)
- 这样异步就可以永远执行下去
- 微任务是ES6语法规定的
- Promise、async/await
- 宏任务是由浏览器规定的
- setTimeout、setInterval、Ajax、DOM事件
css垂直居中的方法
- 如果不考虑兼容性,用flex布局实现会比较方便,在大盒子里面设置display:flex,align-items,设置center,这样就会垂直居中了,横向的话,就是justify-content也指定为center,就会水平居中了,如果不考虑兼容性的话,可以设置margin值,给他左边距设置50%,再用transform -50给他拉回来
ts面试题
- TypeScript 是 JavaScript 的超集,为该语言添加了静态类型。它允许开发人员定义变量、函数参数和返回值的数据类型,这有助于在编译时而不是运行时捕获错误
- TypeScript 中的静态类型可以在开发过程中指定变量、函数参数和返回值的数据类型。这有助于及早捕获与类型相关的错误,从而提高代码质量和可维护性
- 当无法自动推断类型时,TypeScript 中的类型断言允许您显式告诉编译器变量的类型。这是使用
<type>
或 as type 语法实现的 - TypeScript 中的泛型允许您创建可与各种类型一起使用的可重用组件或函数。它们支持强类型,同时保持使用不同数据类型的灵活性
有使用过原生js吗
- 原生js的操作可以分为Dom操作和Bom操作,还有其他一些js api的操作,bom操作,其实就是浏览器相关的操作,比如获取浏览器信息的navigator,获取url信息的location,对浏览器url进行操作的history等
- 对于dom操作的话,主要就是针对html元素的一些增删改查
- 先说dom的新增,比如我们根据http请求,获取并处理好了一些数据,并组成了一段html代码片段,需要将他插入到dom里面的话,可以使用appendChild,但如果我们需要完全替换掉盒子里面的内容的话,可以使用innerHtml,如果我们为了在一个空的盒子里面需要创造一些元素的话,我们可以使用createElement,我们知道,DOM操作比较耗时,我们有时候为了避免频繁的操作dom元素,会对dom进行缓存,就需要使用到dom的代码片段,createDocumentFragment
- 再说说dom的删除,dom的删除其实就是removeChild
- 再说说dom的修改,dom节点的修改实际上就是将innerHtml与appendChild联合起来使用,dom节点上属性的修改,有修改对象属性property,和修改html属性两种,前者不会体现在html中,例如p.style.color,后者会改变html结构,需要使用setAttribute(键值对)、getAttribute
- 最后说一说dom结构的查询,主要就是如何获取dom节点,比如根据id查找,根据类名查找,根据标签名查找,还有就是querySelector、querySelectorAll
- 其他的非dom的原生js操作,有数组操作,xhr的一些操作,正则的一些操作等
map,filter,forEach的区别
- 他们三个其实都是array的原型方法,也就是被挂载到array的prototype上面,对于foreach而言,他的本质实际上就是循环,他主要的一个作用就是可以循环一个数组,然后在循环的过程中去做一些事情,filter和map都包含返回值,对filter而言,他可以通过他的返回值来去筛选出我想要的数据,对于map而言其实也是循环,但他可以基于原数组的数据变成一个新的数组
闭包的理解
- 闭包可用理解为能够读取其他函数内部变量的函数,或简单理解为定义在一个函数内部的函数,内部函数持有外部函数内变量的引用,闭包的话大致有两个作用,第一个是保护,第二个是保存
- 保护的话是首选函数内部会产生一个私有作用域,不受外界干扰,在各种模块开发上实际上都可以看到闭包的影子
- 保存的话就是,当一个函数返回了一个引用数据类型,并且被外界所接收,就会形成一个不销毁的作用域,他就会一直存在在堆内存中,但也很容易造成内存泄漏
- 内存泄漏的话,其实就是浏览器无法回收这个代码的内存,比如说一个对象,或者是一个数组
什么时候用margin,什么时候用padding
- 同级盒子一般使用margin
- 父子盒子一般使用padding
- 因为父子盒子用margin很容易造成塌陷问题
- 最常用的方式就是超出部分进行隐藏,就是overflow hidden,
- 超出部分隐藏的原理实际上就是产生一个块格式化上下文bfc,当我们产生一个bfc的时候,就会根据这个块级格式化上下文的规则去渲染我们的页面,他和我们html的渲染是分开的,他不存在margin塌陷,所以就可以解决这个问题
flex布局
- 在最外部盒子中设置flex之后,在当前盒子可以设置一些属性,比如flex-direction可以改变items的流向,flex-wrap可以设置是否折行,justify-content可以设置主轴的对齐方式,align-items可以设置交叉轴对齐方式
- 在子元素上可以使用align-self设置子元素的对齐方式
在开发中遇到的最大问题是什么
- 考核你解决项目问题的能力
- avue项目
- 之前有家公司做项目用的avue,avue里面的api比较简单,也有些bug
- avue主要是element-ui的集成,主要是针对一些简单的表格的,他的筛选、表格、分页都是写在一起的
- 但对于复杂的表格,比如一个tab页里面有两个表格全是前端维护的,表格里面有按钮,按钮点进去会触发另一个表格,表格里面还有文本框下拉框以及还有各种校验,一个下拉菜单有很多限制,触发一个下拉菜单会对表格文本框做一些禁用或者显示隐藏,点击提交会在父表格增加一条记录同时影响另外的表格,这种avue坑就有很多
- git方面有
- 由于我有段时间有管理团队,团队开发用的是git,我那时候git基本都可以用,但分支这块用的不熟,所以找时间把分支系统了解了一下
- 还有就是我的博客用的是github page,但现在github使用https上传很麻烦,会经常push不上去,捣鼓了很久,用ssh上传解决了
- 还有的就是我的博客,vuepress里面加上评论和阅读量找了一些插件
- 部署项目
- 做管理的那段时间,领导要求我去部署前后端项目,在安装nginx的时候出了点问题,导致他不能访问,后来排查出来时防火墙的问题
- 在客户端部署nginx服务的时候,有时候因为vue项目里面的接口是走代理的,nginx也要配置相应的代理
- 服务器上有些东西需要加密,可以在nginx上配置密码
- 部署三维模型的时候,模型和项目是分开部署的,都是在nginx里面,模型的请求一直出现跨域,后来配置了nginx-cros才解决问题
- 新东西
- 之前公司在做数据中台的时候需要用elk
- 使用es存储数据最大的问题是es如何与前端框架结合,我后来使用proxy代理的方法,然后在某个js里面封装es增删改查语法,才在项目里用起来
- 用node做爬虫的时候,由于有很多反爬虫机制,后来我用nightmare这个库来模拟浏览器操作,才解决了问题
- 剩下的就是模型上的一些问题了
- 更多的是模型数据上的处理以及模型如何与硬件设备一一对应
- 最大的问题是模型数据如何在场景里面去使用,后面了解到3dtiles,后面慢慢摸索,可以把各种类型的像dae、obj、oggb、bim转换成3dtiles,并在页面中渲染
- 3维场景里面的最大问题是浏览器崩溃和锯齿,通过了解一系列cesium配置,可以把影响降低到最小
- 在业务场景中有的不是点击标注做的交互,要直接点击模型,后面了解到模型的单体化,和数据进行沟通交流,才把问题解决
- 更多的是模型数据上的处理以及模型如何与硬件设备一一对应
- 最后是项目管理的一些坑
- 其实也不能说是坑,项目把控的时候要做excel表格,主要是我那时候不熟悉,后面excel熟练了一些
- avue项目
三维相关的一些东西
2.1.1.2. 三维可视化有哪些主要的引擎
- webgl
- three.js
- cesium.js
- marsv.js => 火星科技,在cesium的基础上封装
2.1.13. 我了解到的三维可视化知识点
主要是cesium
- 加载地球
- 加载地球底图
- 底图类型
- 天地图
- 高德地图
- 谷歌地图
- 百度地图
- 微软地图 => bingMap
- 底图功能
- 基础底图
- 可显示所在点的经度、纬度、海拔、方向以及视高
- 复位底图
- 点击后回到指定视区
- 视图
- 可切换三维视图、二维视图、哥伦布视图
- 全屏
- 方向盘操作
- 按下鼠标左键并向四周拖拽不释放可修改视图角度,双击重置视图;单击并拖拽旋转,修改视角方向
- 鼠标右键
- 可显示此处经纬度、显示当前视角信息、开启光照效果、开启深度检测、绕此处环绕飞行、移动到此处、第一视角站到此处
- 基础底图
- 注意事项
- 主要是一些地图的底图,每个地图加密算法不一样,坐标点不一样,天地图未经过加密,其他地图坐标都是通过天地图的坐标转换而来的
- 底图类型
- 加载地球模型
- 主要用3dtiles来加载模型
- 主要用cesiumlab工具处理导出
- 3D Tiles是用于流式传输大规模异构3D地理空间数据集的开放规范。为了扩展Cesium的地形和图像流,3D Tiles将用于流式传输3D内容,包括建筑物,树木,点云和矢量数据。
- 3D Tiles是由一个从一开始就使用WebGL的团队设计的,而OpenGL在此之前已经使用了很多年。因此,与glTF一样,从接收3D Tile到使用WebGL渲染3DTF的流程简化为快速简单,并最大限度地减少客户端处理。为了减少WebGL绘制调用的数量,可以预先批量处理或批量处理切片。
- 3dtiles有两种方法直接获取模型数据,第一个是用geojson盖在上面,第二个是处理模型的时候分开,然后用单体化的类去获取
- 主要用3dtiles来加载模型
- 加载模型数据格式(这里的都是较大场景)
- 单模型场景
- 即把所有场景效果改成false
- 倾斜摄影
- 原格式为osgb,由无人机飞行得来,用cesiumlab可以转化成3dtiles
- 城市建筑白模
- 原格式为dae,因为没有贴图,模型较小,用cesiumlab可以转化成3dtiles
- 人工模型
- 原格式为dae,在白模的基础上加上贴图,有精模和简模之分,模型很大
- bim数据
- 建筑模型,单体化比较好做,原格式为dae,用cesiumlab可以转化成3dtiles
- 单模型场景
- 小模型加载 => gltf
- GLTF——3D图形界的JPEG
- glTF(GL TransmissionFormat),即图形语言交换格式,它是一种3D内容的格式标准,由Khronos Group管理(Khronos Group还管理着OpenGL系列、OpenCL等重要的行业标准);
- glTF的设计是面向实时渲染应用的,尽量提供可以直接传输给图形API的数据形式,不再需要二次转换
- glTF对OpenGL ES、WebGL非常友好
- glTF的目标是:3D领域的JPEG
- 作为一个标准,自2015年10月发布(glTF 1.0)以来,已经得到了业界广泛的认可,你可以相信它的水平
- GLTF具体的信息可以去官方网站上看:https://www.khronos.org/gltf/
- 加载地球底图
- 地球标注
- 单个点
- 点、图标点、文字、小模型
- 二维空间、二维贴地
- 有深度检测功能
- 线、曲线、面、圆、矩形
- 三维空间
- 墙、立体、圆柱体、矩形体
- 单个点
- 场景控制
- 开场动画
- 旋转的地球
- 双屏对比
- 加载不同的地球底图
- 鹰眼
- 小地图
- 大部分是二维地图
- 巡更漫游
- 显示隐藏巡更线
- 增删改巡更路线
- 开始巡更、停止巡更、暂停巡更
- 打开关闭深度检测
- 开启摄像头
- 巡更到某个位置会打开摄像头
- 监控视频格式主要是*.w3u8
- 主要使用videojs插件
2.1.2 三维可视化业务场景
2.1.2.1 模型部分
- 加载模型
- 标注的增删改查
- 视点的增删改查
- 巡更的增删改查
- 关键点事件处理(一般是加载视频)
- 其他
- 单体化……
- 视频投影……
2.1.2.2 硬件设备
- 需要对接一些硬件设备信息
- 展现方式为标注
- 硬件设备信息详情主要是:
- 文字信息(大部分不是实时的)
- 图片信息(需要实时或者普通接口)
- 视频-摄像头(一般使用hls进行对接【对方提供*.m3u8格式视频流】)
2.1.2.3 统计图
- 二维或者三维,统计设备信息
2.1.2.4. 布局
- 设备报警信息放哪里
- 相关统计图放的位置
- 哪些页面放哪些模块
2.2. 后台管理
- 封装了axios
- 配置了nginx,使vue使用proxy之后打包可以正常运行
- 封装了若干插件
- 进度条、上传、 quill 富文本、使用 i18n 实现国际化等