[Vue.js] 一篇超级长的笔记,给《Vue.js 实战》划个重点

本文前言

本笔记建立在书籍《Vue.js实战 / 梁灏编著》的基础上,旨在帮助有 Vue.js 基础的朋友快速回忆 Vue.js 的细碎内容。初学者建议阅读《Vue.js实战》全书进行系统学习。


第1篇 基础篇

第1章 初识 Vue.js

MVVM模式

Model-View-View-Model 的缩写,由经典的软件架构 MVC 衍生来。当 View(视图层)变化时,会自动更新到 ViewModel(视图模型),反之亦然。View 和 ViewModel 之间通过双向绑定(data-binding)建立联系。

MVVM关系

通过 script 加载 CDN 文件

<script src="https://unpkg.com/vue/dist/vue.min.js"></script>

第2章 数据绑定和第一个 Vue 应用

创建 Vue.js 应用

<div id="app">
    <h1>你好,{{name}}</h1>
</div>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            name: '世界'
        }
    })
</script>

下面的引用是对创建 Vue.js 应用的补充说明,便于深入理解。

Vue.js 应用的创建很简单,通过构造函数 Vue 就可以创建一个 Vue 的根实例,并启动 Vue 应用:

var app = new Vue({
 //选项
})

变量 app 就代表了这个 Vue 实例。事实上,几乎所有的代码都是一个对象,写入 Vue 实例的选项内的。

首先,必不可少的一个选项就是 el。el 用于指定一个页面中已存在的 DOM 元素来挂载 Vue 实例,它可以是 HTMLElement,也可以是 CSS 选择器,比如:

<div id="app"></div>

<script>
 var app = new Vue({
     el: document.getElementById('app') //或者是'#app'
 })
</script>

生命周期

  • created:实例创建完成后调用,此阶段完成了数据的观测等,但尚未挂载,$el 还不可用。需要初始化处理一些数据时会比较有用。
  • mounted:el 挂载到实例上后调用,一般我们的第一个业务逻辑会在这里开始。
  • beforeDestroy:实例销毁之前调用,主要解绑一些使用 addEventListener 监听的事件等。

v-bind 和 v-on

v-bind 的基本用途是动态更新 HTML 元素上的属性,比如 id,class 等,例如下面几个示例:

<div id="app">
    <a v-bind:href="url">链接</a>
    <img v-bind:src="imgUrl">
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            url: 'https://www.github.com',
            imgUrl: 'http://xxx.xxx.xx/img.png'
        }
    })
</script>

另一个非常重要的指令就是 v-on,它用来绑定事件监听器,这样我们就可以做一些交互了,先来看下面的示例:

<div id="app">
    <p v-if="show">这是一段文本</p>
    <button v-on:click="handleClose">点击隐藏</button>
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            show: true
        },
        methods: {
            handleClose: function() {
                this.show = false;
            }
        }
    })
</script>

语法糖

语法糖是指在不影响功能的情况下,添加某种方法实现同样的效果,从而方便程序开发。
Vue.js 的 v-bind 和 v-on 指令都提供了语法糖,也可以说是缩写,比如 v-bind,可以省略v-bind,直接写一个冒号“: ”,v-on 可以直接用“@”来缩写。

第3章 计算属性

什么是计算属性

在模板中双向绑定一些数据或表达式的时候,如果表达式过长,或逻辑更为复杂时,就会变得臃肿甚至难以阅读和维护,比如:

<div>
    {{ text.split(',').reverse().join(',') }}
</div>

这里的表达式包含3个操作,并不是很清晰,所以在遇到复杂的逻辑时应该使用计算属性。上例可以用计算属性进行改写:

<div id="app">
    {{ reversedText }}
</div>
<script>
	var app = new Vue({
        el: '#app',
        data:  {
            text: '123,456'
        },
        computed:{
            reversedText: function(){
				return this.text.split(',').reverse().join(',');
            }
        }
    })
</script>

计算属性的 getter 和 setter

<div id="app">
	姓名:{{ fullName }}
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            firstName: 'Jack',
            lastName: 'Green'
        },
        computed: {
            fullName: {
                //getter, 用于读取
                get: function () {
                    return this.firstName + '' + this.lastName;
                },
                //setter, 写入时触发
                set: function (newValue) {
                    var names = newValue.split(' ');
                    this.firstName = names[0];
                    this.lastName = names[names.length - 1];
                }
            }
        }
    })
</script>

当执行 app.fullName = 'John Doe'; 时,setter 就会被调用,数据 firstName 和 lastName 都会相对更新,视图同样也会更新。

计算属性的两个小技巧

计算属性还有两个很实用的小技巧容易被忽略:一是计算属性可以依赖其他计算属性;二是计算属性不仅可以依赖当前Vue实例的数据,还可以依赖其他实例的数据,例如:

<div id="app1"></div>
<div id="app2">
	{{ reversedText }}
</div>
<script>
	var app1 = new Vue({
       el: '#app1',
        data: {
            text: '123,456'
        }
    });
    
    var app2 = new Vue({
        el: '#app2',
        computed: {
            reversedText: function(){
                // 这里以来的是实例 app1 的数据 text
                return app1.text.split(',').reverse().join(',');
            }
        }
    })
</script>

计算属性缓存

计算属性是基于它的依赖缓存的。一个计算属性所依赖的数据发生变化时,它才会重新取值,所以上述例子中的 text 只要不改变,计算属性也就不更新,例如:

computed: {
    now: function () {
        return Date.now();
    }
}

这里的 Date.now() 不是响应式依赖,所以计算属性 now 不会更新。但是 methods 则不同,只要重新渲染,它就会被调用,因此函数也会被执行。
使用计算属性还是 methods 取决于你是否需要缓存,当遍历大数组和做大量计算时,应当使用计算属性,除非你不希望得到缓存。

第4章 v-bind 及 class 与 style 绑定

在数据绑定中,最常见的两个需求就是元素的样式名称 class 和内联样式 style 的动态绑定,它们也是 HTML 的属性,因此可以使用 v-bind 指令。我们只需要用 v-bind 计算出表达式最终的字符串就可以,不过有时候表达式的逻辑较复杂,使用字符串拼接方法较难阅读和维护,所以 Vue.js 增强了对 class 和 style 的绑定。

绑定样式名称

对象语法

给 v-bind:class 设置一个对象,可以动态地切换 class,例如

<div id="app">
    <div :class="{'active': isActive}"></div>
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            isActive: true
        }
    })
</script>

上面示例中,类名 active 依赖于数据 isActive,当其为 true 时,div 会拥有类名 Active,为 false 时则没有,所以上例最终渲染完的结果是:

<div class="active"></div>

对象中也可以传入多个属性,来动态切换 class 。另外,:class 可以与普通 class 共存,例如:

<div id="app">
    <div class="static" :class="{'active': isActive, 'error': isError}"
</div>

当:class 的表达式过长或逻辑复杂时,还可以绑定一个计算属性,这是一种很友好和常见的用法,一般当条件多于两个时,都可以使用data或computed,例如使用计算属性:

<div id="app">
    <div :class="classes"></div>
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            isActive: true,
            error: null
        },
        computed: {
            classes: function(){
                return {
                    active: this.isActive && !this.error,
                    'text-fail': this.error && this.error.type === 'fail'
                }
            }
        }
    })
</script>
数组语法

当需要应用多个class时,可以使用数组语法,给:class绑定一个数组,应用一个class列表:

<div id="app">
    <div :class="[activeClass, errorClass]"></div>
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            activeClass: 'active',
            errorClass: 'error'
        }
    })
</script>

渲染后的结果为:

<div class="active error"></div>

还可以在数组语法中使用对象语法:

<div id="app">
    <div :class="[{'active': isActive}, errorClass]"></div>
</div>
<script>
	var app = new Vue({
        el:'#app',
        data: {
            isActive: true,
            errorClass: 'error'
        }
    })
</script>

当然,与对象语法一样,也可以使用data,computed 和 methods 三种方法,以计算属性为例:

<div id="app">
    <button :class="classes"></button>
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            size: 'large',
            disabled: true
        },
        computed: {
            classes: function(){
                'btn',
				{
                    ['btn-'+this.size]: this.size != '',
                    ['btn-disabled']: this.disabled
                }
            }
        }
    })
</script>

示例中的样式 btn 会始终应用,当数据 size 不为空时,会应用样式前缀 btn-,后加 size 的值;当数据 disabled 为真时,会应用样式 btn-disabled,所以该示例最终渲染的结果为:

<button class="btn btn-large btn-disabled"></button>

使用计算属性给元素动态设置类名,在业务中经常用到,尤其是在写复用的组件时,所以在开发过程中,如果表达式较长或逻辑复杂,应该尽可能地优先使用计算属性。

绑定内联样式

使用 v-bind:style(即 :style)可以给元素绑定内联样式,方法与 :class 类似,也有对象语法和数组语法,看起来很像直接在元素上写 CSS。

CSS属性名称使用驼峰命名(camelCase)或短横分隔命名(kebab-case)。

大多数情况下,直接写一长串的样式不便于阅读和维护,所以一般写在data或computed里,以data为例改写上面的示例:

<div id="app">
    <div :style="styles">文本</div>
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            styles: {
                color: 'red',
                fontSize: 14 + 'px'
            }
        }
    })
</script>

应用多个样式对象时,可以使用数组语法:

<div :style="[styleA, styleB]">文本</div>

在实际业务中,:style 的数组语法并不常用,因为往往可以写在一个对象里面;而较为常用的应当是计算属性。
另外,使用 :style时,Vue.js 会自动给特殊的 CSS 属性名称增加前缀,比如 transform

第5章 内置指令

基本指令

v-cloak

v-cloak 不需要表达式,它会在 Vue 实例结束编译时从绑定的HTML元素上移除,经常和 CSS 的display: none;配合使用。

在一般情况下,v-cloak 是一个解决初始化慢导致页面闪动的最佳实践,对于简单的项目很实用,但是在具有工程化的项目里,比如 webpack 和 vue-router,项目的HTML结构只有一个空的div元素,剩余的内容都是由路由去挂载不同组件完成的,所以不再需要v-cloak.

v-once

v-once 也是一个不需要表达式的指令,作用是定义它的元素或组件只渲染一次,包括元素或组件的所有子节点。首次渲染后,不再随数据的变化重新渲染,将被视为静态内容。

v-once 在业务中也很少使用,当你需要进一步优化性能时,可能会用到。

条件渲染指令

v-if、v-else-if、v-else

与JavaScript的条件语句 if,else,else if 类似,Vue.js 的条件指令可以根据表达式的值在DOM中渲染或销毁元素/组件。

<div id="app">
    <p v-if="status === 1">当status为1时显示该行</p>
    <p v-else-if="status === 2">当status为2时显示该行</p>
    <p v-else>否则显示该行</p>
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            status: 1
        }
    })
</script>
v-show

v-show 的用法与 v-if 基本一致,只不过 v-show 是改变元素的 CSS 属性 display。当 v-show 表达式的值为false时,元素会隐藏,查看DOM结构会看到元素上加载了内联样式 display: none;

<div id="app">
    <p v-show="status === 1">当status为1时显示该行</p>
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            status: 2
        }
    })
</script>

渲染后的结果为:

<p style="display: none;">当status为1时显示该行</p>

列表渲染指令 v-for

当需要将一个数组遍历或枚举一个对象循环显示时,就会用到列表渲染指令 v-for。它的表达式需结合 in 来使用,类似 item in items 的形式,看下面的示例:

<div id="app">
    <ul>
        <li v-for="book in books">{{ book.name }}</li>
    </ul>
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            books: [
                { name: '《Vue.js 实战》'},
                { name: '《JavaScript 语言精粹》' }{ name: '《JavaScript 高级程序设计》'}
            ]
        }
    })
</script>

渲染结果:

  • 《Vue.js 实战》

  • 《JavaScript 语言精粹》

  • 《JavaScript 高级程序设计》

v-for 的表达式支持一个可选参数作为当前项的索引,例如:

<div id="app">
    <ul>
        <li v-for="(book, index) in books">{{ index }} - {{ book.name }}</li>
    </ul>
</div>
<script>
	//内容省略
</script>

渲染结果:

  • 0 - 《Vue.js 实战》

  • 1 - 《JavaScript 语言精粹》

  • 2 - 《JavaScript 高级程序设计》

除了数组外,对象的属性也是可以遍历的,例如:

<div id="app">
    <span v-for="value in user">{{ value }}</span>
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            user: {
                name: 'Aresn',
                gender: '男',
                age: 26
            }
        }
    })
</script>

渲染结果:

<span>Aresn </span><span>男 </span><span>26 </span>

遍历对象属性时,有两个可选参数,分别是键名索引

<div id="app">
    <ul>
        <li v-for="(value, key, index) in user">
        	{{index}} - {{key}}: {{value}}
        </li>
    </ul>
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            user: {
                name: 'Aresn',
                gender: '男',
                age: 26
            }
        }
    })
</script>

渲染后的结果:

  • 0 - name: Aresn

  • 1 - gender: 男

  • 2 - age: 26

第6章 表单与 v-model

表单控件在实际业务较为常见,比如单选、多选、下拉选择、输入框等,用它们可以完成数据的录入、校验、提交等。Vue.js 提供了 v-model 指令,用于在表单类元素上双向绑定数据,例如在输入框上使用时,输入的内容会实时映射到绑定的数据上。例如下面的例子:

<div id="app">
    <input type="text" v-model="message" placeholder="输入...">
    <p>输入的内容是:{{message}}</p>
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            message: ''
        }
    })
</script>

在输入框输入的同时,{{message}} 也会实时将内容渲染在视图中。

单选按钮:

单选按钮在单独使用时,不需要 v-model,直接使用 v-bind 绑定一个布尔类型的值,为真时选中,为否时不选,例如:

<div id="app">
    <input type="radio" :check="picked">
    <label>单选按钮</label>
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            picked: true
        }
    })
</script>

如果是组合使用来实现互斥选择的效果,就需要 v-model 配合 value 来使用:

<div id="app">
    <input type="radio" v-model="picked" value="html" id="html">
    <label for="html">HTML</label>
    <br>
    <input type="radio" v-model="picked" value="js" id="js">
    <label for="html">JavaScript</label>
    <br>
    <input type="radio" v-model="picked" value="css" id="css">
    <label for="html">CSS</label>
    <br>
    <p>选择的项是:{{picked}}</p>
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            picked: 'js'
        }
    })
</script>

复选框:

复选框也分单独使用和组合使用,不过用法稍与单选不同。复选框单独使用时,也是用 v-model 来绑定一个布尔值,例如:

<div id="app">
    <input type="checkbox" v-model="checked" id="checked">
    <label for="checked">选择状态:{{checked}}</label>
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            checked: false
        }
    })
</script>

在勾选时,数据 checked 的值变为了 true,label 中渲染的内容也会更新。
组合使用时,也是 v-model 与 value 一起,多个勾选框都绑定到同一个数组类型的数据,value 的值在数组当中,就会选中这一项。这一过程也是双向的,在勾选时,value 的值也会自动 push 到这个数组中,示例代码如下:

<div id="app">
    <input type="checkbox" v-model="checked" value"html" id="html">
    <label for="html">HTML</label>
    <br>
    <input type="checkbox" v-model="checked" value"js" id="js">
    <label for="html">JavaScript</label>
    <br>
    <input type="checkbox" v-model="checked" value"css" id="css">
    <label for="html">CSS</label>
    <br>
</div>
<script>
	var app = new Vue({
        el: '#app',
        data: {
            checked: ['html', 'css']
        }
    })
</script>

第7章 组件详解

7.1 组件与复用

组件需要注册后才可以使用。注册有全局注册和局部注册两种方式

全局注册示例代码如下:

<div id="app">
    <my-component></my-component>
</div>
<script>
	Vue.component('my-component', {
        template: '<div>这里是组件的内容</div>'
    });
    var app = new Vue({
        el: '#app'
    })
</script>

局部注册示例代码如下:

<div id="app">
    <my-component></my-component>
</div>
<script>
	var Child = {
        template: '<div>局部注册组件的内容</div>'
    };
    var app = new Vue({
        el: '#app',
        components: {
            'my-component': Child
        }
    })
</script>

组件中 data 的使用:

组件在使用data时,和实例稍有区别,data必须是函数,然后将数据return出去,例如:

<div id="app">
    <my-component></my-component>
</div>
<script>
	Vue.component('my-component', {
        template: '<div>{{message}}</div>',
        data: function(){
            return {
                message: '组件内容'
            }
        }
    });
    var app = new Vue({
        el: '#app'
    })
</script>

复用组件时的数据隔离

JavaScript 对象是引用关系,所以如果 return 出的对象引用了外部的一个对象,那这个对象就是共享的,任何一方修改都会同步。比如下面的示例:

<div id="app">
    <my-component></my-component>
    <my-component></my-component>
    <my-component></my-component>
</div>
<script>
	var data = {
        counter: 0
    };
    
    Vue.component('my-component', {
        template: '<button @click="counter++">{{counter}}</button>',
        data: function(){
            return data;
        }
    });
    
    var app = new Vue({
        el: '#app'
    })
</script>

组件使用了3次,但是点击任意一个<button>,3个的数字都会加1,那是因为组件的data引用的是外部的对象,这肯定不是我们期望的效果,所以给组件返回一个新的data对象来独立,示例代码如下:

<div id="app">
    <my-component></my-component>
    <my-component></my-component>
    <my-component></my-component>
</div>
<script>
    Vue.component('my-component', {
        template: '<button @click="counter++">{{counter}}</button>',
        data: function(){
            return {
                couter: 0
            };
        }
    });
    
    var app = new Vue({
        el: '#app'
    })
</script>

这样,点击3个按钮就互不影响了,完全达到复用的目的。

7.2 使用 props 传递数据

在组件中,使用选项 props 来声明需要从父级接收的数据,props 的值可以是两种,一种是字符串数组,一种是对象。

字符串数组写法

基本写法:

<div id="app">
    <my-component parent-message="来自父组件的数据"></my-component>
</div>
<script>
	Vue.component('my-component', {
        props: ['parentMessage'],
        template: '<div>{parentMessage}</div>'
    });
    var app = new Vue({
        el: '#app'
    })
</script>

如果要传递多个数据,在 props 数组中添加项即可。由于HTML特性不区分大小写,当使用DOM模板时,驼峰命名(camelCase)的props名称要转为短横分隔命名(kebab-case)。

parentMessage --> parent-message

业务中会经常遇到两种需要改变 prop 的情况一种是父组件传递初始值进来,子组件将它作为初始值保存起来,在自己的作用域下可以随意使用和修改。这种情况可以在组件 data 内再声明一个数据,引用父组件的 prop,示例代码如下:

<div id="app">
    <my-component :init-count="1"></my-component>
</div>
<script>
	VUe.component('my-component', {
        props: ['initCount'],
        template: '<div>{{count}}</div>',
        data: function(){
            return {
                count: this.initCount
            }
        }
    });
    var app = new Vue({
        el: '#app'
    })
</script>

组件中声明了数据 count,它在组件初始化时会获取来自父组件的initCount,之后就与之无关了,只用维护count,这样就可以避免直接操作initCount.
另一种情况就是 prop 作为需要被转变的原始值传入。这种情况用计算属性就可以了,示例代码如下:

<div id="app">
    <my-component :width="100"></my-component>
</div>
<script>
	Vue.component('my-component', {
        props: ['width'],
        template: '<div :style="style">组件内容</div>',
        computed: {
            style: function(){
                return {
                    width: this.width + 'px'
                }
            }
        }
    });
    var app = new Vue({
        el: '#app'
    })
</script>

因为用CSS传递宽度要带单位(px),但是每次都写太麻烦,而且数值计算一般是不带单位的,所以统一在组件内使用计算属性就可以了。

注意,在JavaScript中对象和数组是引用类型,指向同一个内存空间,所以props是对象和数组时,在子组件内改变是会影响父组件的。

对象写法 / Prop 验证

我们上面所介绍的props选项的值都是一个数组,一开始也介绍过,除了数组外,还可以是对象,当 prop 需要验证时,就需要对象写法。
一般当你的组件需要提供给别人使用时,推荐都进行数据验证,比如某个数据必须是数字类型,如果传入字符串,就会在控制台弹出警告。

Vue.component('my-component', {
    props: {
        propA: Number, //必须是数字类型
        propB: [String, Number], //必须是字符串或数字类型
        propC: {
            type: Boolean,
            default: true
        }, //布尔值,如果没有定义,默认值就是 true
        propD: {
            type: Number,
            required: true
        }, //数字,而已是必传
        propE: {
            type: Array,
            default: function(){
                return [];
            }
        }, //如果是数组或对象,默认值必须从一个工厂函数获取
        //自定义一个验证函数
        propF: {
            validator: function(value){
                return value > 10;
            }
        }
    }
});

验证的 type 类型可以是:

  • string
  • Number
  • Boolean
  • Object
  • Array
  • Function

7.3 组件通信

组件通信实例

自定义事件

子组件用 $emit() 来触发事件,父组件用 $on() 来监听子组件的事件。
父组件也可以直接在子组件的自定义标签上使用 v-on 来监听子组件触发的自定义事件,示例代码如下:

<div id="app">
    <p>总数:{{total}}</p>
    <my-component @increase="handleGetTotal"
                  @reduce="handleGetTotal"></my-component>
</div>
<script>
	Vue.component('my-component', {
        template: '\
		<div>\
			<button @click="handleIncrease">+1</button>\
			<button @click="handleReduce">-1</button>\
		</div>',
        data: function(){
            return {
                counter: 0
            }
        },
        methods: {
            handleIncrease: function () {
                this.counter++;
                this.$emit('increase', this.counter);
            },
            handleReduce: function () {
                this.counter--;
                this.$emit('reduce', this.counter);
            }
        }
    });

    var app = new Vue({
        el: '#app',
        data: {
            total: 0
        },
        methods: {
            handleGetTotal: function (total) {
                this.total = total;
            }
        }
    })
</script>

如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:

<my-component v-on:click.native="doTheThing"></my-component>
使用 v-model

组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件。

<input v-model="parentData">

等价于:

<input 
    :value="parentData"
    @input="parentData = $event.target.value"
>

示例:

<div id="app">
    <p>总数:{{total}}</p>
    <my-component v-model="total"></my-component>
</div>
<script>
	Vue.component('my-component', {
        template: '<button @click="handleClick>+1</button>',
        data: function(){
            return {
                counter: 0
            }
        },
        methods: {
            handleClick: function () {
                this.counter++;
                this.$emit('input', this.counter);
            }
        }
    });

    var app = new Vue({
        el: '#app',
        data: {
            total: 0
        }
    })
</script>
非父子组件通信

使用一个空的 Vue 实例作为中央事件总线(bus),也就是一个中介。

var bus = new Vue();

示例:

<div id="app">
    {{ message }}
    <component-a></component-a>
</div>
<script>
	var bus = new Vue();
    
    Vue.component('component-a',{
        template: '<button @click="handleEvent">传递事件</button>',
        methods: {
            handleEvent: function() {
                bus.$emit('on-message', '来自组件component-a的内容');
            }
        }
    });
    
    var app = new Vue({
        el: '#app',
        data: {
            message: ''
        },
        mounted: function() {
            var _this = this;
            //在实例初始化时,监听来自 bus 实例的事件
            bus.$on('on-message', function(msg){
                _this.message = msg;
            })
        }
    })
</script>

代码解释:首先创建了一个名为 bus 的空 Vue 实例,里面没有任何内容;然后全局定义了组件component-a;最后创建Vue实例app,在app初始化时,也就是在生命周期mounted钩子函数里监听了来自bus的事件on-message,而在组件component-a中,点击按钮会通过bus把事件on-message发出去,此时app就会接收到来自bus的事件,进而在回调里完成自己的业务逻辑。

7.4 使用 slot 分发内容

solt 用法

单个 Solt

在子组件内使用特殊的 <slot>元素就可以为这个子组件开启一个 slot(插槽),在父组件模板里,插入在子组件标签内的所有内容将替代子组件的 <slot> 标签及它的内容。示例代码如下:

<div id="app">
    <child-component>
    	<p>分发的内容</p>
        <p>更多分发的内容</p>
    </child-component>
</div>
<script>
	Vue.component('child-component', {
        template: '\
		<div>\
			<slot>\
				<p>如果父组件没有插入内容,我将作为默认出现</p>\
			</slot>\
        </div>'
    });
    
    var app = new Vue({
        el: '#app'
    })
</script>

具名 Slot

<slo> 元素指定一个 name 后可以分发多个内容,具名 Slot 可以与单个 Slot 共存,例如下面的示例:

<div id="app">
    <child-component>
    	<h2 slot="header">标题</h2>
        <p>正文内容</p>
        <p>更多的正文内容</p>
        <div slot="footer">底部信息</div>
    </child-component>
</div>
<script>
	Vue.component('child-component', {
        template: '\
		<div class="container">\
			<div class="header">\
				<slot name="header"></slot>\
			</div>\
			<div class="main">\
				<slot></slot>\
        	</div>\
			<div class="footer">\
				<slot name="footer"></slot>\
			<div>\
		</div>'
    });
    
    var app = new Vue({
        el: '#app'
    })
</script>

第2篇 进阶篇

第10章 使用 webpack

什么是webpack?

什么是webpack? - 知乎 (zhihu.com)


写在最后的话

目前本篇笔记还不是《Vue.js 实战》的全部内容,仅详细涵盖了书籍中的第1篇基础篇。基础篇内容既是基础又是核心,考虑到本文的内容是帮助读者快速回忆 Vue.js 细碎的知识点,所以就先发了了出来,后面的内容以后再补充吧。

编辑于2022-01-06

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值