本次让我们体系的认识vue的口试常用标题,无论是给准备口试还是准备跳槽的小同伴,一个学习以及温故知新的版块。这此中到场了我的理解,我只管用白话文和易懂的语言情势举行表明,如果有地方表明的不精确大概禁绝确的环境,还请各人不吝见教。
2022年大环境的不景气,让我们用知识充实自己,面对生存的一次次寻衅与查验,加油!
入门级:
1:什么是mvvm?
MVVM是Model-View-ViewModel的简写,是M-V-VM三部门构成。它本质上是MVC的改进版本,MVVM就是将此中的View的状态和运动抽象化,此中ViewModel将视图 UI 和业务逻辑分开,它可以取出 Model 的数据同时资助处置惩罚 View 中由于必要展示内容而涉及的业务逻辑。
MVVM接纳双向数据绑定,view中数据变革将主动反映到viewmodel上,反之,model中数据变革也将会主动展示在页面上。把Model和View关联起来的就是ViewModel。ViewModel负责把Model的数据同步到View表现出来,还负责把View的修改同步回Model。
让我们开发职员可以专注于业务逻辑方面(ViewModel),对于数据的绑定与展示(主动更新dom),不必要过多的dom操作。可以理解为数据(medel)驱动UI(view),而UI(view)的改变也会影响数据(medel)。他们之间就是靠ViewModel来实现。
因此开发者只必要关注业务逻辑,不必要手动操作 DOM,也不必要关注数据状态的同步问题,这些都由 MVVM 同一管理。
2:为什么要用vue?
1.捏造dom:dom操作黑白常的斲丧性能的,不再使用原生的dom操作节点的方式,模仿一个捏造dom树,运用deff算法,只更新修改的dom节点,极大的开释了dom操作。
2.视图,数据,布局的分离:使数据的更改更为简朴,不必要举行逻辑代码的修改,只必要操作数据就能完成干系操作(mvvm)
3.组件化:把一个单页应用中的各个模块拆分到一个个单独的组件中,各个组件有自己的运动逻辑以及自己的样式,相互不干扰。便于开发,以及后期维护。相同组件的公用也大大节省了开发本钱。
3:vue的生命周期(11个钩子函数)
1.beforeCreate(创建前):在今生命周期函数实行的时间,data和methods中的数据还没有初始化。
2.created(创建后):在这个生命周期中,data 和 methods 都已经被初始化好了,可以访问到data中的数据以及methods的方法。
3.beforeMount(载入前):在今生命周期函数实行的时间,模板已经在内存中编译好了,但是尚未挂载到页面中去,此时页面还是旧的。
4.mounted(载入后):此时页面和内存中是最新数据,dom树创建,此时才可以操作dom节点。
5.beforeUpdate(更新前):顾名思义,这个时间页面正准备举行更新,只是还未开始更新动作,以是页面中的数据还是旧的,但是data中的数据已经是新的,只是页面并未和最新数据同步。
6.Updated(更新后):此时页面表现数据和最新的 data 数据同步。
7.beforeDestroy(烧毁前):组件烧毁前的钩子函数,此时实例上的data,methods,以及过滤器等都处于可用状态。我们一样平常可以在这个钩子内扫除当前组件的定时器(clearInterval() )。
8.destroyed(烧毁后):此时组件已经被完全烧毁,实例中的全部的数据、方法、属性、过滤器…等都已经不可用了
// 以上8个生命周期钩子函数是我们常用的钩子函数,接下来的3个钩子函数可以在特定的时间使用,方便我们理解
9.activated(组件激活时):在使用被keep-alive缓存的组件时,进入函数。如果一个子页面大概一个组件被keep-alive包罗,那么当这个页面或组件第一次时会走一次完备的生命周期,当此组件无法被烧毁。等重复使用的时间,会从缓存内里直接调出,此时组件不在实行前4个生命周期钩子(由于它并没有被烧毁,不必要重新创建)。取而代之的是进入activated钩子函数。表现该页面或组件被激活。
10.deactivated(组件未激活时):实例没有被激活时(同9)。
11.errorCaptured(错误调用):当捕捉一个来自后代组件的错误时被调用
留意:有很多口试会问父子组件创建烧毁的生命周期顺序:
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
即父组件走到beforeMount 后,开始走完子组件的完备生命周期,然后再走父组件mounted
如许理解:
1.有父才有子,以是一开始是父组件先创建实例。
2.mounted自己就是挂在到页面上的钩子,以是必须要等全部的子组件完成后再一起挂载到页面中。(既然是父,固然要包罗全部的子)
4:watch、computed 和 methods 的区别
- methods 方法:组件内部的业务逻辑方法的聚集
- computed 盘算属性:依靠已有的变量来盘算一个目标变量,比方根据data的变量来盘算新的变量,用来格式化。大概引用store,...mapState的语法糖引用state。(computed是有缓存的,留意不能举行异步操作)
- watch 监听:监听某一个变量的变革,而且实行相应的回调函数(watch没有缓存,目标变革一次实行一次,可以举行异步操作)
很多口试官喜欢问computed 和watch的区别,这里请多加理解
5.Vue.js的特点
- 简洁:页面由HTML模板+Json数据+Vue实例构成,布局简朴易懂
- 数据驱动:主动盘算属性和追踪依靠的模板表达式
- 组件化:用组件来构造页面,可复用,维护方便
- 轻量:代码量小,不依靠其他库
- 快速:精确有效批量 DOM 更新
- 模板友爱:可通过 npm,bower 等多种方式安装,很轻易融入
6:插槽的理解
插槽用于决定将所携带的内容,插入到子组件指定的某个位置,但内容必须在父组件中子组件的标签内界说,在子组件中用标签吸取。slot 是组件内部的占位符。即组件编写时留给组件使用者的一个插入口。使用者可以在此编写自己的html格式以及样式,插入的位置由编写者订定
7.Vue组件之间传参
1.父传子:
- 父组件通过props方式转达数据
- 父组件也可以直接选择子节点的情势选中子组件的实例
this.$refs.nodeName // refs是根据组件名字来取的相应组件的属性this.$children[2] // 返回一个数组(使用几率小,一样平常不如许调用)2.子传父:
- 子组件用$emit方法,触发父组件的监听
- this.$parnet获取当前组件的父组件实例
3.兄弟组件之间(这里写的是兄弟组件之间,现实上是全部组件之间都可以,包罗父子):
- 用一个事故总线,evenBus。新建一个空的vue实例作事故总线(为了方便调用一样平常绑定到vue原型),然后用$on监听事故,用$emit触发事故。
this.$eventBus.$on('sayName',(data)=>{ console.log(data)}) // 监听事故总线中sayName方法this.$eventBus.$emit('sayName',data)具体教学请移步到:https://www.jianshu.com/p/267e17c59d32
- Vuex:Vuex 是一个专门为 Vue.js 应用程序开发的状态管理模式。在下面的复习中我们会具体教学到
4.欣赏器本地缓存,比方localStorage,sessionStorage
8.vue 组件中的 data 为什么是一个函数
data 是一个函数时,每个组件实例都有自己的作用域,每个实例相互独立,不会相互影响。Object 是引用数据范例,如果不消 function 返回,每个组件的 data 都是内存的同一个所在(储存的是所在,指针,此处可以复习浅拷贝和深拷贝),一个数据改变了其他也改变了。
理解就是运用了function的函数作用域让他酿成局部作用域,如许每复用一次组件,就会返回一份新的 data,类似于给每个组件实例创建一个私有的数据空间
9.路由懒加载(首页加载优化)
在单页应用中,如果没有应用懒加载,运用 webpack 打包后的文件将会非常的大,造成进入首页时,必要加载的内容过多,延时过长,倒霉于用户体验,而运用懒加载则可以将页面举行分别,必要的时间加载页面,可以有效的分担首页所负担的加载压力,镌汰首页加载用时
原理:vue 异步组件技能:异步加载,vue-router 设置路由 , 使用 vue 的异步组件技能 , 实现按需加载
import Vue from 'vue'import Router from 'vue-router'// import HelloWorld from '@/components/HelloWorld'Vue.use(Router)export default new Router({ routes: [// {// path: '/',// name: 'HelloWorld',// component: HelloWorld// } { path: '/', name: 'HelloWorld', component: () => import('@/components/HelloWorld.vue') } ]})10:请说出 vue.cli 项目中 src 目次每个文件夹和文件的用法`
assets 文件夹是放静态资源;
components 是放组件;
router 是界说路由干系的设置;
store vuex模块;
view 视图;
app.vue 是一个应用主组件;
main.js 是入口文件
11.Vue 中 key 值的作用
当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“当场复用”计谋。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简朴复用此处每个元素,而且确保它在特定索引下表现已被渲染过的每个元素。key 的作用重要是为了高效的更新捏造 DOM。
key 是为 Vue 中 vnode 的唯一标志,通过这个 key,我们的 diff 操作可以更精确、更快速
12:vue 的指令
- v-bind:给元素绑定属性,简写为:
- v-on:给元素绑定事故,简写为@
- v-html:给元素绑定命据,且该指令可以分析 html 标签
- v-text:给元素绑定命据,不分析标签
- v-model:数据双向绑定
- v-for:遍历数组
- v-show:条件渲问鼎令,将不符合条件的数据潜伏(display:none)
- v-if:条件渲问鼎令,动态在 DOM 内添加或删除 DOM 元素(无节点)
- v-else:条件渲问鼎令,必须跟 v-if 成对使用
- v-else-if:判定多层条件,必须跟 v-if 成对使用
- v-cloak:办理插值闪耀问题
- v-once:只渲染元素或组件一次
- v-pre:跳过这个元素以及子元素的编译过程,以此来加快整个项目标编译速率
13.v-for 与 v-if
由于v-for的优先级高于v-if,势必会先遍历数组,然后再判定是否表现,如许就会影响速率,尤其是只必要渲染很小一部门的时间,渲染了很多无用的节点,增长很多无用的dom操作,发起用computed先把必要的数组格式化出来
<div v-for="item in list"> {{item}}</div>computed() { list() { return [1, 2, 3, 4, 5, 6, 7].filter(item => item !== 3) } }14.Vue怎么兼容IE
使用 babel-polyfill 插件省省吧,2022年6月16日起ie都退役了
15.Vue 怎么重置 data
在很多环境下我们会碰到初始化data的时间,好比在调用element的dialog组件时(组件是v-show控制,会生存之前的状态)
Object.assign(this.$data, this.$options.data()) // 初始化data16.route 和 router
- route 是“路由信息对象”,包罗 path,params,hash,query,fullPath,matched,name 等路由信息参数。
route查询修改当前路由的对象
- router 是“路由实例对象”,包罗了路由的跳转方法(push、go),钩子函数等。
router获取当前路由实例,调用方法
17.Vue的修饰符有哪些?
常用修饰符:
- .stop 阻止事故继续传播
- .prevent 阻止标签默认运动
- .capture 使用事故捕捉模式,即元素自身触发的事故先在此到处置惩罚,然后才交由内部元素举行处置惩罚
- .self 只当在 event.target 是当前元素自身时触发处置惩罚函数
- .once 事故将只会触发一次
- .passive 告诉欣赏器你不想阻止事故的默认运动
- .right 使用鼠标右键触发事故@click.right
中级:
1.捏造 DOM 原理
捏造 DOM,实在就是用对象的方式取代真实的DOM操作,把真实的DOM操作放在内存当中,在内存中的对象里做模仿操作。当页面打开时欣赏器会分析 HTML 元素,构建一颗 DOM树,将状态全部生存起来,在内存当中模仿我们真实的 DOM操作,操作完后又会生成一颗 dom 树,两颗DOM树举行比力,根据 diff 算法比力两颗 DOM树差异的地方,只渲染一次差异的地方。
用diff算法把捏造DOM和真实DOM比力,找出差异的地方,页面只渲染差异的地方
2:nextTick 的理解
Vue 是异步修改 DOM 的,而且不鼓励开发者直接打仗 DOM,但是偶然间必要必须对数据更改后的 DOM 元素做相应的处置惩罚,但是获取到的 DOM 数据并不是更改后的数据,这时间就必要 this.$nextTick();
很常见一个例子,在数据变革后马上要使用ref举行节点操作,由于vue是异步修改dom的,以是在数据变革后大概没有找到必要操作的dom,故而报错
<div ref="mydom" v-if="isShow"></div> methods() { this.isShow = true; this.$nextTick(()=>{ this.$refs.mydom.play() // 等待最新的dom更新了之后的回调,此时已经有了mydom节点,可以对其举行dom操作 }) },3.不必要相应式的数据应该怎么处置惩罚?
在我们的Vue开发中,会有一些数据,从始至终都未曾改变过,这种死数据,既然不改变,那也就不必要对他做相应式处置惩罚了,否则只会做一些无勤奋斲丧性能,好比一些写死的下拉框,写死的表格数据,这些数据量大的死数据,如果都举行相应式处置惩罚,那会斲丧大量性能。
// 方法一:将数据界说在return 之外(初始化时期只会对data内的数据绑定getter和setter)data () { this.list1 = { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx } this.list2 = { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx } this.list3 = { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx } this.list4 = { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx } this.list5 = { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx } return {} } // 方法二:Object.freeze()data () { return { list1: Object.freeze({xxxxxxxxxxxxxxxxxxxxxxxx}), list2: Object.freeze({xxxxxxxxxxxxxxxxxxxxxxxx}), list3: Object.freeze({xxxxxxxxxxxxxxxxxxxxxxxx}), list4: Object.freeze({xxxxxxxxxxxxxxxxxxxxxxxx}), list5: Object.freeze({xxxxxxxxxxxxxxxxxxxxxxxx}), } }4.vue 中的双向绑定原理
概念:双向绑定是vue的一个核心功能,所谓双向绑定就是当视图发生改变的时间转达给VM(ViewModel ),让数据得到更新,当数据发生改变的时间传给VM(ViewModel ),使得视图发生变革。
那么vue怎么做到的呢?
observer(观察者),挟制监听全部属性,什么意思呢?
vue.js是接纳数据挟制结合发布者-订阅者模式的方式,通过Object.defineProperty()来挟制各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。
先简朴的实现一个js的双向数据绑定来认识一下Object.defineProperty()方法
<input type="text" id="in"/> 输入的值为:<span id="out"></span> <script> var int = document.getElementById('in'); var out = document.getElementById('out'); var obj = {}; Object.defineProperty(obj, 'msg', { enumerable: true, configurable: true, set (newVal) { out.innerHTML = newVal; } }) int.addEventListener('input', function(e) { obj.msg = e.target.value; })/*通过给in输入框添加事故监听input来触发obj对象的set方法,而set在修改了访问器属性的同时,也修改了dom样式,改变了span标签内的文本。*/5.vue3的相识
大抵有三个点:
1.关于提出的新 API setup()函数。
2.对于 Typescript 的支持。
3.末了说了关于更换 Object.defineProperty 为 Proxy 的支持。具体说了下关于 Proxy 取代带来的性能上的提升,由于传统的原型链拦截的方法,无法检测对象及数组的一些更新操作,但使用 Proxy 又带来了欣赏器兼容问题。
6.vue-cli 替我们做了哪些工作
vue-cli 是基于 Vue.js 举行快速开发的完团体系,也可以理解成是很多 npm 包的聚集。
vue-cli 完成的功能:
- .vue 文件 --> .js 文件
- ES6 语法 --> ES5 语法
- Sass,Less,Stylus --> CSS
- 对 jpg,png,font 等静态资源的处置惩罚
- 热更新
- 界说环境变量,区分 dev 和 production 模式
- 如果开发者必要增补或修改默认设置,必要在 package.json 同级下新建一个 vue.config.js 文件
7.axios拦截器
相应拦截
axios.interceptors.response.use((response)=>{ //对相应数据做点什么 return response.data},(error)=>{ //对错误相应做点什么 return Promise.reject(error)})哀求拦截
axios.interceptors.request.use((config)=>{ //在发送哀求之前做些什么 return config},(error)=>{ //对哀求错误做些什么 return Promise.reject(error)})14:vue-router 路由钩子函数是什么 实行顺序是什么
路由钩子的实行流程, 钩子函数种类有:全局保卫、路由保卫、组件保卫
完备的导航分析流程:
- 导航被触发。
- 在失活的组件里调用 beforeRouteLeave 保卫。
- 调用全局的 beforeEach 保卫。
- 在重用的组件里调用 beforeRouteUpdate 保卫 (2.2+)。
- 在路由设置里调用 beforeEnter。
- 分析异步路由组件。
- 在被激活的组件里调用 beforeRouteEnter。
- 调用全局的 beforeResolve 保卫 (2.5+)。
- 导航被确认。
- 调用全局的 afterEach 钩子。
- 触发 DOM 更新。
- 调用 beforeRouteEnter 保卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入
1.全局保卫:
import Vue from 'vue'import VueRouter from 'vue-router'import Home from '../views/Home.vue'Vue.use(VueRouter)const routes = [ { path: '/', redirect: '/home' }, { path: '/home', name: 'Home', component: Home }, { path: '/about', name: 'About', component: () => import('../views/About.vue') }]const router = new VueRouter({ routes})// 跳转路由之前router.beforeEach((to,from,next)=>{ // .............. next()})// 跳转路由之后router.afterEach((to,from,next)=>{ // .............. next()})export default router2.单个路由独享的保卫
const routes = [ { path: '/about', name: 'About', component: () => import('../views/About.vue'), beforeEach(to,from,next)=>{ // .............. next() }) }]3.组件级保卫(beforeRouteEnter)组件级的保卫写在页面组件中,与data,methods同级。如图
export default { data(){ return{} }, created:{}, components: {}, methods:{}, beforeRouteEnter(to,from,next){ // .............. next() }};15.Vuex的理解重点
界说:Vuex是一个专为Vue.js应用程序开发的状态管理模式。它接纳会合式储存管理应用的全部组件的状态,并以相应的规则包管状态以一种可预测的方式发生变革。
使用场景:必要构建一个中大型单页应用,您很大概会思量怎样更好的在组件外部管理状态,Vuex将会成为自然而然的选择。
优点:当你在state中界说了一个数据之后,可以在所在项目中的任何一个组件里举行获取、举行修改、而且你的修改可以得到全局的相应变动。(全局变量理解方式)
重要包罗以下几个模块:
- State:界说了应用状态的数据布局,可以在这里设置默认的初始状态。
- Getter:答应组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部盘算属性。
- Mutation:是唯一更改 store 中状态的方法,且必须是同步函数。
- Action:用于提交 mutation,而不是直接变动状态,可以包罗恣意异步操作。
- Module:答应将单一的 Store 拆分为多个 store 且同时生存在单一的状态树中。大型项目时可以把store也拆分多个模块,每个store包罗自己的state,getter,mutation,action
Vuex的运行机制:Vuex提供数据(state)来驱动试图(vue components),通过dispath派发actions,在此中可以做一些异步的操作,然后通过commit来提交mutations,末了mutations来更改state。
import Vuex from 'vuex';import Vue from 'vue';Vue.use(Vuex);const store = new Vuex.Store({ state: { }, mutations: { increment(state, val) { console.log(state); }, }, actions: { addCount(context) { console.log(context); // 可以包罗异步操作 // context 是一个与 store 实例具有相同方法和属性的 context 对象 }, }, getters: { doneTodos(state) { return state; } }});export default store;16:Vuex 页面革新数据丢失怎么办理
我们都知道,vuex是作为一个公共的状态管理聚集,但是他是存储在内存中的,在欣赏器中,革新页面会清空一次内存。显然对于一些公共的状态,我们是不盼望革新清空的,这里就有了vuex数据恒久化的一个问题
必要做 vuex 数据恒久化 一样平常使用本地存储的方案来生存数据 可以自己设计存储方案 也可以使用第三方插件
1.推荐使用 vuex-persist 插件,它就是为 Vuex 恒久化存储而生的一个插件。不必要你手动存取 storage ,而是直接将状态生存至 cookie 大概 localStorage 中
(注现实开发中使用sessionStorage来生存,缘故原由是localStorage在同一欣赏器中多个账户登录生存到localStroage会出问题)
2.大概手动把vuex数据存储在sessionStorage中
window.addEventListener('beforeunload', e => { console.log('页面举行了革新大概关闭')// 生存vuex操作})// 留意要卸载监听事故window.removeEventListener('beforeunload', e =>{})17.你都用过哪些vue性能优化
这里只枚举针对 Vue 的性能优化 整个项目标性能优化是一个大工程 可以另写一篇性能优化的文章了
1.镌汰http哀求
2.对象层级不要过深,否则性能就会差
3.不必要相应式的数据不要放到 data的return 中(可以用 Object.freeze() 冻结数据)
4.v-if 和 v-show 区分使用场景
5.computed 和 watch 区分使用场景
6.v-for 遍历必须加 key,key 最好是 id 值,且制止同时使用 v-if
7.大数据列表和表格性能优化-捏造列表/捏造表格
8.防止内部走漏,组件烧毁后把全局变量和事故烧毁
9.图片懒加载
10.路由懒加载(首页加载优化)
11.第三方插件的按需引入
12.得当接纳 keep-alive 缓存组件
13.防抖、节流运用
14.服务端渲染 SSR or 预渲染
15.插件引入只管不要全局引入(首页加载优化)
18.形貌下vue从初始化页面=>修改数据=>革新页面 UI 过程?
1.当 Vue 进入初始化阶段时,一方面 Vue 会遍历 data 中的属性,并用 Object.defineProperty 将它转化成 getter/setterd 的情势,实现数据挟制;
2.另一方面,Vue 的指令编译器 Compiler 对元素节点的各个指令举行分析,初始化视图,并订阅 Watcher 来更新视图,此时 Watcher 会将自己添加到消息订阅器 Dep 中,此时初始化完毕。
3.当数据发生变革时,触发 Observer 中 setter 方法,立即调用 Dep.notify( ),Dep 这个数组开始遍历全部的订阅者,并调用其 update 方法,Vue 内部再通过 diff 算法,patch 相应的更新完成对订阅者视图的改变。
19.给对象添加了新的属性,data改变了,但是页面上没有改变,为什么?
这里用到$set
缘故原由:vue在创建实例的时间把data深度遍历全部属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。让 Vue 追踪依靠,在属性被访问和修改时关照变革。以是属性必须在 data 对象上存在才气让 Vue 转换它,如许才气让它是相应的。
vue.$set 是能让 vue 知道你添加了属性, 它会给你做处置惩罚
change(){ this.$set(this.list,1,0);}进阶层
1.说一下Vue.mixin
在日常的开发中,我们常常会碰到在差异的组件中常常会必要用到一些相同大概相似的代码,这些代码的功能相对独立,可以通过 Vue 的 mixin 功能抽离公共的业务逻辑,原理类似“对象的继续”,当组件初始化时会调用 mergeOptions 方法举行归并,接纳计谋模式针对差异的属性举行归并。当组件和混入对象含有同名选项时,这些选项将以得当的方式举行“归并”
具体请点击https://www.jianshu.com/p/772d67305f98
2.keep-alive 使用场景和原理
keep-alive 是 Vue 内置的一个组件,可以实现组件缓存,当组件切换时不会对当前组件举行卸载。
- 常用的两个属性 include/exclude,答应组件有条件的举行缓存。
- 两个生命周期 activated/deactivated,用来得知当前组件是否处于活泼状态。
- keep-alive 的中还运用了 LRU(最近最少使用) 算法,选择最近最久未使用的组件予以镌汰
3.函数式组件使用场景和原理
1.函数式组件必要在声明组件是指定 functional:true
2.不必要实例化,以是没有this,this通过render函数的第二个参数context来取代
3.没有生命周期钩子函数,不能使用盘算属性,watch
4.不能通过$emit对外袒露事故,调用事故只能通过context.listeners.click的方式调用外部传入的事故
5.由于函数式组件是没有实例化的,以是在外部通过ref去引用组件时,现实引用的是HTMLElement
6.函数式组件的props可以不消表现声明,以是没有在props内里声明的属性都会被主动隐式分析为prop,而平凡组件全部未声明的属性都分析到$attrs内里,并主动挂载到组件根元素上面(可以通过inheritAttrs属性克制) |