深圳智学无忧项目面试题(套题)
| 选择题 | 填空题 | 问答题 | 编程题 | 试题难度 | 
|---|---|---|---|---|
| 0 | 0 | 20 | 0 | 一般 | 
问答题
- 1、封装一个组件的步骤是怎么样?
- 1.使用Vue.extend()创建一个组件 - 2.使用Vue.component()方法注册组件 - 3.如果子组件需要数据,可以在props中接受定义 - 4.子组件修改好数据之后,想把数据传递给父组件,可以使用emit()方法 
- 2、你再项目中有使用get或者post请求么?那么get和post的区别是什么呢
- 我在项目中有使用过,我个人理解get和post的区别有一下几点: - 1.发送请求 - get请求无消息体,只能携带少量数据 - post请求有消息体,可以携带大量数据 - 2.携带数据的方式: - get请求将数据放在url地址中 - post请求将数据放在消息体中 - 3.GET请求请提交的数据放置在HTTP请求协议头中,而POST提交的数据则放在实体数据中; - 4.GET方式提交的数据最多只能有1024字节,而POST则没有此限制。 
- 3、你在项目中有做过哪些方面的封装呢
- 有的,在项目开发时,我会对一些有复用性的功能会封装成组件,减少代码臃肿,方便项目维护,有封装过富文本框、主题切换、用户头像、分页等。当然除了组件封装也会对http请求做封装,以及项目中常用的方法做封装,像日期格式、正则表达式验证这些。 
- 4、你在项目中有做过图片上传么?那么图片上传的实现思路是怎么样的呢
- 主要是讲思路: - 把图片转成base64位,上传到后台,后台返回保存图片的链接地址,然后把链接地址在上传到后台,多个图片时,就把得到的多个链接地址上传到后台 
- 5、项目中遇到的困难,以及你是如何解决的
- 最近使用uniapp做了一个兼容三端微信小程序,H5,Android三端的程序,遇到的兼容性问题还是挺多的。我的解决方法就是要分析调试,找到问题的原因就好解决了。 - 在布局登录页面时,需要登录框垂直居中,在小程序对登录框容器使用高度100vh,使用弹性盒子布局,设置align-items:center就可以了,但在h5端不行,进过调试发现,H5端的导航栏是模拟出来,100vh是包含了导航栏的高度,所以在H5端就不能使用100vh。最后面的做法就是让page的高度为100%,登录框的容器也为100%,page的100%高度正好是去掉了导航栏的窗体高度,这样就兼容了三端。 - 还有项目要求登录框是椭圆的,我用的是easy-input组件需要样式覆盖才能实现,发现在小程序上不行,原因是easyinput是虚拟化组件节点,添加的class不会被渲染,而在H5端是可以的,只好用view包裹起来,添加class。 - 兼容性的问题还是挺多的,一般进过分析,调试找出问题的原因,就能够很快的解决。 
- 7、你在项目中使用过路由么?那么你讲一讲路由的原理
- 先讲路由有几种模式,然后在讲区别 - (1)hash 模式的实现原理 - 早期的前端路由的实现就是基于 location.hash 来实现的。其实现原理很简单,location.hash 的值就是 URL 中 # 后面的内容。比如下面这个网站,它的 location.hash 的值为 '#search': - https://www.word.com#search - hash 路由模式的实现主要是基于下面几个特性: - URL 中 hash 值只是客户端的一种状态,也就是说当向服务器端发出请求时,hash 部分不会被发送; - hash 值的改变,都会在浏览器的访问历史中增加一个记录。因此我们能通过浏览器的回退、前进按钮控制hash 的切换; - 可以通过 a 标签,并设置 href 属性,当用户点击这个标签后,URL 的 hash 值会发生改变;或者使用 JavaScript 来对 loaction.hash 进行赋值,改变 URL 的 hash 值; - 我们可以使用 hashchange 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)。 - (2)history 模式的实现原理 - HTML5 提供了 History API 来实现 URL 的变化。其中做最主要的 API 有以下两个:history.pushState() 和 history.repalceState()。这两个 API 可以在不进行刷新的情况下,操作浏览器的历史纪录。唯一不同的是,前者是新增一个历史记录,后者是直接替换当前的历史记录,如下所示: - window.history.pushState(null, null, path); - window.history.replaceState(null, null, path); - history 路由模式的实现主要基于存在下面几个特性: - pushState 和 repalceState 两个 API 来操作实现 URL 的变化 ; - 我们可以使用 popstate 事件来监听 url 的变化,从而对页面进行跳转(渲染); - history.pushState() 或 history.replaceState() 不会触发 popstate 事件,这时我们需要手动触发页面跳转(渲染)。 
- 8、浅拷贝与深拷贝的区别,如何实现一个深拷贝 / 深度克隆你通常使用哪种方法,如果使用JSON.stringify,再使用JSON.parse()会出现什么问题
- 浅拷贝对于值类型拷贝是内容,对于引用类型拷贝的是引用地址,指向的是同一个对象。 - 深拷贝的方式很多可以使用JSON.stringif在用JSON.parse的方式,但会丢失undefined、Function等类型的数据,也不支持循环引用。 - 也可以使用递归遍历对象的方式,构建一个新的对象,在用递归遍历进行值拷贝,始终避免引用赋值的情况。 - 不过我在项目开发使用的是lodash工具库的cloneDeep函数来做的,这个函数已经非常全面的考虑各种引用类型的深拷贝情况。 
- 9、在项目中使用深度监听导致项目加载慢,怎么处理
- 看如下代码,注释很清楚: - <template> - <div> - <input type="text" v-model="value" > - <p>{{pValue}}</p> - <input type="text" v-model="userName.name"> - </div> - </template> - <script> - export default { - data() { - return { - value:'111111111', - pValue:"12", - userName:{ - name:"Mir.Wang" - } - } - }, - watch: { - value(a,b){ //监听input值,发生变化就会触发 - this.pValue = a - }, - pValue(a,b){ //监听p标签得值,当input值发生变化时,设置了p标签的值,该函数就会触发 - //console.log(a,b) - }, - "userName.name"(a,b){ //用字符串的方法来取代深度监听deep:true,//深度监听底层一个一个得遍历,很浪费性能 - console.log(a,b) - } - }, - } - </script> 
- 11、项目开发流程是怎么样的呢?
- 一. 初始需求阶段 - ● 用户提出需求:确定项目开发的目标和范围,与其可行性。 - ● 分析需求规格:敲定主要功能模块,确定开发周期和报价。 - ● 需求讨论规划:双方面谈,将软件需要实现的各个功能进行详细需求分析调整。 - 二. 合同原型阶段 - ● 签署开发合同:双方签订合同,客户支付预付款并提供人力、物力及相关协助。 - ● 原型详细设计:将需求分析转化成未来系统符合用户期望的原型设计。 - ● 开需求评审会:原型设计完成后,客户审核并确认具体设计,供应商开始编写实现。 - 三. 个性化开发阶段 - ● 软件开发设计:对整个软件系统进行设计,如系统框架设计、数据库设计等,为系统开发一个健壮的结构并调整设计使其与实现环境相匹配。 - ● 程序开发编码:在开发构建阶段,由供应商程序员根据详细设计及计划,将所有应用程序功能开发并集成为产品。 - ● 软件测试阶段:测试要验证对象间的交互作用,验证软件中所有组件的正确集成,检验所有的需求已被正确的实现, 识别并确认缺陷在软件部署之前被提出并处理。 - 四. 交付维护阶段 - ● 产品软件部署:部署的目的是成功的生成版本并将软件分发给最终用户。 - ● 正式验收交付:要确定软件、环境、用户是否可以开始系统的运作,交付阶段的重点是确保软件对最终用户是可用的。 - ● 后期项目维护:软件产品发布后,根据需求变化或硬件环境的变化对应用程序进行修改。 
- 12、项目打包上线的流程
- 我们的项目是基于webpack来打包的,使用npm run build打包成最终要上线的代码,为了提升性能,我们的项目还做了分包处理,每个路由的组件单独打包一个独立的js、css文件来加载。打包完成后,将文件上传到iis服务的对应站点目录。 
- 13、你在工作中是如何提升工作效率的
- 一、提前制定工作计划 - 工作没有计划,就容易bai盲目,找不到努力的方向。所以,要提前制定符合自己的工作计划,合理安排工作时间,并严格遵守执行。我们可以利用敬业签多分类、易归纳的优点,提前制定出工作计划,为每项工作安排合理的时间,高效利用工作的每一小时。 - 二、对工作任务进行优先级排序 - 首先要明确自己的工作任务及目标,然后根据工作任务的轻重缓急进行优先级排序,重要的事情提前做,避免被无关紧要的事情拖延。我们还可以借助敬业签待办事项提醒的功能,将工作中的重要事项,设置成重要事项间隔提醒,帮助我们战胜拖延,对时间做到心中有数。 - 三、养成随手记录的习惯 - 要在工作中养成随手记录的习惯,临时下发的工作任务或是对工作有用的信息及时记录下来,不仅能防止我们遗忘,还能让我们释放大脑内存,将专注力放在工作上。敬业签随时记录、自动保存的功能,能配合我们养成随手记录的习惯。 - 四、及时总结经验和教训 - 在我们的工作中可能会犯一些错误,或者遇到一些难题,所以要及时总结经验和教训,避免再次遇到时会手足无措。敬业签还能实现多端云同步,只需登录同一账号,便可在Windows电脑端、ipad、安卓Android手机、苹果IOS手机以及Web网页端查看到记录内容,保证我们随时随地都能参考经验教训。 
- 14、你在项目中使用了哪些代码优化的方法
- 如果没有对 Vue 项目没有进行过优化总结的同学,可以参考本文作者的另一篇文章《 Vue 项目性能优化 — 实践指南 》,文章主要介绍从 3 个大方面,22 个小方面详细讲解如何进行 Vue 项目的优化。 - (1)代码层面的优化 - v-if 和 v-show 区分使用场景 - computed 和 watch 区分使用场景 - v-for 遍历必须为 item 添加 key,且避免同时使用 v-if - 长列表性能优化 - 事件的销毁 - 图片资源懒加载 - 路由懒加载 - 第三方插件的按需引入 - 优化无限列表性能 - 服务端渲染 SSR or 预渲染 - (2)Webpack 层面的优化 - Webpack 对图片进行压缩 - 减少 ES6 转为 ES5 的冗余代码 - 提取公共代码 - 模板预编译 - 提取组件的 CSS - 优化 SourceMap - 构建结果输出分析 - Vue 项目的编译优化 - (3)基础的 Web 技术的优化 - 开启 gzip 压缩 - 浏览器缓存 - CDN 的使用 - 使用 Chrome Performance 查找性能瓶颈 
- 15、你的vue项目中对vue. config. js文件做了什么
- 可以配置一下东西: - // vue.config.js - const path = require(‘path’); - const CompressionWebpackPlugin = require(“compression - webpack - plugin”); // 开启gzip压缩, 按需引用 - const productionGzipExtensions = /.(js|css|json|txt|html|ico|svg)(?.*)?$/i; // 开启gzip压缩, 按需写入 - const BundleAnalyzerPlugin = require(“webpack - bundle - analyzer”).BundleAnalyzerPlugin; // 打包分析 - const IS_PROD = [‘production’, ‘prod’].includes(process.env.NODE_ENV); - const resolve = (dir) => path.join(__dirname, dir); - module.exports = { - publicPath: process.env.NODE_ENV === ‘production’ ?‘/ site / vue - demo /’ : ‘/’, // 公共路径 - indexPath: ‘index.html’ , // 相对于打包路径index.html的路径 - outputDir: process.env.outputDir || ‘dist’, // ‘dist’, 生产环境构建文件的目录 - assetsDir: ‘static’, // 相对于outputDir的静态资源(js、css、img、fonts)目录 - lintOnSave: false, // 是否在开发环境下通过 eslint-loader 在每次保存时 lint 代码 - runtimeCompiler: true, // 是否使用包含运行时编译器的 Vue 构建版本 - productionSourceMap: !IS_PROD, // 生产环境的 source map - parallel: require(“os”).cpus().length > 1, // 是否为 Babel 或 TypeScript 使用 thread-loader。该选项在系统的 CPU 有多于一个内核时自动启用,仅作用于生产构建。 - pwa: { }, // 向 PWA 插件传递选项。 - chainWebpack: config => { - config.resolve.symlinks(true); // 修复热更新失效 - // 如果使用多页面打包,使用vue inspect --plugins查看html是否在结果数组中 - config.plugin(“html”).tap(args => { - // 修复 Lazy loading routes Error - args[0].chunksSortMode = “none”; - return args; - }); - config.resolve.alias // 添加别名 - .set(’@’, resolve(‘src’)) - .set(’@assets’, resolve(‘src / assets’)) - .set(’@components’, resolve(‘src / components’)) - .set(’@views’, resolve(‘src / views’)) - .set(’@store’, resolve(‘src / store’)); - // 压缩图片 - // 需要 npm i -D image-webpack-loader - config.module - .rule(“images”) - .use(“image - webpack - loader”) - .loader(“image - webpack - loader”) - .options({ - mozjpeg: { progressive: true, quality: 65 }, - optipng: { enabled: false }, - pngquant: { quality: [0.65, 0.9], speed: 4 }, - gifsicle: { interlaced: false }, - webp: { quality: 75 } - }); - // 打包分析, 打包之后自动生成一个名叫report.html文件(可忽视) - if (IS_PROD) { - config.plugin(“webpack - report”).use(BundleAnalyzerPlugin, [ - { - analyzerMode: “static” - } - ]); - } - }, - configureWebpack: config => { - // 开启 gzip 压缩 - // 需要 npm i -D compression-webpack-plugin - const plugins = []; - if (IS_PROD) { - plugins.push( - new CompressionWebpackPlugin({ - filename: “[path].gz[query]”, - algorithm: “gzip”, - test: productionGzipExtensions, - threshold: 10240, - minRatio: 0.8 - }) - ); - } - config.plugins = […config.plugins, …plugins]; - }, - css: { - extract: IS_PROD, - requireModuleExtension: false,// 去掉文件名中的 .module - loaderOptions: { - // 给 less-loader 传递 Less.js 相关选项 - less: { - // globalVars 定义全局对象,可加入全局变量 - globalVars: { - primary: ‘#333’ - } - } - } - }, - devServer: { - overlay: { // 让浏览器 overlay 同时显示警告和错误 - warnings: true, - errors: true - }, - host: “localhost”, - port: 8080, // 端口号 - https: false, // https:{type:Boolean} - open: false, //配置自动启动浏览器 - hotOnly: true, // 热更新 - // proxy: ‘http://localhost:8080’ // 配置跨域处理,只有一个代理 - proxy: { //配置多个跨域 - “/api”: { - target: “http://172.11.11.11:7071”, - changeOrigin: true, - // ws: true,//websocket支持 - secure: false, - pathRewrite: { - “^ /api”: “/” - } - }, - “/api2”: { - target: “http://172.12.12.12:2018”, - changeOrigin: true, - //ws: true,//websocket支持 - secure: false, - pathRewrite: { - “^ /api2”: “/” - } - }, - } - } - } 
- 16、项目使用什么源代码管理工具来管理代码呢
- 常用的源代码管理工具有两种 - 1.git - 2.SVN - 了解常用的命令 - git: - git help :git指令帮助手册 - 查看其他指令的做法:git help 其他指令 - git config :git的配置信息相关(修改的是.git/config文件) - 配置用户名:git config “user.name” 用户名(用于跟踪修改记录) - 配置邮箱:git config “user.email” 邮箱(用于多人开发间的沟通) - 查看配置信息:git config –l - 编辑配置信息:git config –e(用vim编辑,:wq是退出vim编辑器) - 设置指令的别名:git config alias.别名 原指令名称 - 设置带参数指令的别名:git config alias.别名 “原指令名称 参数” - 将此设置应用到整个系统中:git config ––gloabal - git status :查文件的状态 - 查看某个文件的状态:git status 文件名 - 查看当前路径所有文件的状态:git status - git log :查看文件的修改日志 - 查看某个文件的修改日志:git log 文件名 - 查看当前路径所有文件的修改日志:git log - 用一行的方式查看简单的日志信息:git log ––pretty=oneline - 查看最近的N次修改:git log –N(N是一个整数) - git diff :查看文件最新改动的地方 - 查看某个文件的最新改动的地方:git diff 文件名 - 查看当前路径所有文件最新改动的地方:git diff - git init :初始化一个空的本地仓库,生成一个.git目录,用于维护版本信息 - 在当前路径初始化仓库:git init - 在其他路径初始化仓库:git init 仓库路径 - git add :将工作区的文件保存到暂缓区 - 保存某个文件到暂缓区:git add 文件名 - 保存当前路径的所有文件到暂缓区:git add .(注意,最后是一个点 . ) - git commit :将暂缓区的文件提交到当前分支 - 提交某个文件到分支:git commit -m ”注释” 文件名 - 保存当前路径的所有文件到分支:git commit -m ”注释” - git reset :版本回退(建议加上––hard参数,git支持无限次后悔) - 回退到上一个版本:git reset ––hard HEAD^ - 回退到上上一个版本:git reset ––hard HEAD^^ - 回退到上N个版本:git reset ––hard HEAD~N(N是一个整数) - 回退到任意一个版本:git reset ––hard 版本号(版本号用7位即可) - git reflog :查看指令使用记录(能够查看所有的版本号) - git rm:删除文件(删完之后要进行commit操作,才能同步到版本库) - git clone:下载远程仓库到本地 - 下载远程仓库到当前路径:git clone 仓库的URL - 下载远程仓库到特定路径:git clone 仓库的URL 存放仓库的路径 - git pull:下载远程仓库的最新信息到本地仓库 - git push:将本地的仓库信息推送到远程仓库 
- 18、小程序登录的流程是怎么样?
- 首先,我们不应该直接获取用户信息,目前好像也不能直接获取用户信息。 - 原则是:当我们需要获取用户信息的时候才发起授权。 - 1.wx.getUserInfo 这个函数 是需要授权才能获取用户信息 - 2.那么我们只能用button 然后加上open-开放功能获取用户信息,如果判断用户点击允许还是拒绝 可以通用bind**属性获取 - 那么登录流程 是不是可以这样呢 - 就是哪个页面需要显示用户信息 - 1就是判断是否授权 getSetting 方法 如果授权过了 就可以直接获取用户信息 页面上面的button 不显示 - 2如果没有授权 那就得需要通过button 来申请授权 然后用户同意后才能显示 - 可以写一个单独的 获取用户信息的方法 然后 同意后 调用即可 
- 19、小程序支付功能是怎么实现的呢
- 1、小程序注册,要以公司的以身份去注册一个小程序,才有微信支付权限; - 2、绑定商户号。 - 3、在小程序填写合法域 - 4.调用wx.login()获取appid - 5.调用 - wx.requestPayment( - { - 'timeStamp': '',//时间戳从1970年1月1日00:00:00至今的秒数,即当前的时间 - 'nonceStr': '',//随机字符串,长度为32个字符以下。 - 'package': '',//统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=* - 'signType': 'MD5',//签名类型,默认为MD5,支持HMAC-SHA256和MD5。注意此处需与统一下单的签名类型一致 - 'paySign': '',//签名,具体签名方案参见微信公众号支付帮助文档; - 'success':function(res){},//成功回调 - 'fail':function(res){},//失败 - 'complete':function(res){}//接口调用结束的回调函数(调用成功、失败都会执行) - }) 
- 20、小程序的上线流程
- 1.给商家注册小程序,完善商户信息,并在商家微信公众平台后台把权限赋予开发者; - 2.开发人员在商家公众平台的后端获取商户的APPID,然后在微信开发工具上进行开发;(获取APPID的方法:左侧设置---开发设置—开发者ID) - 3.开发过程当中利用手机端进行测试,找出BUG并进行修改; - 4.开发完成后在商家公众平台后台配置HTTPS服务器; - 5.配置完成后在微信开发工具上上传代码,填写版本号; - 6.上传成功后来到商家公众平台的后端里面的开发管理选项里面提交审核代码;并填写对应的功能页与关键字; - 7.提交审核之后等待审核(经过几次实验,平均每次审核时间4 -5小时); - 8.审核通过后发布版本就可以了,发布过后两三分钟就可以在手机小程序上搜索到对应的上线项目; 
 
                            