这篇文章主要讲vue组件化应用构建

1. 组件化应用构建

组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树。
在 Vue 里,一个组件本质上是一个拥有预定义选项的一个 Vue 实例。在 Vue 中注册组件很简单:

  • 通过Vue.component()方法直接创建

    1
    2
    3
    4
    // 定义名为 todo-item 的新组件
    Vue.component('todo-item', {
    template: '<li>这是个待办项</li>'
    })
  • 通过将模板字符串定义到script标签中

    1
    2
    3
    4
    5
    6
    7
    8
    <script id="tpl" type="text/x-template">
    <h2>这里是待办事项</h2>
    </script>
    <script>
    Vue.component('my-com', {
    template: '#tpl'
    });
    </script>
    1
    2
    3
    4
    <div id="app">
    <!-- 创建一个 my-com 组件的实例 -->
    <my-com></my-com>
    </div>

组件化和模块化的不同:

  • 模块化: 是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一;
  • 组件化: 是从UI界面的角度进行划分的;前端的组件化,方便UI组件的重用;

2. 组件展示数据和响应事件

  • 组件可以有自己的data,Vue实例中的data可以是一个对象,但是组件中的data必须是一个方法,而且这个方法内部还必须返回一个对象。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    <!-- 以下内容在body标签内部**公共组件和私有组件的区别 -->
    <div id="app">
    <my-com></my-com>
    </div>

    <div id="app2">
    <my-com></my-com>
    <inner></inner>
    </div>

    <template id="tlp">
    <!--注意:template属性指定的内容,只能有一个根元素-->
    <div>
    <h3>这是利用组件模板创建的待办事项</h3>
    <span>没毛病。。。</span>
    </div>
    </template>
    <script id="tlp2" type="text/x-template">
    <h2>i am a priority component, do not forget the SPACE</h2>
    </script>

    <script src="./lib/vue-2.4.0.js"></script>
    <script>
    // 公用组件
    Vue.component('myCom', {
    template: '#tlp'
    });

    let vm = new Vue({
    el: '#app',
    data: {},
    methods: {}
    });
    let vm2 = new Vue({
    el: '#app2',
    data: {},
    methods: {},
    filters: {},
    directives: {},
    components: { // 定义内部私有组件,注意是复数
    inner: {
    template: '#tlp2' // 不能有空格否则id找不到
    }
    }
    })
    </script>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    <!-- 以下内容在body标签内部**data必须是一个方法并且返回一个对象 -->
    <div id="app">
    <my-com></my-com>
    <my-com></my-com>
    </div>
    <template id="tlp">
    <div>
    <button @click="add">click me +1</button>
    <h5>{{ count }}</h5>
    </div>

    </template>
    <script src="./lib/vue-2.4.0.js"></script>
    <script>
    let outData = {count: 0};
    Vue.component('myCom', {
    template: '#tlp',
    data: function () {
    // return outData; // 如果返回了外部的对象,那么两次创建的组件会同步变化
    return { count: 0 } // 这样的返回值才能保证组将之间互不影响
    },
    methods: {
    add() {
    this.count ++
    }
    }
    });

    let vm = new Vue({
    el: '#app',
    data: {},
    methods: {
    }
    });
    </script>
  • 利用组件实现登录/注册的切换

    1
    2
    3
    4
    5
    6
    7
    8
    9
    .v-enter,
    .v-leave-to {
    opacity: 0;
    transform: translateX(100px);
    }
    .v-enter-active,
    .v-leave-active {
    transition: all .8s ease;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <div id="app">
    <a href="" @click.prevent="cName='login'">登录</a>
    <a href="" @click.prevent="cName='register'">注册</a>

    <!-- 通过 mode 属性,设置组件切换时候的 模式 -->
    <transition mode="out-in">
    <!-- Vue提供了 component ,来展示对应名称的组件 -->
    <!-- component 是一个占位符, :is 属性,可以用来指定要展示的组件的名称 -->
    <component :is="cName"></component>
    </transition>

    <!-- 总结:当前学习了的 Vue 提供的标签 -->
    <!-- component, template, transition, transitionGroup -->
    </div>
    <script src="./lib/vue-2.4.0.js"></script>
    <script>
    Vue.component('login', {
    template: '<h2>登录</h2>'
    });
    Vue.component('register', {
    template: '<h2>注册</h2>'
    });

    let vm = new Vue({
    el: '#app',
    data: {
    cName: 'login'
    },
    methods: {}
    });
    </script>

2.1 父组件向子组件传值

  • 利用props定义属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <div id="app">
    <!-- 父组件可以通过 属性绑定(v-bind:)的形式把数据传递给子组件 -->
    <com1 v-bind:fathermsg="msg"></com1>
    </div>
    <script src="./lib/vue-2.4.0.js"></script>
    <script>
    let vm = new Vue({
    el: '#app',
    data: {
    msg: '父组件内容'
    },
    methods: {},
    components: {
    com1: {
    template: '<h2>子组件内容 -- {{ fathermsg }}</h2>',
    data() { // 这里的data是子组件自身私有的,可以是通过ajax请求来的数据,这些数据时可以读写的
    return {
    content: 'test content'
    }
    },
    // 组件中props属性中的数据都是通过父组件传递过来的,这里面的数据是只读的
    props: ['fathermsg']
    }
    }
    });
    </script>

2.2 子组件向父组件传值

  • 父组件把方法传递给子组件,同时传递参数给子组件,这样达到传递数据的目的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    <div id="app">
    <!-- 父组件向子组件传递方法,使用v-on, 自定义一个事件属性之后,组件就能通过$emit()调用这个方法了 -->
    <com2 @func="getData"></com2>
    </div>
    <script type="text/x-template" id="tpl">
    <div>
    <h2>子组件的内容</h2>
    <button @click="sonClick">点击调用父组件中的方法并传参</button>
    </div>
    </script>
    <script src="./lib/vue-2.4.0.js"></script>
    <script>
    let com2 = {
    template: '#tpl',
    data(){
    return { // 需要传递的数据
    sonData: {
    name: 'jack',
    age: 18
    }
    }
    },
    methods: { // 组件中的点击事件
    sonClick(){
    // emit 是发出,触发的意思。这个方法将触发func方法并将参数传递给父组件
    this.$emit('func', this.sonData)
    }
    }
    };
    let vm = new Vue({
    el: '#app',
    data: {
    dataFromSon: null // 定义一个变量准备接受子组件传递过来的数据
    },
    methods: {
    getData(data){
    // 将子组件传递过来的值赋值给父组件
    this.dataFromSon = data;
    }
    },
    components: {
    com2 // com2组件定义在外部
    }
    });
    </script>