5. 组件化开发

 本节内容:

  一、组件[component]

    1.1局部组件

    1.2 默认组件(全局组件)

  二、组件传值

    2.1 父组件往子组件传值

    2.2 子组件父组件传值

    2. 3 平行组件传值

一、组件[component]

     组件(Component)是自定义封装的功能。在前端开发过程中,经常出现多个网页的功能是重复的,而且很多不同的网站之间,也存在同样的功能

而在网页中实现一个功能,需要使用html定义功能的内容结构,使用css声明功能的外观样式,还要使用js来定义功能的特效,因此就产生了把一个

功能相关的[HTML、css和javascript]代码封装在一起组成一个整体的代码块封装模式,我们称之为“组件”。

所以,组件就是一个html网页中的功能,一般就是一个标签,标签中有自己的html内容结构,css样式和js特效。

这样,前端人员就可以在开发时,只需要书写一次代码,随处引入即可使用。

 

我们在进行vue开发的时候,还记得我们自己创建的vm对象吗,这个vm对象我们称为一个大组件,根组件(页面上叫Root),在一个网页的开发中,

根据网页上的功能区域我们又可以细分成其他组件,或称为子组件

注意: 在组建中template ,写组件中的html标签时,外层一定要套一个标签

1.1局部组件

三步:声子、用子、挂子

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="vue.js"></script>
</head>
<body>

<div id="app">
    <div class="vheader">
        这是头部{{msg}}
    </div>
    <App/>  <!--3 使用子组件-->

</div>


</body>
<script>
    //子组件的名称尽量不要叫做Header或者vHeader等,以防和最新的H5中的标签名称冲突,导致组件无法使用
    //  1 声明子组件
    let App = {

        data(){
            return { //组件中必须写成函数形式的
                'appmsg':'hello app!'
            }
        },
        // 写组件的html标签的地方
        template:`
            <div class="content">

                内容部分{{appmsg}}
            </div>

        `


    };



    let vm = new Vue({
        el:'#app',

        data(){
            return {
                'msg':'hello'
            }
        },

        components:{
            //App:App  //键的名臣和组件名称相同时,可以简写
            App,  // 2 挂载子组件

        }

    })


</script>
</html>
View Code

1.2 默认组件(全局组件)

直接看代码,局部组件使用时需要挂载,全局组件使用时不需要挂载。那么他们两个什么时候用呢,

局部组件就在某个局部使用的时候,全局组件是大家公用的,或者说每个页面都有这么一个功能的

时候,在哪里可能都会用到的时候。

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

</div>

<script>
    Vue.component("addnum",{
        template:'<div><input type="text" v-model="num"><button @click="num+=1">点击</button></div>',
        data: function(){
            // 写在这里的数据只有当前组件可以使用
            return {
                num:1,
            }
        }
    });


    var vm = new Vue({
        el:"#app",
        data:{

        }
    })
</script>
View Code

二、组件传值

2.1 父组件往子组件传值

两步:  

1.在子组件中使用props属性声明,然后可以直接在子组件中任意使用

2.父组件要定义自定义的属性

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="vue.js"></script>
</head>
<body>

<div id="app">
    <div class="vheader">
        这是头部{{msg}}
    </div>
    <App :xx="msg"/> 

</div>


</body>
<script>
    let App = {

        data(){
            return {
                'appmsg':'hello app!'
            }
        },
        template:`
            <div class="content">

                内容部分{{appmsg}}--{{xx}}
            </div>

        `,
        props:['xx',]

    };

    let vm = new Vue({
        el:'#app',

        data(){
            return {
                'msg':'hello'
            }
        },

        components:{
            App,  

        }

    })




</script>
</html>
示例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .c1{
            background-color: green;
        }
    </style>
</head>
<body>

<div id="app">
    <h1>{{ganmao}}</h1>
    <!-- 用子: 使用子组件 -->

    <App></App>



</div>


</body>
<script src="../vue.js"></script>
<script src="../axios.js"></script>
<script>
    // 局部组件
    //1 声子: 声明子组件
    let Vheader = {
        data(){
            return {
                msg:'我是子组件1号'
            }
        },
        // 写组件的html标签的地方
        template:
                    `
            <div class="c1">
                <h3 style="color:#ff0000">{{msg}}</h3>
                <h2 style="color:blue;">{{son}}</h2>

            </div>
        `
        ,
        props:['son', ],  //第二步: 写父组件中使用子组件时的自定义标签属性名称,那么他就可以拿到标签属性对应的值,并且可以作为当前子标签的一个数据属性来使用

    };

    let App = {
        data(){
            return {
                app_num:80,
            }
        },

        components: {
            Vheader,
        },

        // 注意: 写组件中的html标签时,外层一定要套一个标签


        // 第一步: 使用子组件的地方写自定义属性
        // 静态传值: <Vheader son="20"></Vheader>
        // 动态传值: <Vheader :son="app_num"></Vheader>
        template:
                    `
               <div class="app">
                   <h2>我是app组件</h2>
                  <Vheader :son="app_num"></Vheader>


              </div>

                    `
    }

    

    let vm  = new Vue({
        el:'#app',
        // data:{}
        data(){
            return {
                ganmao:'xxx',

            }
        },
        components:{
           App,
        }


    })


</script>


</html>
View Code
使用父组件传递数据给子组件时, 注意一下几点:

1. 传递数据是变量,则需要在属性左边添加冒号.

   传递数据是变量,这种数据称之为"动态数据传递"

   传递数据不是变量,这种数据称之为"静态数据传递"

2. 父组件中修改了数据,在子组件中会被同步修改,但是,子组件中的数据修改了,是不是影响到父组件中的数据.

   这种情况,在开发时,也被称为"单向数据流"

2.2 子组件父组件传值

两步:

  a.子组件中使用this.$emit('fatherHandler',val);fatherHandler是父组件中使用子组件的地方添加的绑定自定义事件,

  注意,如果fatherHandler报错了,那么可能是你的vue版本不支持自定义键名称fatherHandler中有大写字母,

  所以我们改成father-handler或者直接就全部小写就可以了

  b.父组件中的methods中写一个自定义的事件函数:appFatherHandler(val){},在函数里面使用这个val,

  这个val就是上面子组件传过来的数据

 第一步:在父组件使用子组件的地方写自定义事件
  <Vheader @fatherHandler="xx"></Vheader>

第二步: 在子组件中this.$emit('fatherHandler', 200);
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="vue.js"></script>
</head>
<body>

<div id="app">
    <div class="vheader">
        这是头部{{msg}} -- {{sondata}}
    </div>
    <App @son="sonDataHandler"/>

</div>


</body>
<script>
    let App = {

        data(){
            return {
                'appmsg':'hello app!'
            }
        },
        template:`
            <div class="content">

                内容部分{{appmsg}}
                <button @click="xH"></button>
            </div>

        `,
        methods:{
            xH(){
                this.$emit('son',this.appmsg)
            }
        }

    };

    let vm = new Vue({
        el:'#app',

        data(){
            return {
                'msg':'hello',
                'sondata':'xxx',
            }
        },

        components:{
            App,

        },
        methods:{
            sonDataHandler(val){
                console.log(val);

                this.sondata = val;

            }

        }

    })


</script>
</html>
View Code
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .c1{
            background-color: green;
        }
    </style>
</head>
<body>

<div id="app">
    <h1>{{ganmao}}</h1>
    <!-- 用子: 使用子组件 -->

    <App></App>



</div>


</body>
<script src="../vue.js"></script>
<script src="../axios.js"></script>
<script>
    // 局部组件
    //1 声子: 声明子组件
    let Vheader = {
        data(){
            return {
                msg:'我是子组件1号',
                header_num:99,
            }
        },
        // 写组件的html标签的地方
        template:
                    `
            <div class="c1">
                <h3 style="color:#ff0000">{{msg}}</h3>
                <button @click="zouni">zouni</button>

            </div>
        `
        ,
        methods: {
            zouni(){
                console.log(this);
                // this -- 组件对象
                this.$emit('fatherHandler', this.header_num);
            }

        }


    };

    let App = {
        data(){
            return {
                app_num:80,

                //  声明数据属性,承接子组件传递来的值
                son_data:0,
            }
        },

        components: {
            Vheader,
        },

        // 第一步:在父组件使用子组件的地方写自定义事件
        // <Vheader @fatherHandler="xx"></Vheader>

        // 第二步: 在子组件中this.$emit('fatherHandler', 200);


        template:
                    `
               <div class="app">
                   <h2>我是app组件</h2>
                  <Vheader @fatherHandler="xx"></Vheader>
                   <h3 style="color:yellow;">{{son_data}}</h3>

              </div>

                    `
        ,

        methods:{
            xx(val){
                this.son_data = val;
                console.log(this);
                // console.log('>>>>>', val);
            },


        }



    }


    let vm  = new Vue({
        el:'#app',
        // data:{}
        data(){
            return {
                ganmao:'xxx',

            }
        },
        components:{
           App,
        },



    })
    console.log(vm);

</script>


</html>
View Code

2. 3 平行组件传值

什么是平行组件,看图

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .c1{
            background-color: green;
        }
    </style>
</head>
<body>

<div id="app">

    <h1>{{ganmao}}</h1>
    <!-- 用子: 使用子组件 -->
    <App></App>


</div>


</body>
<script src="../vue.js"></script>
<script src="../axios.js"></script>
<script>

    // 第一步:声明公交车

    let bus = new Vue();


    let Vheader2 = {
        data(){
            return {
                msg:'我是子组件2号',
                header2_num:88,
                vheader_data:'',
            }
        },
        // 写组件的html标签的地方
        template:
                    `
            <div class="c1">
                <h3 style="color:#ff0000">{{msg}}</h3>
                <h3>{{vheader_data}}</h3>

            </div>
        `,
        created(){

            // 第三步:在公交车上获取值
            bus.$on('xxx',(val) => {
                console.log('???', val); // ??? 99

                this.vheader_data = val;

            });


        }

    }

    // 局部组件
    //1 声子: 声明子组件
    let Vheader = {
        data(){
            return {
                msg:'我是子组件1号',
                header_num:99,
            }
        },
        // 写组件的html标签的地方
        template:
                    `
            <div class="c1">
                <h3 style="color:#ff0000">{{msg}}</h3>
                 <button @click="zouni">zouni</button>

            </div>
        `
        ,
        methods: {
            zouni(){
                // 第二步:往公交车上添加值
                bus.$emit('xxx', this.header_num)
            }

        }


    };

    let App = {
        data(){
            return {
                app_num:80,

                //  声明数据属性,承接子组件传递来的值
                son_data:0,
            }
        },

        components: {
            Vheader,
            Vheader2,
        },

        // 第一步:在父组件使用子组件的地方写自定义事件
        // <Vheader @fatherHandler="xx"></Vheader>

        // 第二步: 在子组件中this.$emit('fatherHandler', 200);


        template:
                    `
               <div class="app">
                   <h2>我是app组件</h2>
                  <Vheader></Vheader>
                   <Vheader2></Vheader2>

              </div>

                    `
        ,

        methods:{
            xx(val){
                this.son_data = val;
                console.log(this);
                // console.log('>>>>>', val);
            },


        }



    }


    let vm  = new Vue({
        el:'#app',
        // data:{}
        data(){
            return {
                ganmao:'xxx',

            }
        },
        components:{
           App,
        },



    })
    console.log(vm);

</script>


</html>
例子1
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="vue.js"></script>
</head>
<body>

<div id="app">
    <div class="vheader">
        这是头部{{msg}} -- {{sondata}}
    </div>
    <!--<App :xx="msg"/>-->
    <App @sonHa="sonDataHandler"/>

</div>


</body>
<script>
    let bus = new Vue();

    Vue.component('T1',{
        data(){
            return {
                't1num':100,
            }
        },
        template:`

            <div class="t1">

                {{t1num}}
                <button @click="f1">走你</button>

            </div>
        `,
        methods:{
            f1(){
                // console.log(this.t1num);
                bus.$emit('TestData',this.t1num)

            }
        }

    });

    Vue.component('T2',{

        data(){
            return {
                't2num':200,
                't1n':0,
            }
        },
        template:`

            <div class="t2">

                <h1>{{t2num}}</h1>
                <h2 style="color:red;">{{t1n}}</h2>

            </div>
        `,
        created(){
            // console.log(this.t1n);
            bus.$on('TestData',(val)=>{

                console.log(val);
                this.t1n = val;

            })

        }

    });


    let App = {

        data(){
            return {
                'appmsg':'hello app!'
            }
        },
        template:`
            <div class="content">

                内容部分{{appmsg}}
                <button @click="xH">点击</button>
                <T1></T1>
                <T2></T2>
            </div>

        `,
        methods:{
            xH(){
                this.$emit('sonHa',this.appmsg)
            }
            // console.log(this);


        }
        // props:['xx',]


    };



    let vm = new Vue({
        el:'#app',

        data(){
            return {
                'msg':'hello',
                'sondata':'xxx',
            }
        },

        components:{
            App,

        },
        methods:{
            sonDataHandler(val){
                console.log(val);

                this.sondata = val;

            }

        }

    })

</script>
</html>
例子2

 

 

原文地址:https://www.cnblogs.com/yj0405/p/14562964.html