Vue——组件
(1)组件是可复用的 Vue 实例,且带有一个名字;它们与 new Vue
接收相同的选项,但是像 el
这样根实例特有的选项除外。
(2)每用一次组件,就会有一个它的新实例被创建。
(3)一个组件的 data
选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝。
(4)一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。
(5)每个组件必须只有一个根元素every component must have a single root element 。
(6)v-on
监听子组件实例的任意事件。子组件可以通过调用内建的 $emit
方法 ,并传入事件名称来触发一个事件,$emit第二个参数可以抛出数据。
(7)自定义事件也可以用于创建支持 v-model
的自定义输入组件。
(8)<slot>插槽可以实现自定义组件接收父组件传递过来的内容。
(9) Vue 的 <component>
元素加一个特殊的 is
attribute 来实现不同组件之间进行动态切换。
(10)在HTML的某些元素,例如<table>,放置自定义组件时会导致自定义组件被作为无效的内容提升到外部,并导致最终渲染结果出错,此时,可以借助is属性来解决该问题;不过在以下三种情况中将自定义组件放置在例如<table>的元素中时就不会发生上述现象:
- 字符串 (例如:
template: '...'
) - 单文件组件 (
.vue
) <script type="text/x-template">
(11)自定义组件的命名方式:
-
使用 kebab-case:my-component-name
-
使用 PascalCase:MyComponentName
使用时可以<my-component-name>或者<MyComponentName>,不过在DOM中使用时只有<my-component-name>是有效的,所以还是建议采用my-component-name的方式使用。
(12)自定义组件的注册方式:
- 全局注册:Vue.component实现全局注册,全局注册的行为必须在根 Vue 实例 (通过
new Vue
) 创建之前发生。 - 局部注册:
components
选项实现局部注册,对于components
对象中的每个属性来说,其属性名就是自定义元素的名字,其属性值就是这个组件的选项对象。
(13)Prop的大小写
HTML 中的 attribute 名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名;如果使用字符串模板,那么这个限制就不存在了。
(14)如果你想要将一个对象的所有属性都作为 prop 传入,你可以使用不带参数的 v-bind
(取代 v-bind:prop-name
)。
(15)在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态。
(16)`null` 和 `undefined` 会通过任何类型验证;在自定义组件时prop类型为对象或数组时,其默认值必须从一个工厂函数获取。
(17)那些 prop 会在一个组件实例创建之前进行验证,所以实例的属性 (如 data
、computed
等) 在 default
或 validator
函数中是不可用的。
(18)对于绝大多数 attribute 来说,从外部提供给组件的值会替换掉组件内部设置好的值;class
和 style
attribute 会稍微智能一些,即两边的值会被合并起来,从而得到最终的值。
(19)不希望自定义组件的根元素继承 attribute,可以在自定义组件的选项中设置 inheritAttrs: false;
inheritAttrs: false
选项不会影响style
和class
的绑定;这个模式允许在使用基础组件的时候更像是使用原始的HTML元素,而不会担心哪个元素是真正的根元素。
(20)不同于组件和 prop,事件名不存在任何自动化的大小写转换,事件名不会被用作一个 JavaScript 变量名或属性名,所以就没有理由使用 camelCase 或 PascalCase 了。
(21)v-on
事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的),所以 v-on:myEvent
将会变成 v-on:myevent
——导致 myEvent
不可能被监听到。因此,推荐始终使用 kebab-case 的事件名。
(22)一个组件上的 v-model
默认会利用名为 value
的 prop 和名为 input
的事件,model
选项可以用来避免某些冲突,在model定义的prop仍然需要在props中定义好。
(23)带有 .sync
修饰符的 v-bind
不能和表达式一起使用 (例如 v-bind:id.sync=”person.id + ‘!’”
是无效的)。取而代之的是,你只能提供你想要绑定的属性名,类似 v-model
。
(24)当用一个对象同时设置多个 prop 的时候,可以将.sync
修饰符和 v-bind
配合使用;将 v-bind.sync
用在一个字面量的对象上,例如 v-bind.sync=”{ id: person.id }”
,是无法正常工作的,因为在解析一个像这样的复杂表达式的时候,有很多边缘情况需要考虑。
(25)<keep-alive>
元素将其动态组件包裹起来,这样失活的组件将会被缓存;<keep-alive>
要求被切换到的组件都有自己的名字,不论是通过组件的 name
选项还是局部/全局注册。
(26)Vue 允许以一个工厂函数的方式定义组件,这个工厂函数会异步解析定义的组件。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。
- 将异步组件和 webpack 的 code-splitting 功能一起配合使用。
-
Vue.component('async-webpack-example', function (resolve) { // 这个特殊的 `require` 语法将会告诉 webpack // 自动将你的构建代码切割成多个包,这些包 // 会通过 Ajax 请求加载 require(['./my-async-component'], resolve) })
-
可以在工厂函数中返回一个 Promise,所以把 webpack 2 和 ES2015 语法加在一起,可以写成这样: Vue.component( 'async-webpack-example', // 这个 `import` 函数会返回一个 `Promise` 对象。 () => import('./my-async-component') )
-
当使用局部注册的时候,也可以直接提供一个返回 Promise 的函数: new Vue({ // ... components: { 'my-component': () => import('./my-async-component') } })
(27)在每个 new Vue
实例的子组件中,其根实例可以通过 $root
属性进行访问;所有的子组件都可以将这个实例作为一个全局 store 来访问或使用;在绝大多数情况下,强烈推荐使用 Vuex 来管理应用的状态。
(28)$refs
只会在组件渲染完成之后生效,并且它们不是响应式的。这仅作为一个用于直接操作子组件的“逃生舱”——应该避免在模板或计算属性中访问 $refs
。
(29)依赖注入:provide
选项允许父组件指定其想要提供给后代组件的数据/方法,而在任何后代组件里,都可以使用 inject
选项来接收指定想要添加在这个实例上的属性;依赖注入还是有负面影响的,它将应用程序中的组件与它们当前的组织方式耦合起来,使重构变得更加困难,同时所提供的属性是非响应式的。
(30)程序化的事件侦听器: $emit,$on,$once, $off。
(31)组件是可以在它们自己的模板中调用自身的,不过它们只能通过 name
选项来做这件事,要注意防止无限循环,否则会导致“max stack size exceeded”错误。
(32)内联模板
- 当
inline-template
这个特殊的 attribute 出现在一个子组件上时,这个组件将会使用其里面的内容作为模板,而不是将其作为被分发的内容。 - 内联模板需要定义在 Vue 所属的 DOM 元素内。
inline-template
会让模板的作用域变得更加难以理解。
(33)渲染普通的 HTML 元素在 Vue 中是非常快速的,但有的时候你可能有一个组件,这个组件包含了大量静态内容。在这种情况下,你可以在根元素上添加 v-once
attribute 以确保这些内容只计算一次然后缓存起来,但是建议不要过度使用这个模式。