当前位置: 首页 > Web前端 > CSS

Vue的常用测试点(一)

时间:2023-03-31 12:01:34 CSS

0.原序中有36道Vue常见面试题。考虑到Vue面试题太多,分为三部分:Part1,Part2,Part2。如果你能看懂这三篇文章,相信你不会害怕面试中的vue题。1、在页面定义一个定时器,在哪个阶段会被清零?答:在beforeDestroy中销毁定时器。①为什么要销毁:我在a页写了一个定时器,比如每秒打印1。当我点击按钮进入b页时,会发现定时器还在执行,这对性能消耗很大。②方案一:mounted(){this.timer=setInterval(()=>{console.log(1)},1000)},beforeDestroy(){clearInterval(this.timer)}方案一有两个不好的地方在引用Yuda的地方:它需要在这个组件实例中保存这个定时器,如果可能的话,最好只有生命周期钩子才能访问它。这不是一个严重的问题,但它可以被认为是碎片。我们的构建代码独立于我们的清理代码,这使得我们更难以编程方式清理我们构建的所有内容。方案二(推荐):该方法是在定义定时器mounted(){consttimer=setInterval(()=>{console.log(1)},1000)this后,通过$once事件监听器的位置清除定时器.$once('hook:beforeDestroy',()=>{clearInterval(timer)})}官网参考链接:https://cn.vuejs.org/v2/guide...2.父组件如何获取子组件的数据,子组件如何获取父组件的数据,父子组件如何传值?①一、父组件如何主动获取子组件的数据?方案一:$children$children用于访问子组件实例。要知道一个组件的子组件可能不是唯一的,所以它的返回值是一个数组。现在,我们定义Header、HelloWorld两个组件mounted(){console.log(this.$children)}打印一个数组,可以使用foreach分别获取需要的数据缺点:无法确定子组件顺序不对反应灵敏。如果您确切知道要访问什么子组件,建议使用$refs。方案二:$refs在调用helloworld子组件的时候直接定义一个ref,这样就可以通过this.$refs获取需要的数据。this.$refs.hello.propertythis.$refs.hello.method②子组件如何主动获取父组件中的数据?Pass:$parent用于访问父组件实例,通常父组件是唯一确定的,类似于childrenthis.$parent。属性this.$parent。Method父子组件通信除了上面三种,还有props和attrs③inheritAttrs是@2.4新增的属性和接口。inheritAttrs属性控制父组件提供的属性是否显示在子组件的html属性上。如果我们将父组件Index中的desc、keywordsword、message这三个属性传递给子组件HelloWorld,在父组件Index部分如下子组件:HelloWorld,props:{message:String}中只接受messageprops,实际上我们只需要message,其他两个属性会作为普通的html元素插入到子组件的根元素。如图所示这样做会掩盖组件的预期功能。这时在子组件中写入,inheritAttrs:false,这些不用的属性会被去掉,如果为true,则显示出来。如果父组件中不需要的属性与子组件的原有属性冲突,则父组件子组件:HelloWorld此时父组件中type="text",子组件中type="number",但是type="text"显示在最后在实践中,这不是我们想要的,所以只要你设置:inheritAttrs:false,type就会变成number。上面这些没有用到的属性,怎么获取呢?这里用到了$attrs③$attrs的作用:可以获取未使用的注册属性,如果有需要,我们可以在这里继续往下传递。上面没有用到的desc和关键字可以通过$attrs获取。通过$attrs的这个特性,可以将父组件传递给孙子组件,省去了父组件传递给子组件,再从子组件传递给孙子组件的麻烦。代码如下:父组件Index部分

data(){return{message:'主页',desc:'主页描述',keywords:'我是关键字key'}},子组件HelloWorld部分获取父组件数据
孙子组件sunzi部分可以看出通过v-bind="$attrs"给孙子组件传输数据除了上面的,provide/inject也适用于跨代组件通信,尤其是获取祖先组件的数据,非常方便。简单来说,当引入的组件层数过多时,我们的后代组件想要获取祖先组件的资源,那怎么办呢?总不能把parent级别往上拿,代码结构容易混淆。这就是提供/注入的作用。exportdefault{name:"",inject:['for'],data获取for变量(){return{demo:this.for}}}3.如何定义自定义指令,它的生命周期是怎样的?通过Vue.directive()定义全局指令有几个可用的钩子(生命周期),每个钩子都可以选择一些参数。钩子如下:bind:指令附加到元素时触发inserted:元素添加到父元素时触发每当更新组件和子组件时,取消绑定:一旦删除指令就会触发。bind和update可能是五个中最有用的两个hook。每个挂钩都有可用的el、绑定和vnode参数。update和componentUpdated钩子还公开了oldVnode以区分传递的旧值和新值。el是要绑定的元素。绑定是一个对象,它保存传递给钩子的参数。有许多参数可用,包括名称、值、oldValue、表达式、arguments、arg和修饰符。vnode有一个更不寻常的用例,它可以用于你需要直接引用虚拟DOM的节点。binding和vnode都应该被认为是只读的。现在,自定义一个directive,添加一些样式,并指明定位距离Vue.directive('tack',{bind(el,binding){el.style.position='fixed';el.style.top=binding.value+'px'}})iistheheader
假设我们想区分70px距离顶部还是左侧,我们可以通过传递一个参数Vue.directive('tack',{bind(el,binding,vnode){el.style.position='fixed';consts=(binding.arg==='left'?'left':'top');el.style[s]=binding.value+'px';}})你也可以传入多个值Vue.directive('tack',{bind(el,binding,vnode){el.style.position='fixed';el.style.top=binding.value.top+'px';el.style.left=binding.value.left+'px';}})我是header
4,vue生命周期,简单说说每个阶段?breforeCreate():在创建实例之前,该阶段实例的数据和方法是不可读的。created():实例创建完成后,这个阶段已经完成了数据的观察,属性和方法的计算,watch/event事件回调,mount挂载阶段还没有开始。$el属性目前是不可见的,数据不会呈现在DOM元素上。created完成后,进行模板编译等操作,将模板编译成render函数,待render函数可用后执行。beforeMount()beforeMount():挂载开始前调用:相关渲染函数第一次调用mounted():挂载后调用,el选项的DOM节点被新创建的vm.$el替换,并且这个生命周期函数在挂载到实例后被调用。此时实例的数据渲染到DOM节点上,后续的钩子函数执行过程需要外部触发器来执行数据变化。它会调用beforeUpdate,然后通过VirtualDom,最后更新。当组件被销毁时,它会调用beforeDestory并销毁。5.手表和电脑有什么区别?Computed:①具有缓存机制;②不能接受参数;③可以依赖其他计算,甚至来自其他组件的数据;④不能复制数据中的属性;watch:①可以接受两个参数;②可以在监听的时候触发回调,并做一些事情;③被监控的属性必须存在;④允许异步watch配置:handler、deep(是否深??)、imeditate(是否立即执行)总结:当一些数据需要随其他数据发生变化时,推荐使用computed时,一般对数据变化有响应时,建议在执行一些业务逻辑或异步操作时使用watch6。请说说computed中的getter和setter①Computed分为getter(读取)和setter(设置值))②一般情况下没有setter,computedpreset只有getter,即只能是读取,并且设置值不能改变。1.默认只写getter{{fullName}}varvm=newVue({el:'#demo',data:{firstName:'Foo',lastName:'Bar'},computed:{fullName:function(){returnthis.firstName+''+this.lastName}}})//其实fullName的完整写法应该是这样的:fullName:{get(){returnthis.firstName+''+this.lastName}}注意:并不是说我们改变了getter中使用的变量,会触发computed的更新,但前提是computed中的值必须是在模板中使用。如果删除{{fullName}},则不会触发get()方法。2.setter的写法,可以设置值varvm=newVue({el:'#demo',data:{firstName:'zhang',lastName:'san'},computed:{fullName:{//getter方法get(){console.log('computedgetter...')returnthis.firstName+''+this.lastName},//setter方法set(newValue){console.log('computedsetter...')varnames=newValue.split('')this.firstName=names[0]this.lastName=names[names.length-1]returnthis.firstName+''+this.lastName}}}})这里如果我们修改fullName的值,会触发setter,同时也会触发getter。注意:不触发setter也会触发getter,它们是相互独立的。我们这里修改fullName来触发getter,因为setter函数中有代码可以改变firstName和lastName的值。这两个值都变了。fullName取决于这两个值,因此它会自动更改。7、导航钩子有哪些类型,如何使用,如何传递数据到下一个点击的路由页面?①globalnavigationguardFrontguardrouter.beforeEach((to,from,next)=>{//dosometing});Posthook(无下一个参数)router.afterEach((to,from)=>{//dosometing});②routeexclusiveguardcontrouter=newVueRouter({routes:[{path:'/file',component:File,beforeEnter:(to,from,next)=>{//做一些事情}}]});顺便看看route中的参数配置:③组件中的Navigationhooks组件中的navigationhook主要分为三种:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave。它们直接在路由组件内部定义beforeRouteEnterdata(){return{pro:'product'}},beforeRouteEnter:(to,from,next)=>{console.log(to)next(vm=>{console.log(vm.pro)})}注意:beforeRouteEnter无法获取到组件实例this,因为在执行guard之前组件实例并没有被创建,我们可以通过给next传递一个回调来访问组件实例。当导航被确认时,会执行这个回调,然后就可以访问组件实例了。只有beforeRouteEnter支持给next传递回调,另外两个不支持,因为剩下的两个钩子可以正常获取组件实例this如何传递routing传递数据到下一个重定向页面呢?答:传递params和queryparamsthis.$router.push({name:"detail",params:{name:'xiaoming',}});接受this.$route.params.namequery传递this.$router。push({path:'/detail',query:{name:"xiaoming"}})Accept//接收到的参数是this.$routethis.$route.query.id,那么query和params有什么区别呢?①params只能使用name导入路由,query可以同时使用name和path(通常是路径)②params类似于post方法,参数不会显示在地址栏query类似于get请求,在页面跳转时,您可以在地址栏中看到请求参数。这有什么区别。刚才提到的路线?先打印出来看看。router.push方法$route是当前router跳转对象,在里面可以获取name、path、query、params等。8、es6特有的类型,常用的操作数组的方法有哪些?es6的主要新特性:①让const都具有块级作用域②箭头函数③模板字符串④解构赋值⑤forof循环⑥导入导出导入导出⑦设置数据结构⑧...展开运算符⑨装饰器@⑩class类继承?async,await?promise?Symbol?ProxyProxy操作数组的常用方法:es5:concat,join,push,pop,shift,unshift,slice,splice,substringandsubstr,sort,reverse,indexOfandlastIndexOf,every,some,filter,map,forEach,reducees6:find,findIndex,fill,copyWithin,Array.from,Array.of,entries,values,key,includes9,vue双向绑定原理?使用Object.defineProperty()劫持每个属性的setter和getter,当数据发生变化时向订阅者发布消息,触发相应的监听回调10.vue-router的实现原理,history和history有什么区别哈希模式?vue-router有两种模式,hash模式和history模式hash模式url中带#的是hash模式,#后面是hash值,它的变化会触发hashchange事件,通过这个事件我们可以知道hash值发生了什么变化.然后我们可以监听hashchange来更新页面的部分内容:window.onhashchange=function(event){console.log(event.oldURL,event.newURL);让hash=location.hash.slice(1);document.body.style.color=hash;}另外,哈希值的变化不会导致浏览器向服务器发送请求。如果浏览器没有发送请求,则不会刷新页面。history模式historyapi可以分为两部分,切换和修改①切换历史状态包括back、forward、go三个方法,对应浏览器的forward、backward、jump操作history.go(-2);//back两次history.go(2);//前进两次history.back();//返回hsitory.forward();//转发②修改历史状态包括pushState、replaceState两个方法,这两个方法接收三个参数:stateObj,title,urlhistory.pushState({color:'red'},'red','red'})window.onpopstate=function(event){console.log(event.state)if(event.state&&event.state.color==='red'){document.body.style.color='red';}}history.back();history.forward();通过pushstate将页面的状态保存在state对象中,当页面的url变回这个url时,可以通过event.state获取state对象,从而恢复页面状态。这里的页面状态就是页面字体颜色,其实就是滚动条的位置,阅读进度,组件开关这些页面状态都可以存储在state中。history的缺点:1:hash模式下,请求中只会包含hash符号前的内容,比如http://www.a12c.com,所以对于...,即使路由没有完全覆盖,也是没有返回404错误。2:在history模式下,前端URL必须和实际向后端发起请求的URL一致。比如http://www.a12c.com/book/a。如果后端缺少对/book/a的路由处理,会返回404错误。过去有127个常用的JS代码片段,每段代码30秒就能看懂。(3)127个常用JS代码片段,每段代码需要30秒看懂(4)[](http://mp.weixin.qq.com/s?__b...