Vue核心知识 谁践踏了优雅 2021-12-22 12:13 247阅读 0赞 ### **VUE实例** ### * vue实例的创建和作用 * vue实例的属性 * vue实例的方法 1. vue实例的创建和作用 new Vue({ render: (h) => h(App) //vue在创建Vue实例时,通过调用render方法来渲染实例的DOM树,也就是这个组件渲染的是App的内容 //vue在调用render方法时,会传入一个createElement函数作为参数,也就是这里的h的实参是createElement函数,然后createElement会以App为参数进行调用 }).$mount(root) //挂载html的root节点下面 2.vue实例的属性 * $data:Vue 实例观察的数据对象。Vue 实例代理了对其 data 对象属性的访问。 * $props:当前组件接收到的 props 对象。Vue 实例代理了对其 props 对象属性的访问。 * $el: Vue实例使用的根 DOM 元素。 * $options: 用于当前 Vue 实例的初始化选项。需要在选项中包含自定义属性时会有用处: new Vue({ customOption: 'foo', created: function () { console.log(this.$options.customOption) // => 'foo' } }) * $parent: 父实例,如果当前实例有的话。 * $root: 当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。 * $chardren: 当前实例的直接子组件。**需要注意 `$children` 并不保证顺序,也不是响应式的。**如果你发现自己正在尝试使用 `$children` 来进行数据绑定,考虑使用一个数组配合 `v-for` 来生成子组件,并且使用 Array 作为真正的来源。 * $slots: 用来访问被[插槽分发][Link 1]的内容。每个[具名插槽][Link 2] 有其相应的属性 (例如:`v-slot:foo` 中的内容将会在 `vm.$slots.foo` 中被找到)。`default` 属性包括了所有没有被包含在具名插槽中的节点,或 `v-slot:default` 的内容。 * $scopedSlots: 用来访问[作用域插槽][Link 3]。对于包括 `默认 slot` 在内的每一个插槽,该对象都包含一个返回相应 VNode 的函数。`vm.$scopedSlots` 在使用[渲染函数][Link 4]开发一个组件时特别有用。 * $refs: 一个对象,持有注册过 [`ref` 特性][ref] 的所有 DOM 元素和组件实例。(帮助我们快速定位这个模板中某一个节点或者组件) * $isServer: 当前 Vue 实例是否运行于服务器。 * $attrs: 包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (`class` 和 `style` 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (`class` 和 `style` 除外),并且可以通过 `v-bind="$attrs"` 传入内部组件——在创建高级别的组件时非常有用。 * $listeners: 包含了父作用域中的 (不含 `.native` 修饰器的) `v-on` 事件监听器。它可以通过 `v-on="$listeners"` 传入内部组件——在创建更高层次的组件时非常有用。 3. vue实例的方法 方法--数据 * $watch: 观察 Vue 实例变化的一个表达式或计算属性函数。回调函数得到的参数为新值和旧值。表达式只接受监督的键路径。对于更复杂的表达式,用一个函数取代。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70][] * $set:这是全局 `Vue.set` 的**别名**。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70 1][] * $delete: 这是全局 `Vue.delete` 的**别名**。 ![20190630105533914.png][] 方法-事件 * $on: 监听当前实例上的自定义事件。事件可以由`vm.$emit`触发。回调函数会接收所有传入事件触发函数的额外参数。 ![20190630120608146.png][] vm.$on('test', function (msg) { console.log(msg) }) vm.$emit('test', 'hi') // => "hi" * $once: 监听一个自定义事件,但是只触发一次,在第一次触发之后移除监听器。 ![20190630122205815.png][] * $off: 移除自定义事件监听器。 1. 如果没有提供参数,则移除所有的事件监听器; 2. 如果只提供了事件,则移除该事件所有的监听器; 3. 如果同时提供了事件与回调,则只移除这个回调的监听器。 ![20190630201814874.png][] * $emit: 触发当前实例上的事件。附加参数都会传给监听器回调。 ![201906302039160.png][] 方法-生命周期 * $mount: 如果 Vue 实例在实例化时没有收到 el 选项,则它处于“未挂载”状态,没有关联的 DOM 元素。可用 `vm.$mount()` 手动地挂载一个未挂载的实例。如果没有提供 `elementOrSelector` 参数,模板将被渲染为文档之外的的元素,并且你必须使用原生 DOM API 把它插入文档中。 这个方法返回实例自身,因而可以链式调用其它实例方法。 ![20190630204418450.png][] 示例: var MyComponent = Vue.extend({ template: '<div>Hello!</div>' }) // 创建并挂载到 #app (会替换 #app) new MyComponent().$mount('#app') // 同上 new MyComponent({ el: '#app' }) // 或者,在文档之外渲染并且随后挂载 var component = new MyComponent().$mount() document.getElementById('app').appendChild(component.$el) * $forceUpdate: 迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。(不建议使用) * $nextTick: 将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 `Vue.nextTick` 一样,不同的是回调的 `this` 自动绑定到调用它的实例上。 示例: new Vue({ // ... methods: { // ... example: function () { // 修改数据 this.message = 'changed' // DOM 还没有更新 this.$nextTick(function () { // DOM 现在更新了 // `this` 绑定到当前实例 this.doSomethingElse() }) } } }) * $destory: 完全销毁一个实例。清理它与其它实例的连接,解绑它的全部指令及事件监听器。触发 `beforeDestroy` 和 `destroyed` 的钩子。 ![20190630215205910.png][] ### Vue组件的生命周期 ### ![70][] 生命周期可以看我的另外一篇文章:[Vue的生命周期][Vue] 需要思考: * 有哪些生命周期方法 * 生命周期方法的调用顺序 * 生命周期中VUE实例有哪些区别 没有暴露出来的,vue内部的渲染函数: * render:就是render function将template编译的过程 * renderError:帮助我们调试项目,当runder function报错的时候就会执行(当前组件的render function报错才报错,不管父组件和子组件的render function报错) new Vue({ render (h) { throw new Error('oops') }, renderError (h, err) { return h('pre', { style: { color: 'red' }}, err.stack) } }).$mount('#app') * errorCaptured:帮助我们收集线上的错误,如果在根组件定义了这个,然后所以的子组件报错都可以捕获到(会向上冒泡,并且正式环境可以使用) ### Vue的数据绑定 ### class的动态绑定和style的动态绑定:[vue中修改css样式和添加CSS样式][vue_css_CSS] ### data、props、propsData、computed和watch使用场景和方法 ### * data **类型**:`Object | Function` **限制**:组件的定义只接受 `function`。 Vue 实例的数据对象。Vue 将会递归将 data 的属性转换为 getter/setter,从而让 data 的属性能够响应数据变化。**对象必须是纯粹的对象 (含有零个或多个的 key/value 对)**:浏览器 API 创建的原生对象,原型上的属性会被忽略。大概来说,data 应该只能是数据 - 不推荐观察拥有状态行为的对象。 一旦观察过,不需要再次在数据对象上添加响应式属性。因此推荐在创建实例之前,就声明所有的根级响应式属性。 实例创建之后,可以通过 `vm.$data` 访问原始数据对象。Vue 实例也代理了 data 对象上所有的属性,因此访问 `vm.a` 等价于访问 `vm.$data.a`。 以 `_` 或 `$` 开头的属性 **不会** 被 Vue 实例代理,因为它们可能和 Vue 内置的属性、API 方法冲突。你可以使用例如 `vm.$data._property` 的方式访问这些属性。 当一个**组件**被定义,`data` 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 `data` 仍然是一个纯粹的对象,则所有的实例将**共享引用**同一个数据对象!通过提供 `data` 函数,每次创建一个新实例后,我们能够调用 `data` 函数,从而返回初始数据的一个全新副本数据对象。 如果需要,可以通过将 `vm.$data` 传入 `JSON.parse(JSON.stringify(...))` 得到深拷贝的原始数据对象。 * props **类型**:`Array<string> | Object` **详细**: props 可以是数组或对象,用于接收来自父组件的数据。props 可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测、自定义验证和设置默认值。 你可以基于对象的语法使用以下选项: 1. `type`: 可以是下列原生构造函数中的一种:`String`、`Number`、`Boolean`、`Array`、`Object`、`Date`、`Function`、`Symbol`、任何自定义构造函数、或上述内容组成的数组。会检查一个 prop 是否是给定的类型,否则抛出警告。Prop 类型的[更多信息在此][Link 5]。 2. `default`: `any` 为该 prop 指定一个默认值。如果该 prop 没有被传入,则换做用这个值。对象或数组的默认值必须从一个工厂函数返回。 3. `required`: `Boolean` 定义该 prop 是否是必填项。在非生产环境中,如果这个值为 truthy 且该 prop 没有被传入的,则一个控制台警告将会被抛出。 4. `validator`: `Function` 自定义验证函数会将该 prop 的值作为唯一的参数代入。在非生产环境下,如果该函数返回一个 falsy 的值 (也就是验证失败),一个控制台警告将会被抛出。你可以在[这里][Link 6]查阅更多 prop 验证的相关信息。 * propsData **类型**:`{ [key: string]: any }` **限制**:只用于 `new` 创建的实例中。 **详细**: 创建实例时传递 props。主要作用是方便测试。 **示例**: var Comp = Vue.extend({ props: ['msg'], template: '<div>{ { msg }}</div>' }) var vm = new Comp({ propsData: { msg: 'hello' } }) * [computed][] **类型**:`{ [key: string]: Function | { get: Function, set: Function } }` **详细**: 计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。 注意如果你为一个计算属性使用了箭头函数,则 `this` 不会指向这个组件的实例,不过你仍然可以将其实例作为函数的第一个参数来访问。 computed: { aDouble: vm => vm.a * 2 } 计算属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。注意,如果某个依赖 (比如非响应式属性) 在该实例范畴之外,则计算属性是**不会**被更新的。 * watch **类型**:`{ [key: string]: string | Function | Object | Array }` **详细**: 一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 `$watch()`,遍历 watch 对象的每一个属性。 **示例**: var vm = new Vue({ data: { a: 1, b: 2, c: 3, d: 4, e: { f: { g: 5 } } }, watch: { a: function (val, oldVal) { console.log('new: %s, old: %s', val, oldVal) }, // 方法名 b: 'someMethod', // 该回调会在任何被侦听的对象的 property 改变时被调用,不论其被嵌套多深 c: { handler: function (val, oldVal) { /* ... */ }, deep: true }, // 该回调将会在侦听开始之后被立即调用 d: { handler: 'someMethod', immediate: true }, e: [ 'handle1', function handle2 (val, oldVal) { /* ... */ }, { handler: function handle3 (val, oldVal) { /* ... */ }, /* ... */ } ], // watch vm.e.f's value: {g: 5} 'e.f': function (val, oldVal) { /* ... */ } } }) vm.a = 2 // => new: 2, old: 1 deep:true对深层监听对象的每一个属性有用 ### Vue的原生指令 ### vue的指令:[vue的指令][vue] * v-text <span v-text="msg"></span> <!-- 和下面的一样 --> <span>{ {msg}}</span> * v-html 更新元素的 `innerHTML` 。**注意:内容按普通 HTML 插入 - 不会作为 Vue 模板进行编译** 。如果试图使用 `v-html` 组合模板,可以重新考虑是否通过使用组件来替代。 * v-show 根据表达式之真假值,切换元素的 `display` CSS 属性。 当条件变化时该指令触发过渡效果。 * v-if 根据表达式的值的真假条件渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建。如果元素是 `<template>` ,将提出它的内容作为条件块。 当条件变化时该指令触发过渡效果。 * v-else **不需要表达式** **限制**:前一兄弟元素必须有 `v-if` 或 `v-else-if`。 **用法**: 为 `v-if` 或者 `v-else-if` 添加“else 块”。 <div v-if="Math.random() > 0.5"> Now you see me </div> <div v-else> Now you don't </div> * v-else-if **限制**:前一兄弟元素必须有 `v-if` 或 `v-else-if`。 **用法**: 表示 `v-if` 的 “else if 块”。可以链式调用。 <div v-if="type === 'A'"> A </div> <div v-else-if="type === 'B'"> B </div> <div v-else-if="type === 'C'"> C </div> <div v-else> Not A/B/C </div> * v-for **预期**:`Array | Object | number | string | Iterable (2.6 新增)` * v-on ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70 2][] **用法**: 绑定事件监听器。事件类型由参数指定。表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略。 用在普通元素上时,只能监听[**原生 DOM 事件**][DOM]。用在自定义元素组件上时,也可以监听子组件触发的**自定义事件**。 在监听原生 DOM 事件时,方法以事件为唯一的参数。如果使用内联语句,语句可以访问一个 `$event` 属性:`v-on:click="handle('ok', $event)"`。 从 `2.4.0` 开始,`v-on` 同样支持不带参数绑定一个事件/监听器键值对的对象。注意当使用对象语法时,是不支持任何修饰器的。 **示例**: <!-- 方法处理器 --> <button v-on:click="doThis"></button> <!-- 动态事件 (2.6.0+) --> <button v-on:[event]="doThis"></button> <!-- 内联语句 --> <button v-on:click="doThat('hello', $event)"></button> <!-- 缩写 --> <button @click="doThis"></button> <!-- 动态事件缩写 (2.6.0+) --> <button @[event]="doThis"></button> <!-- 停止冒泡 --> <button @click.stop="doThis"></button> <!-- 阻止默认行为 --> <button @click.prevent="doThis"></button> <!-- 阻止默认行为,没有表达式 --> <form @submit.prevent></form> <!-- 串联修饰符 --> <button @click.stop.prevent="doThis"></button> <!-- 键修饰符,键别名 --> <input @keyup.enter="onEnter"> <!-- 键修饰符,键代码 --> <input @keyup.13="onEnter"> <!-- 点击回调只会触发一次 --> <button v-on:click.once="doThis"></button> <!-- 对象语法 (2.4.0+) --> <button v-on="{ mousedown: doThis, mouseup: doThat }"></button> * v-bind ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70 3][] **示例: ** <!-- 绑定一个属性 --> <img v-bind:src="imageSrc"> <!-- 动态特性名 (2.6.0+) --> <button v-bind:[key]="value"></button> <!-- 缩写 --> <img :src="imageSrc"> <!-- 动态特性名缩写 (2.6.0+) --> <button :[key]="value"></button> <!-- 内联字符串拼接 --> <img :src="'/path/to/images/' + fileName"> <!-- class 绑定 --> <div :class="{ red: isRed }"></div> <div :class="[classA, classB]"></div> <div :class="[classA, { classB: isB, classC: isC }]"> <!-- style 绑定 --> <div :style="{ fontSize: size + 'px' }"></div> <div :style="[styleObjectA, styleObjectB]"></div> <!-- 绑定一个有属性的对象 --> <div v-bind="{ id: someProp, 'other-attr': otherProp }"></div> <!-- 通过 prop 修饰符绑定 DOM 属性 --> <div v-bind:text-content.prop="text"></div> <!-- prop 绑定。“prop”必须在 my-component 中声明。--> <my-component :prop="someThing"></my-component> <!-- 通过 $props 将父组件的 props 一起传给子组件 --> <child-component v-bind="$props"></child-component> <!-- XLink --> <svg><a :xlink:special="foo"></a></svg> ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70 4][] * v-model ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70 5][] * v-slot * v-pre ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70 6][] * v-cloak * v-once ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70 7][] ### Vue的组件之组件的定义 ### **定义全局组件:** 使用index.js将全部需要全局定义的组件引入: 示例代码: /*所有的自定义全局组件在此注册*/ import Vue from 'vue' function registerEachComponent(item) { Vue.component(item.name,item.component); } function registerComponents(components) { components.map((item)=>{ registerEachComponent(item) }) } let components = [ { name: 'common-layout', component: resolve => require(['./common-layout/common-layout.vue'], resolve) }, { name: 'common-section', component: resolve => require(['./common-section/index.vue'], resolve) }, { name: 'commonInquire', component: resolve => require(['./commonInquire/index.vue'], resolve) }, { name: 'CommonTable', component: resolve => require(['./commonTable/index.vue'], resolve) }, ]; registerComponents(components); 在main.js中引入: /*引入全局注册的组件*/ import './components/global/index.js' **局部组件:** 将定义的组件在需要使用的地方引入并通过components定义 组件定义配置: * props:不应该主动修改props的内容,![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70 8][] * emit:子组件通过emit来让父组件监听子组件的事件 ### Vue的组件之组件的继承 ### extends:将一个能在多个项目中使用的组件通过extends来实现继承,通过覆盖和新增新功能实现对原有组件的使用和拓展 示例: // 假设component是通用的组件 const component2 = { extends: component, data () { text: 1 }, mounted () { console.log('comp2 mounted') } } 注意:如果父组件在mounted定义了事件,然后你在子组件也定义了事件,这样会是父组件的事件先触发,子组件的事件后触发 parent:通过parent可以查看父组件的一些属性和方法(不建议通过parent修改父组件的属性值和方法) ### Vue的组件之自定义双向绑定 ### 使用v-model来实现组件的自定义双向绑定 1.通过在子组件中的props得到值,然后将新的值emit出去,这就实现了双向绑定 2.在内部组件使用model model: { prop: 'value1', event: 'change' }, props: ['value1'] 参考文章:[Vue父子组件如何双向绑定传值][Vue 1] ### Vue的组件之高级属性 ### **slot** 定义组件compOne: <div> <div class="header"> <slot name="header"></slot> </div> <div> <slot name="body"></slot> </div> </div> 使用: <comp-one> <span slot="header">this is header</span> <span slot="body">this is body</span> </comp-one> 文档:[v-slot][] **slot-scope** 使用组件中的属性 定义: <div> <slot value="456" aaa="111"></slot> </div> 使用: <comp-one> <span slot-scope="props">{ {props.value}}{ {props.aaa}}</span> </comp-one> 注意:ref用在组件和原生标签上的区别,在组件上是指向VueCompone,在原生标签上是一个html节点 **provide和inject的使用** Vue.js 不建议在业务中使用这对 API,而是在插件 / 组件库 假设有两个组件: **A.vue** 和 **B.vue**,B 是 A 的子组件。 // A.vue export default { provide: { name: 'Aresn' } } // B.vue export default { inject: ['name'], mounted () { console.log(this.name); // Aresn } } 可以看到,在 A.vue 里,我们设置了一个 **provide: name**,值为 Aresn,它的作用就是将 **name** 这个变量提供给它的所有子组件。而在 B.vue 中,通过 `inject` 注入了从 A 组件中提供的 **name** 变量,那么在组件 B 中,就可以直接通过 **[this.name][]** 访问这个变量了,它的值也是 Aresn。这就是 provide / inject API 最核心的用法。 只要一个组件使用了 `provide` 向下提供数据,那其下所有的子组件都可以通过 `inject` 来注入,不管中间隔了多少代,而且可以注入多个来自不同父级提供的数据。需要注意的是,一旦注入了某个数据,比如上面示例中的 `app`,那这个组件中就不能再声明 `app` 这个数据了,因为它已经被父级占有。 ### Vue的组件之render function ### <comp-one ref="comp"> <span ref="span"> { {value}} </span> </comp-one> 上面的代码通过render函数来实现: render (createElement) { return createElement('comp-one',{ ref: 'comp' },[ createElement('span', { ref: 'span },this.value) ]) } vue将template编译成一个render,形成一个虚拟的DOM 文档:[JSX][] [Link 1]: https://cn.vuejs.org/v2/guide/components.html#%E9%80%9A%E8%BF%87%E6%8F%92%E6%A7%BD%E5%88%86%E5%8F%91%E5%86%85%E5%AE%B9 [Link 2]: https://cn.vuejs.org/v2/guide/components-slots.html#%E5%85%B7%E5%90%8D%E6%8F%92%E6%A7%BD [Link 3]: https://cn.vuejs.org/v2/guide/components-slots.html#%E4%BD%9C%E7%94%A8%E5%9F%9F%E6%8F%92%E6%A7%BD [Link 4]: https://cn.vuejs.org/v2/guide/render-function.html [ref]: https://cn.vuejs.org/v2/api/#ref [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70]: /images/20211220/0ebbdad00fc14f9a82cb63cf5dec73c3.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70 1]: /images/20211220/68f3ce5d7f8c4b97a1a65bd747369218.png [20190630105533914.png]: /images/20211220/49a2ccf82ee64193bd10e65b31ad64a3.png [20190630120608146.png]: /images/20211220/1d09eca9932442ddb8730cab5abf6bb0.png [20190630122205815.png]: /images/20211220/87787640cf904dbaa1180cdb42c2bf42.png [20190630201814874.png]: /images/20211220/cc6cf9a7c7634b3fafa14ed00be3e462.png [201906302039160.png]: /images/20211220/12dba383477d4043b72297e22e67f927.png [20190630204418450.png]: /images/20211220/6996e3e04a4640c9adf084aa56cc2b62.png [20190630215205910.png]: /images/20211220/04a7066a662b4a9ba4a38b7859444a34.png [70]: /images/20211220/8273eefbddaf49b2a4622544ac1fdc9d.png [Vue]: https://blog.csdn.net/wo_921110/article/details/82697933#3.%C2%A0%20Vue%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F [vue_css_CSS]: https://blog.csdn.net/wo_921110/article/details/88662373#vue%E4%B8%AD%E4%BF%AE%E6%94%B9css%E6%A0%B7%E5%BC%8F%E5%92%8C%E6%B7%BB%E5%8A%A0CSS%E6%A0%B7%E5%BC%8F [Link 5]: https://cn.vuejs.org/v2/guide/components-props.html#Prop-%E7%B1%BB%E5%9E%8B [Link 6]: https://cn.vuejs.org/v2/guide/components-props.html#Prop-%E9%AA%8C%E8%AF%81 [computed]: https://cn.vuejs.org/v2/api/#computed [vue]: https://cn.vuejs.org/v2/api/#%E6%8C%87%E4%BB%A4 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70 2]: /images/20211220/42dd217dcf264dbc8623fffe8df600e1.png [DOM]: https://developer.mozilla.org/zh-CN/docs/Web/Events [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70 3]: /images/20211220/fe6c5fdfc6d74165a1481cee6b0e574c.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70 4]: /images/20211220/a0f8c17c1da947b6bd62bdf5b6126a1c.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70 5]: /images/20211220/072c42cea8aa484b9af7733deb27acff.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70 6]: /images/20211220/82d14fc90c2749bf9a42a3f601d2927e.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70 7]: /images/20211220/db342de246f54eca830e38bd8671291d.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dvXzkyMTExMA_size_16_color_FFFFFF_t_70 8]: /images/20211220/e50776445f564f68a2c708ae586c551b.png [Vue 1]: https://juejin.im/post/5b5c2d986fb9a04f897840ac [v-slot]: https://cn.vuejs.org/v2/api/#v-slot [this.name]: https://link.juejin.im/?target=http%3A%2F%2Fthis.name [JSX]: https://cn.vuejs.org/v2/guide/render-function.html#JSX
还没有评论,来说两句吧...