美文网首页
Vue 组件

Vue 组件

作者: hgzzz | 来源:发表于2018-10-31 13:54 被阅读0次

    组件是可复用的 Vue 实例,且带有一个名字

    • 组件也是一个 vue 实例,可以传入和 vue 一样的属性
    • 实例一个组件,这里只是定义一个组件,还没有再全局或者 vue 实例中注册,还不能去使用它
           //1. 创建组件构造器
            let Profile = Vue.extend({
                //1.1 模板选项
                template : `
                    <div>
                        <input type="date">
                        <p>今天心情不错!</p>
                    </div>
                `
            });
    

    或者在 html 页面中用 template 或者 script 便签定义一个模板

      <!-- 写在 vue 实例控制的区域外 -->
        <template id="myTemplate">
            <div>
                <h1>今天心情不错</h1>
                <p>出去走走</p>
            </div>
        </template>
    
      <!--这样也可以定义一个vue组件-->
        <script type="text/template" id="myTemplate">
            <div>
                <h1>今天心情不错</h1>
                <p>出去爬山</p>
            </div>
        </script>
    
    • 全局注册组件:这里全局注册的组件可以在页面上所有的vue实例中去使用
    //  注册全局组件
    Vue.component('mytemplate',Profile);
    

    使用:以组件名称为一对标签的写入 vue 实例控制的界面即可

        <div id="app">
            <mytemplate></mytemplate>
        </div>
    
    • 局部注册组件:在 vue 实例的 components 属性中注册局部组件,局部组件只能在对应 vue 实例控制的区域内使用
     //1. 创建Vue的实例
        let vm = new Vue({
            el : '#app',
            data : {
                message : ''
            },
            methods : {
                //实例的所有函数实现
            },
            components : {
                //注册局部组件,只能在这个vue实例内部使用
                'mytemplate' : Profile
            }
        });
    
    • 父子组件间传值问题,通过一个 TodoList 案例来解释,要求:在文本框中输入 Todo 添加到 list 中,点击 list 删除对应项,涉及到子组件向父组件传值和父组件向子组件传值
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>TodoList</title>
        <script src="../../Vue/node_modules/vue/dist/vue.js"></script>
    </head>
    
    <body>
        <div id="app">
            <input type="text" v-model="inputValue">
            <button @click="addToList">提交</button>
            <ul>
                <todo-item v-for="(item, index) in list" :content="item" :index="index" @delete="deleteFromList">
                </todo-item>
            </ul>
        </div>
        <script>
            // 注册一个 TodoItem 的组件
            let todoItem = {
                template: `<li @click="deleteItem">{{ content }}</li>`,
                props: ['content', 'index'],
                methods: {
                    deleteItem() {
                        this.$emit('delete', this.index);
                    }
                }
            };
            let vm = new Vue({
                el: '#app',
                data: {
                    list: [],
                    inputValue: ''
                },
                methods: {
                    addToList() {
                        this.list.push(this.inputValue);
                        this.inputValue = '';
                    },
                    deleteFromList(index) {
                        this.list.splice(index, 1);
                    }
                },
                components: {
                    todoItem
                }
            });
        </script>
    </body>
    
    </html>
    

    子组件向父组件传值,用事件调用的方式,父组件向子组件传值用属性绑定的方式。

    • 属性绑定:可以实现父组件向子组件传值,在做属性绑定时,一定要在子组件中的 props中去定义这个属性,子组件才可以使用在子组件中,也可以对父组件传的值做一定的校验
    // 可以将 props 属性写成一个对象
    props:{
      // 属性名 
      content : {
        type: String, // 规定接收属性的类型,如果要接收多个属性,可以写成一个数组
        required : Boolean, // 是否为必填,如果为 true 并且父组件没有传值则会报一个警告,默认是 false 
        default : defaultValue, // 默认值
        validator : function (value) {
          // 接收 属性的 value 值,可以对 value 进行验证,放回 true 表示通过验证, false 表示验证失败
         } 
      }
    }
    
    • 事件调用:在子组件中调用this.$emit('父组件自定义函数名',若干参数)的方式触发父组件自定义函数中对用的父级函数,来达到子组件向父组件传递值的目的(函数调用时的参数传递)
    • 非父子组件间传值
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>doucment</title>
    </head>
    
    <body>
        <div id="app">
            <mytemplate :content="'one'"></mytemplate>
            <mytemplate :content="'two'"></mytemplate>
        </div>
        <script src="../../Vue/node_modules/vue/dist/vue.js"></script>
        <script>
            /* 
            组件间不可以直接传值,
            我们可以将这个值放在一个公共的地方,
            然后组件去拿,这个地方就是 Vue 的原型上 
    
            1. 我们在Vue构造函数原型上定义一个属性,职为一个vue实例
            2. 在一个组件中用这个公共实例去触发一个自定义事件
              this.bus.$emit('fnName', args)
            3. 在另一个组件中去接收这个函数的触发,
              通过回调函数的参数接收触发时传递的参数
               this.bus.$on('fnName', function(args){
                  //   handler
              });
        */
            Vue.prototype.bus = new Vue();
    
    
    
    
            //1. 创建组件构造器
            let Profile = {
                //1.1 模板选项
                template: `<div @click="clickHandler">{{ selfContent }}</div>`,
                props: ['content'],
                data() {
                    return {
                        /* 
                         这里接收 content ,
                        因为我们需要去修改父组件的 content  的值,
                        如果是一 个引用类型,可能会造成问题 ,
                        影响别的组件对content的引用
                        需要先接收一下再修改
                        */
                        selfContent: this.content
                    }
                },
                methods: {
                    clickHandler() {
                        // 让原型上的 bus 实例去触发事件一个事件
                        this.bus.$emit('change', this.selfContent);
                    }
                },
                mounted() {
                    this.bus.$on('change', msg => {
                        this.selfContent = msg;
                    });
                },
            };
    
            // 2. 注册全局组件
            Vue.component('mytemplate', Profile);
    
            //1. 创建Vue的实例
            let vm = new Vue({
                el: '#app',
                data: {
                    message: ''
                },
                methods: {
                    //实例的所有函数实现
                }
            });
        </script>
    </body>
    
    </html>
    
    • 如果我们在组件标签上想去触发一个原生 DOM 事件,直接写是不生效的
    <div id="app">
      <myComponent @click="clickHandler></myComponent>
    </div>
    

    我们原本的目的是想直接点击这个组件就可以触发原生的 click事件,但是事与愿违,他会将我们写的 click当成一个自定义事件去解析,如果需要作为一个原生的 DOM 事件去触发,我们可以添加一个修饰符即可
    <myComponent @click.native="clickHandler></myComponent>

    • 假如涉及到了复杂的组件间的传值问题,可以考虑使用 vuex
    • 插槽的使用:如果我们需要由父组件向子组件里面传一段 html 代码,显然是不好取用属性绑定的方式,这里我们用插槽
    <div id="app">
            <my-slot>
                <!--组件中写入的html代码为插槽部分的代码-->
                <!--用slot给插槽命名,只会显示到组件中 name 属性为该名称的插槽中-->
                <div slot="panel-body">
                  <img src="image.jpg" alt="">
                  <p>鞠婧炜</p>
                </div>
            </my-slot>
        </div>
        <template id="my-slot">
            <div class="panel">
                <h1 class="panel-heading">头部</h1>
                <slot name="panel-body">默认显示!!!</slot>
                <footer>尾部</footer>
            </div>
        </template>
    
    • 组件向插槽传值,也是通过属性绑定的方式
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <script src="../../Vue/node_modules/vue/dist/vue.js"></script>
    </head>
    
    <body>
        <div id="app">
            <component>
                <template slot-scope="props">
                    <p>this is a slot DOM</p>
                    <p>{{ props.msg }}</p>
                </template>
            </component>
        </div>
        <script>
            let component = {
                data() {
                    return {
                        msg: 'this is the component msg'
                    }
                },
                template: `<div>
                            <p>conponent DOM</p>
                            <slot :msg="msg"></slot>
                           </div>`
            };
    
            let vm = new Vue({
                el: '#app',
                components: {
                    component
                }
            });
        </script>
    </body>
    
    </html>
    

    相关文章

      网友评论

          本文标题:Vue 组件

          本文链接:https://www.haomeiwen.com/subject/oekatqtx.html