本章继续回顾Vue相关的知识,主要针对组件这块,基础部分请看上一章。
组件基础
简单的组件:
1 | <div id="app"> |
上面的组件需要在components
中引入,当然也可以定义一个全局的组件:
1 | Vue.component('custom-button', { |
上面组件只有一个template属性,一般的组件还有data、方法、计算属性等。这里需要注意的是组件的data需要是一个方法,并且返回一个对象,而Vue实例的data是一个对象,如果组件的data是一个对象的话,那么多个组件将会使用一份数据,这样所有组件数据都是一样的,某个组件修改数据会影响到其他的同类组件。
1 | Vue.component('positive-numbers', { |
Props
组件的Props可以声明父组件要传递到子组件的数据:
1 | <div id="app"> |
props可以添加校验和默认值以及是否必须,校验失败在开发环境会报错:
1 | Vue.component('price-display', { |
组件props的大小写
模板中组件的props如果是带横线的属性,最后在组件内部将会自动转化为驼峰形式,如下
1 | <div id="app"> |
这里需要注意一点percentage-discount="20"
它的值最后是字符串的’20’而不是数字的20,所以上面代码会报错,如果要是数字的则需要:percentage-discount="20"
,同样的Boolean类型的也一样。
sync操作符
子组件中不建议直接修改父组件传下来的props,通常使用子组件的$emit方法来修改告诉父组件要修改值。某些情况下可以使用aync操作符来简化,赋值操作。
1 | <count-from-number :number.sync="numberToDisplay"/> |
组件定义:
1 | Vue.component('count-from-number', { |
实际上sync操作符只是一个语法糖,上面使用sync操作符的代码等同于:
1 | <count-from-number |
自定义组件的v-model
假设现在需要写一个只能输入小写字母的组件input-username,它需要支持v-model:
1 | <input-username |
上述代码等同于:
1 | <input-username |
所以要使得自定义组件支持v-model
可以这样写:
1 | Vue.component('input-username', { |
插槽slot
简单使用:
1 | Vue.component('custom-button', { |
上面定义了一个custom-button
的组件,则组件中间的部分将会给到插槽的位置:
1 | <custom-button>Press me!</custom-button> |
渲染后:
1 | <button class="custom-button">Press me!</button> |
插槽也可以给默认内容,只要下载slot
标签中间:
1 | Vue.component('custom-button', { |
这是如果自定义组件没有内容的时候将会使用默认内容,如:
1 | <custom-button></custom-button> |
渲染后:
1 | <button class="custom-button"> |
具名插槽就是给插槽起一个名字,如下面是blog-post
组件的模板,其中<slot name="header"></slot>
就是一个具名插槽,
1 | <section class="blog-post"> |
使用方式也很简单:
1 | <blog-post :author="author"> |
最终渲染的结果是:
1 | <section class="blog-post"> |
作用域插槽,组件的插槽可以向外面暴露数据:
1 | Vue.component('user-data', { |
上面相当于给defailt作用域的值定义为aaa变量,aaa.user就能获取到插槽的user属性了。当然默认插槽的也可以简写:v-slot="aaa"
。
Mixin
mixin的简单使用:
1 | const loggingMixin = { |
当组件被创建后先后打印:Logged from mixin
和Logged from component
。说白了mixin对象就是一个普通的JavaScript对象,它可以混入属性、方法、生命周期等,其中属性和方法如果组件中也有同名的则组件中的会覆盖mixin中的,但是生命周期都会执行。
vue-loader的使用
当使用vue-loader了以后就可以创建.vue
文件了。
之前的组件书写形式是:
1 | Vue.component('display-number', { |
.vue
文件组件的书写形式是:
1 | <template> |
代码更加之目了然了,组件的引用如下:
1 | <div id="app"> |
非prop属性
vue对非prop属性的处理是放在组件的外层上,并覆盖原有的。对于class和style则会合并。
1 | <div id="app"> |
最后渲染为:
1 | <button type="submit">Click me!</button> |
可以使用this.$attr
获取所有的非props属性。
render方法
上面的例子中都是使用template来定义组件的,实际上还可以写render函数来定义组件。假设有一个组件:
1 | const CustomButton = { |
使用render定义如下:
1 | const CustomButton = { |
上述代码是不是很难理解?render中代码的编写通常是由JSX来生成的,项目中使用babel-plugin-transform-vue-jsx
插件可以把JSX转换成类似于上述的函数内容。上述代码如果使用了JSX编写如下,是不是React很像?
1 | const CustomButton = { |
如果render和template同时出现,那么优先会使用render。