vue组件

组件

  • 组件就是html, css和js文件的集合体, 实现对代码的复用, 组件就是vue对象

组件的分类#

  • 根组件
Copy<script>
    // 像我们熟悉的new Vue({...})形式的, 就是根组件
    new Vue ({
        el: '#d1',
        data: {
            msg: '这是根组件'
        },
        `vue对象就是根组件, 其下面的el属性对应的挂载点就相当于template的占位符
        根组件可以不明确template, template默认采用挂载点页面结构, 
        那如果根组件明确了template, 那就会把挂载点给替换掉`
        tempalte: ''
    })
</script>
  • 局部组件
Copy<script> 
// 这样定义的只是个普通对象, 只有在父组件中注册之后, 才成为vue对象    
let localTag = {
        template: `
        <div>
        <p>这是一个局部标签</p>      
        </div>
        `,
        methods: {
            fn() {
                console.log(this)
            }
        }
    };
</script>
  • 全局组件 Vue.component
Copy<script>
// 这样我们就定义了一个全局组件, 全局组件直接就是vue对象, 因此不需要在根组件中注册
Vue.component('globalTag', {
        template: `
        <div>
        <p>这是一个全局组件</p>
        </div>
        `,
        methods: {
            fn() {
                console.log(this)
            }
        }
    });
</script>

组件的特点#

  • 组件都有管理组件html页面结果的template属性, 且template中只有且只有一个根标签
  • 根组件永远都是爸爸(父组件), 而局部和全局组件及既可以是儿子(子组件)也可以是爸爸
  • 子组件的数据需要隔离 (数据组件化, 每一个组件都拥有自己数据的名称空间)
  • 局部组件必须注册后才能使用, 全局组件不需要注册, 提倡使用局部组件
  • 组件自己的变量(模板和逻辑语句中)自己负责

组件的使用#

  • 声明组件
  • 注册组件(局部组件)
  • 渲染组件,
    • 因为html对标签大小写不敏感, 在html代码中引用局部和全局组件时, 要采用 "-" 取代驼峰体, 如: localTag --><local-tag></local-tag>
Copy<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件的使用</title>
    <style>
        body, h2 {
            margin: 0;
        }
        .wrap {
            width: 880px;
            margin: 0 auto;
        }
        /*清除浮动带来的影响*/
        .wrap:after {
            content: '';
            display: block;
            clear: both;
        }
        .box {
            width: 200px;
            border-radius: 10px;
            overflow: hidden;
            background-color: grey;
            float: left;
            margin: 10px;
        }
        .box img {
            width: 100%;
        }
        .box h2 {
            text-align: center;
            font-weight: normal;
            font-size: 20px;
        }
    </style>

</head>
<body>
<div id="d1">
    <div class="wrap">
        <!--使用局部组件-->
        <local-tag></local-tag>
        <local-tag></local-tag>
        <local-tag></local-tag>
        <local-tag></local-tag>

        <!--使用全局组件-->
        <global-tag></global-tag>
        <global-tag></global-tag>
        <global-tag></global-tag>
        <global-tag></global-tag>
        
    </div>
</div>

<script src="vue/vue.js"></script>
<script>
    // 定义局部组件
    let localTag = {
        template: `
        <div class="box">
            <img src="img/111.jpg" alt="">
            <h2>玩手机</h2>
        </div>
        `,
        methods: {
            fn() {
                console.log(this)
            }
        }
    };

    // 定义全局组件
    Vue.component('globalTag', {
        template: `
        <div class="box">
        <img src="img/222.jpg" alt="">
            <h2>笑脸</h2>
        </div>
        `,
        methods: {
            fn() {
                console.log(this)
            }
        }
    });

    // 根组件
    new Vue({
        el: '#d1',
        data: {
            msg: '这是根组件'
        },
        // 注册局部组件
        components: {
            localTag,
        }
    })
</script>
</body>
</html>

## 组件化

  • 一个组件可能会被复用渲染多次, 要保证基于这个组件进行渲染的页面之间的数据是相互隔离的, 不然一个页面的数据发生了改变, 其他的不特么全都变了么
  • 那如何保证数据隔离呢? 答案就是使用data函数, 然后用data函数返回我们需要的数据, 这样就保证了各自的数据都在各自data函数的名称空间中
Copy<script>
    // 使用data函数定义并返会变量
        data() {
          return 
            { count: 0,}
        },
    
</script>

组件传参-父传子#

  • 子组件可以通过props定义组件标签属性(采用反射机制, 因此需要使用字符串定义)
  • 子组件标签在父组件标签中渲染, 因此子组件标签可以通过 ":子标签属性=父组件变量" 来获取父组件的数据
Copy
<body>
<div id="d1">
    <div class="wrap">
        <!--利用子组件的标签的自定义属性来获取父组件的变量, 且是单向的-->
        <local-tag :msg="msg"></local-tag>
    </div>
</div>

<script src="vue/vue.js"></script>
<script>
    // 局部组件
    let localTag = {
        // 通过props定义属性 (反射原理, 因此要用字符串定义)
        props: ['msg'],
        template: `
        <div class="box" @click="fn">
            <img src="img/111.jpg" alt="">
            <h2>{{ this.msg }}</h2>
        </div>
        `,
    };

    // 根组件
    new Vue({
        el: '#d1',
        data: {
            msg: '这是根组件的变量msg'
        },
        // 注册局部组件
        components: {
            localTag,
        }
    })
</script>
</body>

组件传参-子传父#

  • 自定义事件, 子组件触发, 父组件实现
  • 子组件通过 this.$emit("事件名", 传给父组件事件方法的参数)
  • 说的直白点, 就是在父组件中定义事件方法, 在子组件中调用该事件方法
Copy<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>
<div id="d1">
    <h1>{{ h1 }}</h1>
    <h3>{{ h3 }}</h3>
    <!--action是自定义的事件, 这个事件方法在父组件中定义, 在子组件触发(调用)-->
    <!--在父级标签中出现的所有变量由根组件控制, 因此这个actionFn是根组件的-->
    <tag1 @aciton="actionFn"></tag1>
    <hr>
    <!--<tag2 @h1a="aFn1" @h3a="aFn3"></tag2>-->

</div>
<script src="vue/vue.js"></script>
<script>
    let tag1 = {
        template: `
        <div>
        <input type="text" v-model="t1">
        <input type="text" v-model="t2">
        // 在局部组件内部定义的点击事件
        <button @click="changeTitle">修改标题</button>
</div>
        `,
        data() {
            return {
                t1: '',
                t2: '',
            }
        },
        methods: {
            // 点击事件
            changeTitle() {
                if (this.t1 && this.t2) {
                    // 调用自定义事件
                    this.$emit('action', this.t1, this.t2);
                    this.t1 = '';
                    this.t2 = '';
                }
            }
        }
    };

    let tag2 = {
        template: `
        <div>
        主标题内容: <input type="text"  v-model="t1" @input="t1Fn">
        子标题内容: <input type="text"  v-model="t2">
</div>
        `,
        data() {
            return {
                t1: '',
                t2: '',
            }
        },
        methods: {
            t1Fn() {
                this.$emit('h1a', this.t1);
            }
        },
        watch: {
            t2() {
                this.$emit('h3a', this.t2)

            }
        }
    };

    new Vue({
        el: '#d1',
        data: {
            h1: '主标题',
            h3: '子标题',
        },
        components: {
            tag1,
            tag2,
        },
        methods: {
            actionFn(a, b) {
                this.h1= a;
                this.h3 =b;
            },
            aFn1(a) {
                if (!a) {
                    this.h1 = '主标题';
                    return;
                }
                this.h1 = a;
            },
            aFn3(a) {
                if (!a) {
                    this.h3 = '子标题';
                    return;
                }
                this.h3 = a;
            },
        }
    });
</script>

</body>
</html>
posted @ 2019-12-30 21:50  ^啷个哩个啷$  阅读(204)  评论(0编辑  收藏  举报