[关闭]
@Secretmm 2016-07-09T10:54:24.000000Z 字数 16474 阅读 1220

Vue

框架


vue的基础知识

MVVM模式的理解

Hello World示例

这段代码在画面上输出"Hello World!"。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        <!--这是View-->
        <div id="app">
            {{ message }}
        </div>
    </body>
    <script src="js/vue.js"></script>
    <script>
        // 这是Model
        var exampleData = {
            message: 'Hello World!'
        }

        // 创建一个 Vue 实例或 "ViewModel"
        // 它连接 View 与 Model
        new Vue({
            el: '#app',
            data: exampleData
        })
    </script>
</html>

使用Vue的过程就是定义MVVM各个组成部分的过程的过程。
1.定义View
2.定义Model
3.创建一个Vue实例或"ViewModel",它用于连接View和Model
在创建Vue实例时,需要传入一个选项对象,选项对象可以包含数据、挂载元素、方法、模生命周期钩子等等。
Vue.js有多种数据绑定的语法,最基础的形式是文本插值,使用一对大括号语法,在运行时{{ message }}会被数据对象的message属性替换,所以页面上会输出"Hello World!"。


双向绑定示例

MVVM模式本身是实现了双向绑定的,在Vue.js中可以使用v-model指令在表单元素上创建双向数据绑定。

<!--这是我们的View-->
<div id="app">
    <p>{{ message }}</p>
    <input type="text" v-model="message"/>
</div>

将message绑定到文本框,当更改文本框的值时,<p>{{ message }}</p> 中的内容也会被更新。
反过来,如果改变message的值,文本框的值也会被更新


Vue.js的常用指令

Vue.js的指令是以v-开头的,它们作用于HTML元素,指令提供了一些特殊的特性,将指令绑定在元素上时,指令会为绑定的目标元素添加一些特殊的行为,我们可以将指令看作特殊的HTML特性(attribute)。
Vue.js提供了一些常用的内置指令:
v-if指令
v-show指令
v-else指令
v-for指令
v-bind指令
v-on指令


v-if指令

v-if是条件渲染指令,它根据表达式的真假来删除和插入元素,它的基本语法如下:

v-if="expression"

expression是一个返回bool值的表达式,表达式可以是一个bool属性,也可以是一个返回bool的运算式。例如:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <div id="app">
            <h1>Hello, Vue.js!</h1>
            <h1 v-if="yes">Yes!</h1>
            <h1 v-if="no">No!</h1>
            <h1 v-if="age >= 25">Age: {{ age }}</h1>
            <h1 v-if="name.indexOf('jack') >= 0">Name: {{ name }}</h1>
        </div>
    </body>
    <script src="js/vue.js"></script>
    <script>

        var vm = new Vue({
            el: '#app',
            data: {
                yes: true,
                no: false,
                age: 28,
                name: 'keepfool'
            }
        })
    </script>
</html>

注意:yes, no, age, name这4个变量都来源于Vue实例选项对象的data属性。

这段代码使用了4个表达式:

数据的yes属性为true,所以"Yes!"会被输出;
数据的no属性为false,所以"No!"不会被输出;
运算式age >= 25返回true,所以"Age: 28"会被输出;
运算式name.indexOf('jack') >= 0返回false,所以"Name: keepfool"不会被输出。
注意:v-if指令是根据条件表达式的值来执行元素的插入或者删除行为。

这一点可以从渲染的HTML源代码看出来,面上只渲染了3个<h1>元素,v-if值为false的<h1>元素没有渲染到HTML。

为了再次验证这一点,可以在Chrome控制台更改age属性,使得表达式age >= 25的值为false,可以看到<h1>Age: 28</h1>元素被删除了

v-show指令

v-show也是条件渲染指令,和v-if指令不同的是,使用v-show指令的元素始终会被渲染到HTML,它只是简单地为元素设置CSS的style属性。【v-if是false,那是真正的不存在;而 v-show是看起来存在,只是把对应的属性改成disply】

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <div id="app">
            <h1>Hello, Vue.js!</h1>
            <h1 v-show="yes">Yes!</h1>
            <h1 v-show="no">No!</h1>
            <h1 v-show="age >= 25">Age: {{ age }}</h1>
            <h1 v-show="name.indexOf('jack') >= 0">Name: {{ name }}</h1>
        </div>
    </body>
    <script src="js/vue.js"></script>
    <script>

        var vm = new Vue({
            el: '#app',
            data: {
                yes: true,
                no: false,
                age: 28,
                name: 'keepfool'
            }
        })
    </script>
</html>

在Chrome控制台更改age属性,使得表达式age >= 25的值为false,可以看到<h1>Age: 24</h1>元素被设置了style="display:none"样式。

v-else指令

可以用v-else指令为v-if或v-show添加一个“else块”。v-else元素必须立即跟在v-if或v-show元素的后面——否则它不能被识别。


<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <div id="app">
        <h1 v-if="age >= 25">Age: {{ age }}</h1>
        <h1 v-else>Name: {{ name }}</h1>
        <h1>---------------------分割线---------------------</h1>
        <h1 v-show="name.indexOf('keep') >= 0">Name: {{ name }}</h1>
        <h1 v-else>Sex: {{ sex }}</h1>
    </div>
</body>
<script src="js/vue.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            age: 28,
            name: 'keepfool',
            sex: 'Male'
        }
    })
</script>
</html>

v-else元素是否渲染在HTML中,取决于前面使用的是v-if还是v-show指令。
这段代码中v-if为true,后面的v-else**不会渲染到HTML;**v-show为ture,但是后面的v-else仍然渲染到HTML了。




组件

组件的创建和注册

基本步骤:
调用Vue.extend()方法创建组件构造器
调用Vue.component()方注册组件
Vue实例的作用范围使用组件

<!DOCTYPE html>
<html>
    <body>
        <div id="app">
            <!-- 3. #app是Vue实例挂载的元素,应该在挂载元素范围内使用组件-->
            <my-component></my-component>
        </div>
    </body>
    <script src="js/vue.js"></script>
    <script>

        // 1.创建一个组件构造器
        var myComponent = Vue.extend({
            template: '<div>This is my first component!</div>'
        })

        // 2.注册组件,并指定组件的标签,组件的HTML标签为<my-component>
        Vue.component('my-component', myComponent)

        new Vue({
            el: '#app'
        });

    </script>
</html>

理解组件的创建和注册
我们用以下几个步骤来理解组件的创建和注册:

  1. Vue.extend()是Vue构造器的扩展,调用Vue.extend()创建的是一个组件构造器,而不是一个具体的组件实例。
  2. Vue.extend()构造器有一个选项对象,选项对象的template属性用于定义组件要渲染的HTML。
  3. 使用Vue.component()注册组件时,需要提供2个参数,第1个参数时组件的标签,第2个参数是组件构造器。
  4. Vue.component()方法内部会调用组件构造器,创建一个组件实例。
  5. 组件应该挂载到某个Vue实例下,否则它不会生效。
    请注意第5点,以下代码在3个地方使用了<my-component>标签,但只有#app1和#app2下的标签才起到作用。

全局注册和局部注册

调用Vue.component()注册组件时,组件的注册是全局的,这意味着该组件可以在任意Vue示例下使用。
如果不需要全局注册,或者是让组件使用在其它组件内,可以用选项对象的components属性实现局部注册。

上面的示例可以改为局部注册的方式:

<!DOCTYPE html>
<html>
    <body>
        <div id="app">
            <!-- 3. my-component只能在#app下使用-->
            <my-component></my-component>
        </div>
    </body>
    <script src="js/vue.js"></script>
    <script>
        // 1.创建一个组件构造器
        var myComponent = Vue.extend({
            template: '<div>This is my first component!</div>'
        })

        new Vue({
            el: '#app',
            components: {
                // 2. 将myComponent组件注册到Vue实例下
                'my-component' : myComponent
            }
        });
    </script>
</html>

父组件和子组件

我们可以在组件中定义并使用其他组件,这就构成了父子组件的关系。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="js/vue.js"></script>
</head>
<body>
    <div id="app">
    <!-- 6.在Vue实例作用范围内使用组件 -->
        <parent-component>
        </parent-component>
    </div>
<script type="text/javascript">
//1.创建子组件构造器Child
    var Child=Vue.extend({
        template:'<p>我差不多已经是个死人了</p>'
    })
//2.创建父组件构造器Parent,并将3.Child组件注册到Parent组件下,并将Child组件的标签设置为child-component
    var Parent=Vue.extend({
        template:'<p>我就是个死人了</p><child-component></child-component>',
        //4.在Parent组件内以标签的形式使用Child组件
        components:{
            'child-component':Child
        }
    })
//5.全局注册Parent组件,并指定组件的标签,组件的HTML标签为<parent-component>
    Vue.component('parent-component',Parent)

    new Vue({
        el:'#app'
    })
</script>
</body>
</html>

我们分几个步骤来理解这段代码:

1. var Child = Vue.extend(...)定义一了个Child组件构造器
2.var Parent = Vue.extend(...)定义一个Parent组件构造器
3. components: { 'child-component': Child },将Child组件注册到Parent组件,并将Child组件的标签设置为child-component。
4. template :'<p>This is a Parent component</p><child-component></child-component>',在Parent组件内以标签的形式使用Child组件。
5.Vue.component('parent-component', Parent) 全局注册Parent组件
6.  在页面中使用<parent-component>标签渲染Parent组件的内容,同时Child组件的内容也被渲染出来

组件注册语法糖

全局注册:
使用Vue.component()直接创建和注册组件:

// 全局注册,my-component1是标签名称
Vue.component('my-component1',{
    template: '<div>This is the first component!</div>'
})

var vm1 = new Vue({
    el: '#app1'
})

Vue.component()的第1个参数是标签名称,第2个参数是一个选项对象,使用选项对象的template属性定义组件模板。
使用这种方式,Vue在背后会自动地调用Vue.extend()

局部注册:
在选项对象的components属性中实现局部注册:

var vm2 = new Vue({
    el: '#app2',
    components: {
        // 局部注册,my-component2是标签名称
        'my-component2': {
            template: '<div>This is the second component!</div>'
        },
        // 局部注册,my-component3是标签名称
        'my-component3': {
            template: '<div>This is the third component!</div>'
        }
    }
})

使用script或template标签

尽管语法糖简化了组件注册,但在template选项中拼接HTML元素比较麻烦,这也导致了HTML和JavaScript的高耦合性。
庆幸的是,Vue.js提供了两种方式将定义在JavaScript中的HTML模板分离出来。

使用<script>标签

<!DOCTYPE html>
<html>
    <body>
        <div id="app">
            <my-component></my-component>
        </div>

        <script type="text/x-template" id="myComponent">
            <div>This is a component!</div>
        </script>
    </body>
    <script src="js/vue.js"></script>
    <script>

        Vue.component('my-component',{
            template: '#myComponent'
        })

        new Vue({
            el: '#app'
        })

    </script>
</html>

使用<template>标签

如果使用<template>标签,则不需要指定type属性。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <div id="app">
            <my-component></my-component>
        </div>

        <template id="myComponent">
            <div>This is a component!</div>
        </template>
    </body>
    <script src="js/vue.js"></script>
    <script>

        Vue.component('my-component',{
            template: '#myComponent'
        })

        new Vue({
            el: '#app'
        })

    </script>
</html>

组件的el和data选项

传入Vue构造器的多数选项也可以用在 Vue.extend()Vue.component()中,不过有两个特例: data 和el。
Vue.js规定:在定义组件的选项时,data和el选项必须使用函数。

下面的代码在执行时,浏览器会提出一个错误

Vue.component('my-component', {
    data: {
        a: 1
    }
})

另外,如果data选项指向某个对象,这意味着所有的组件实例共用一个data。
我们应当使用一个函数作为 data 选项,让这个函数返回一个新对象:

Vue.component('my-component', {
    data: function(){
        return {a : 1}
    }
})

使用props

组件实例的作用域是孤立的。这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。可以使用 props 把父组件的数据传给子组件。

props基础示例
下面的代码定义了一个子组件my-component,在Vue实例中定义了data选项。

var vm = new Vue({
    el: '#app',
    data: {
        name: 'keepfool',
        age: 28
    },
    components: {
        'my-component': {
            template: '#myComponent',
            props: ['myName', 'myAge']
        }
    }
})

为了便于理解,你可以将这个Vue实例看作my-component的父组件。
如果我们想使父组件的数据,则必须先在子组件中定义props属性,也就是props: ['myName', 'myAge']这行代码。

定义子组件的HTML模板:

<template id="myComponent">
    <table>
        <tr>
            <th colspan="2">
                子组件数据
            </th>
        </tr>
        <tr>
            <td>my name</td>
            <td>{{ myName }}</td>
        </tr>
        <tr>
            <td>my age</td>
            <td>{{ myAge }}</td>
        </tr>
    </table>
</template>

将父组件数据通过已定义好的props属性传递给子组件:

<div id="app">
    <my-component v-bind:my-name="name" v-bind:my-age="age"></my-component>
</div>

注意:在子组件中定义prop时,使用了camelCase命名法。由于HTML特性不区分大小写,camelCase的prop用于特性时,需要转为 kebab-case(短横线隔开)。例如,在prop中定义的myName,在用作特性时需要转换为my-name

整体代码:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <link rel="stylesheet" href="styles/demo.css" />
    </head>

    <body>

        <div id="app">
            <my-component v-bind:my-name="name" v-bind:my-age="age"></my-component>
        </div>

        <template id="myComponent">
            <table>
                <tr>
                    <th colspan="2">
                        子组件数据
                    </th>
                </tr>
                <tr>
                    <td>my name</td>
                    <td>{{ myName }}</td>
                </tr>
                <tr>
                    <td>my age</td>
                    <td>{{ myAge }}</td>
                </tr>
            </table>
        </template>
    </body>
    <script src="js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                name: 'keepfool',
                age: 28
            },
            components: {
                'my-component': {
                    template: '#myComponent',
                    props: ['myName', 'myAge']
                }
            }
        })
    </script>
</html>

prop的单向绑定

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <link rel="stylesheet" href="styles/demo.css" />
    </head>

    <body>

        <div id="app">

            <table>
                <tr>
                    <th colspan="3">父组件数据</td>
                </tr>
                <tr>
                    <td>name</td>
                    <td>{{ name }}</td>
                    <td><input type="text" v-model="name" /></td>
                </tr>
                <tr>
                    <td>age</td>
                    <td>{{ age }}</td>
                    <td><input type="text" v-model="age" /></td>
                </tr>
            </table>
            <my-component v-bind:my-name="name" v-bind:my-age="age"></my-component>
        </div>

        <template id="myComponent">
            <table>
                <tr>
                    <th colspan="3">子组件数据</td>
                </tr>
                <tr>
                    <td>my name</td>
                    <td>{{ myName }}</td>
                    <td><input type="text" v-model="myName" /></td>
                </tr>
                <tr>
                    <td>my age</td>
                    <td>{{ myAge }}</td>
                    <td><input type="text" v-model="myAge" /></td>
                </tr>
            </table>
        </template>
    </body>
    <script src="js/vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                name: 'keepfool',
                age: 28
            },
            components: {
                'my-component': {
                    template: '#myComponent',
                    props: ['myName', 'myAge']
                }
            }
        })
    </script>

</html>

理解:修改了子组件的数据,没有影响父组件的数据。
修改了父组件的数据,子组件的数据也随之改变。

双向绑定

可以使用.sync显式地指定双向绑定,这使得彼此之间修改数据,对方的数据都会改变。

<my-component v-bind:my-name.sync="name" v-bind:my-age.sync="age"></my-component>

单次绑定

可以使用.once显式地指定单次绑定,单次绑定在建立之后不会同步之后的变化,这意味着即使父组件修改了数据,也不会传导给子组件。

<my-component v-bind:my-name.once="name" v-bind:my-age.once="age"></my-component>

使用Slot

为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板。这个处理称为内容分发,Vue.js 实现了一个内容分发 API,使用特殊的 <slot> 元素作为原始内容的插槽。

如果不理解这段话,可以先跳过,你只要知道<slot>元素是一个内容插槽。

单个Slot
下面的代码在定义my-component组件的模板时,指定了一个<slot></slot>元素。

<div id="app">
    <my-component>
        <h1>Hello Vue.js!</h1>
    </my-component>

    <my-component>
    </my-component>
</div>
<template id="myComponent">
    <div class="content">
        <h2>This is a component!</h2>
        <slot>如果没有分发内容,则显示slot中的内容</slot>
        <p>Say something...</p>
    </div>
</template>
<script src="js/vue.js"></script>
<script>
    Vue.component('my-component', {
        template: '#myComponent'
    })

    new Vue({
        el: '#app'
    })
</script>

第一个<my-component>标签有一段分发内容<h1>Hello Vue.js!</h1>,渲染组件时显示了这段内容。image

第二个<my-component>标签则没有,渲染组件时则显示了slot标签中的内容。

View Demo

指定名称的slot
上面这个示例是一个匿名slot,它只能表示一个插槽。如果需要多个内容插槽,则可以为slot元素指定name属性。

多个slot一起使用时,会非常有用。例如,对话框是HTML常用的一种交互方式。
在不同的运用场景下,对话框的头部、主体内容、底部可能是不一样的。

这时,使用不同名称的slot就能轻易解决这个问题了。

<template id="dialog-template">
    <div class="dialogs">
        <div class="dialog" v-bind:class="{ 'dialog-active': show }">
            <div class="dialog-content">
                <div class="close rotate">
                    <span class="iconfont icon-close" @click="close"></span>
                </div>
                <slot name="header"></slot>
                <slot name="body"></slot>
                <slot name="footer"></slot>
            </div>
        </div>
        <div class="dialog-overlay"></div>
    </div>
</template>

<script src="js/vue.js"></script>
<script>
    Vue.component('modal-dialog', {
        template: '#dialog-template',
        props: ['show'],
        methods: {
            close: function() {
                this.show = false
            }
        }
    })

    new Vue({
        el: '#app',
        data: {
            show: false
        },
        methods: {
            openDialog: function() {
                this.show = true
            },
            closeDialog: function() {
                this.show = false
            }
        }
    })
</script>

在定义modal-dialog组件的template时,我们使用了3个slot,它们的name特性分别是header、body和footer。

<modal-dialog>标签下,分别为三个元素指定slot特性:

<div id="app">
    <modal-dialog v-bind:show.sync="show">

        <header class="dialog-header" slot="header">
            <h1 class="dialog-title">提示信息</h1>
        </header>

        <div class="dialog-body" slot="body">
            <p>你想在对话框中放什么内容都可以!</p>
            <p>你可以放一段文字,也可以放一些表单,或者是一些图片。</p>
        </div>

        <footer class="dialog-footer" slot="footer">
            <button class="btn" @click="closeDialog">关闭</button>
        </footer>
    </modal-dialog>

    <button class="btn btn-open" @click="openDialog">打开对话框</button>
</div>

对话框的标题内容、主体内容、底部内容,完全由我们自定义,而且这些内容就是一些简单的HTML元素!

如果需要定制对话框的样式,我们只需要在<modal-dialog>上追加一个v-bind指令,让它绑定一个class

<modal-dialog v-bind:show.sync="show" v-bind:class="dialogClass">

然后修改一下Vue实例,在data选项中追加一个dialogClass属性,然后修改openDialog()方法:

new Vue({
    el: '#app',
    data: {
        show: false,
        dialogClass: 'dialog-info'
    },
    methods: {
        openDialog: function(dialogClass) {
            this.show = true
            this.dialogClass = dialogClass
        },
        closeDialog: function() {
            this.show = false
        }
    }
})

虽然我们在modal-dialog组件中定义了3个slot,但是在页面中使用它时,并不用每次都指定这3个slot
比如,有时候我们可能只需要header和body:

<modal-dialog v-bind:show.sync="show" v-bind:class="dialogClass">
    <header class="dialog-header" slot="header">
        <h1 class="dialog-title">提示信息</h1>
    </header>

    <div class="dialog-body" slot="body">
        <p>你想在对话框中放什么内容都可以!</p>
        <p>你可以放一段文字,也可以放一些表单,或者是一些图片。</p>
    </div>
</modal-dialog>

现在看到的对话框是没有底部的,只有标题和主体内容。

多个slot同时使用的场景还有很多,例如:用户的注册、登录、找回密码等这些表单集合,也可以用一个组件来完成。


父子组件之间的访问

有时候我们需要父组件访问子组件,子组件访问父组件,或者是子组件访问根组件。
针对这几种情况,Vue.js都提供了相应的API:

父组件访问子组件:使用$children$refs
子组件访问父组件:使用$parent
子组件访问根组件:使用$root
$children示例

下面这段代码定义了3个组件:父组件parent-component,两个子组件child-component1child-component2

在父组件中,通过this.$children可以访问子组件。
this.$children是一个数组,它包含所有子组件的实例。

<div id="app">
    <parent-component></parent-component>
</div>

<template id="parent-component">
    <child-component1></child-component1>
    <child-component2></child-component2>
    <button v-on:click="showChildComponentData">显示子组件的数据</button>
</template>

<template id="child-component1">
    <h2>This is child component 1</h2>
</template>

<template id="child-component2">
    <h2>This is child component 2</h2>
</template>

<script src="js/vue.js"></script>
<script>
    Vue.component('parent-component', {
        template: '#parent-component',
        components: {
            'child-component1': {
                template: '#child-component1',
                data: function() {
                    return {
                        msg: 'child component 111111'
                    }
                }
            },
            'child-component2': {
                template: '#child-component2',
                data: function() {
                    return {
                        msg: 'child component 222222'
                    }
                }
            }
        },
        methods: {
            showChildComponentData: function() {
                for (var i = 0; i < this.$children.length; i++) {
                        alert(this.$children[i].msg)
                }
            }
        }
    })

    new Vue({
        el: '#app'
    })
</script>

$refs示例

组件个数较多时,我们难以记住各个组件的顺序和位置,通过序号访问子组件不是很方便。
在子组件上使用v-ref指令,可以给子组件指定一个索引ID:

<template id="parent-component">
    <child-component1 v-ref:cc1></child-component1>
    <child-component2 v-ref:cc2></child-component2>
    <button v-on:click="showChildComponentData">显示子组件的数据</button>
</template>
在父组件中,则通过$refs.索引ID访问子组件的实例:

showChildComponentData: function() {
    alert(this.$refs.cc1.msg);
        alert(this.$refs.cc2.msg);
}

$parent示例

下面这段代码定义了两个组件:child-component和它的父组件parent-component。
在子组件中,通过this.$parent可以访问到父组件的实例。

<div id="app">
    <parent-component></parent-component>
</div>

<template id="parent-component">
    <child-component></child-component>
</template>

<template id="child-component">
    <h2>This is a child component</h2>
    <button v-on:click="showParentComponentData">显示父组件的数据</button>
</template>

<script src="js/vue.js"></script>
<script>
    Vue.component('parent-component', {
        template: '#parent-component',
        components: {
            'child-component': {
                template: '#child-component',
                methods: {
                    showParentComponentData: function() {
                        alert(this.$parent.msg)
                    }
                }
            }
        },
        data: function() {
            return {
                msg: 'parent component message'
            }
        }
    })
    new Vue({
        el: '#app'
    })
</script>

自定义事件

有时候我们希望触发父组件的某个事件时,可以通知到子组件;触发子组件的某个事件时,可以通知到父组件。
Vue 实例实现了一个自定义事件接口,用于在组件树中通信。这个事件系统独立于原生 DOM 事件,用法也不同。

每个 Vue 实例都是一个事件触发器:

使用 $on() 监听事件;
使用 $emit() 在它上面触发事件;
使用 $dispatch() 派发事件,事件沿着父链冒泡;
使用 $broadcast() 广播事件,事件向下传导给所有的后代。
派发事件
下面这段代码是一个简单的事件派发处理

<div id="app">
    <p>Messages: {{ messages | json }}</p>
    <child-component></child-component>
</div>

<template id="child-component">
    <input v-model="msg" />
    <button v-on:click="notify">Dispatch Event</button>
</template>

<script src="js/vue.js"></script>
<script>
    // 注册子组件
    Vue.component('child-component', {
        template: '#child-component',
        data: function() {
            return {
                msg: ''
            }
        },
        methods: {
            notify: function() {
                if (this.msg.trim()) {
                    this.$dispatch('child-msg', this.msg)
                    this.msg = ''
                }
            }
        }
    })

    // 初始化父组件
    new Vue({
        el: '#app',
        data: {
            messages: []
        },
        events: {
            'child-msg': function(msg) {
                this.messages.push(msg)
            }
        }
    })
</script>

我们将这个示例分为几个步骤解读:

子组件的button元素绑定了click事件,该事件指向notify方法
子组件的notify方法在处理时,调用了$dispatch,将事件派发到父组件的child-msg事件,并给该该事件提供了一个msg参数
父组件的events选项中定义了child-msg事件,父组件接收到子组件的派发后,调用child-msg事件。

广播事件

下面这段代码是一个简单的事件广播处理

<div id="app">
    <input v-model="msg" />
    <button v-on:click="notify">Broadcast Event</button>
    <child-component></child-component>
</div>

<template id="child-component">
    <ul>
        <li v-for="item in messages">
            父组件录入了信息:{{ item }}
        </li>
    </ul>
</template>

<script src="js/vue.js"></script>
<script>
    // 注册子组件
    Vue.component('child-component', {
        template: '#child-component',
        data: function() {
            return {
                messages: []
            }
        },
        events: {
            'parent-msg': function(msg) {
                this.messages.push(msg)
            }
        }
    })
    // 初始化父组件
    new Vue({
        el: '#app',
        data: {
            msg: ''
        },
        methods: {
            notify: function() {
                if (this.msg.trim()) {
                    this.$broadcast('parent-msg', this.msg)
                }
            }
        }
    })
</script>

我们将这个示例分为几个步骤解读:

父组件的button元素绑定了click事件,该事件指向notify方法
父组件的notify方法在处理时,调用了$broadcast,将事件派发到子组件的parent-msg事件,并给该该事件提供了一个msg参数
子组件的events选项中定义了parent-msg事件,子组件接收到父组件的广播后,调用parent-msg事件。


CURD示例

Vue.js组件的API来源于三部分——prop,slot和事件。

prop 允许外部环境传递数据给组件;
件 允许组件触发外部环境的 action
slot 允许外部环境插入内容到组件的视图结构内。





添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注