2020大厂前端面试之vue专题(三)

Miette ·
更新时间:2024-11-14
· 678 次阅读

21.v-model中的实现原理及如何自定义v-model v-model 可以看成是 value+input方法 的语法糖 input v-model checkbox v-model select v-model
组件的v-model 就是value+input的语法糖 理解: 组件的 v-model 是 value+input方法 的语法糖 可以自己重新定义 v-model 的含义 Vue.component('el-checkbox',{ template:``, model:{ prop:'check', // 更改默认的value的名字 event:'change' // 更改默认的方法名 }, props: { check: Boolean }, }) 原理: 会将组件的 v-model 默认转化成value+input const VueTemplateCompiler = require('vue-template-compiler'); const ele = VueTemplateCompiler.compile(''); // with(this) { // return _c('el-checkbox', { // model: { // value: (check), // callback: function ($$v) { // check = $$v // }, // expression: "check" // } // }) // } function transformModel (options, data: any) { const prop = (options.model && options.model.prop) || 'value' const event = (options.model && options.model.event) || 'input' ;(data.attrs || (data.attrs = {}))[prop] = data.model.value const on = data.on || (data.on = {}) const existing = on[event] const callback = data.model.callback if (isDef(existing)) { if ( Array.isArray(existing) ? existing.indexOf(callback) === -1 : existing !== callback ) { on[event] = [callback].concat(existing) } } else { on[event] = callback } } 原生的 v-model ,会根据标签的不同生成不同的事件和属性 const VueTemplateCompiler = require('vue-template-compiler'); const ele = VueTemplateCompiler.compile(''); /** with(this) { return _c('input', { directives: [{ name: "model", rawName: "v-model", value: (value), expression: "value" }], domProps: { "value": (value) }, on: { "input": function ($event) { if ($event.target.composing) return; value = $event.target.value } } }) } */

编译时:不同的标签解析出的内容不一样

if (el.component) { genComponentModel(el, value, modifiers) // component v-model doesn't need extra runtime return false } else if (tag === 'select') { genSelect(el, value, modifiers) } else if (tag === 'input' && type === 'checkbox') { genCheckboxModel(el, value, modifiers) } else if (tag === 'input' && type === 'radio') { genRadioModel(el, value, modifiers) } else if (tag === 'input' || tag === 'textarea') { genDefaultModel(el, value, modifiers) } else if (!config.isReservedTag(tag)) { genComponentModel(el, value, modifiers) // component v-model doesn't need extra runtime return false }

运行时:会对元素处理一些关于输入法的问题

inserted (el, binding, vnode, oldVnode) { if (vnode.tag === 'select') { // #6903 if (oldVnode.elm && !oldVnode.elm._vOptions) { mergeVNodeHook(vnode, 'postpatch', () => { directive.componentUpdated(el, binding, vnode) }) } else { setSelected(el, binding, vnode.context) } el._vOptions = [].map.call(el.options, getValue) } else if (vnode.tag === 'textarea' || isTextInputType(el.type)) { el._vModifiers = binding.modifiers if (!binding.modifiers.lazy) { el.addEventListener('compositionstart', onCompositionStart) el.addEventListener('compositionend', onCompositionEnd) // Safari < 10.2 & UIWebView doesn't fire compositionend when // switching focus before confirming composition choice // this also fixes the issue where some browsers e.g. iOS Chrome // fires "change" instead of "input" on autocomplete. el.addEventListener('change', onCompositionEnd) /* istanbul ignore if */ if (isIE9) { el.vmodel = true }}}} 22.Vue中v-html会导致哪些问题? 理解: 可能会导致 xss 攻击 v-html 会替换掉标签内部的子元素 原理: let template = require('vue-template-compiler'); let r = template.compile(`<div v-html="'hello'">
`) // with(this){return _c('div',{domProps: {"innerHTML":_s('hello')}})} console.log(r.render); // _c 定义在core/instance/render.js // _s 定义在core/instance/render-helpers/index,js if (key === 'textContent' || key === 'innerHTML') { if (vnode.children) vnode.children.length = 0 if (cur === oldProps[key]) continue // #6601 work around Chrome version <= 55 bug where single textNode // replaced by innerHTML/textContent retains its parentNode property if (elm.childNodes.length === 1) { elm.removeChild(elm.childNodes[0]) } } 23. Vue父子组件生命周期调用顺序 加载渲染过程 父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted 子组件更新过程 父beforeUpdate->子beforeUpdate->子updated->父updated 父组件更新过程 父beforeUpdate->父updated 销毁过程 父beforeDestroy->子beforeDestroy->子destroyed->父destroyed 理解: 组件的调用顺序都是先父后子,渲染完成的顺序肯定是先子后父 组件的销毁操作是先父后子,销毁完成的顺序是先子后父 原理:

原创文章 38获赞 60访问量 1万+ 关注 私信 展开阅读全文
作者:寂寞花如雪



VUE 前端面试 面试 前端

需要 登录 后方可回复, 如果你还没有账号请 注册新账号