一、组件化的基本使用

组件构造基本步骤
1.创建组件构造器对象
2.注册组件
3.使用组件

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script src="../js/vue.js"></script>
  
  <div id="app">
    <!--3.使用组件-->
    <my-cpn></my-cpn>
    <my-cpn></my-cpn>
    
  </div>
  <!--下面的这个标签组件不会解析,因为必须放在vue实例里面-->
  <my-cpn></my-cpn>
  <script>
    //ES6中可以使用 ` `来定义字符串,而且能换行定义
   //1.创建组件构造器对象
const cpnC = Vue.extend({
  template:`<div>
             <h2>hhhhh</h2>
             <p>xxxxxx</p>
            </div> `
           
});

//2.注册组件
Vue.component('my-cpn',cpnC);

  const app = new Vue({
    el: '#app',
    data: { 
      message: 'helloWorld!'
    }
  });
  </script>
</body>
</html>

全局组件和局部组件
全局组件,意味着可以在多个vue实例下使用。
局部组件,只能在对应注册的实例中使用。
代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script src="../js/vue.js"></script>
  
  <div id="app">
    <cpn></cpn>
    <cpn></cpn>
    <cpn></cpn>
    <cpn></cpn>
    
  </div>

  <div id="app2">
    <!-- <cpn></cpn>
    <cpn></cpn>
    <cpn></cpn>
    <cpn></cpn> -->
    
  </div>
  <script>
   //1.创建一个组件构造器
const cpnC=Vue.extend({
  template:`
     <div>
       <h2>我是哈哈</h2>
       <p>我是内容</p>
     </div>
  `
});
//2.全局组件,意味着可以在多个vue实例下使用
//Vue.component('cpn',cpnC);

//??怎末注册的组件才是局部组件。只要去相应的vue实例里面注册就是了

  const app = new Vue({
    el: '#app',
    data: { 
      message: 'helloWorld!'
    },
    components:{
      cpn:cpnC
    }
  });

  const app2 = new Vue({
    el: '#app2',
    data: { 
      message: 'helloWorld!'
    }
    
  });

  </script>
</body>
</html>

上面组件只在app中注册了,所以只能再app这个实例中使用,而不能再app2中使用。

组件的语法糖注册方法
代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script src="../js/vue.js"></script>
  
  <div id="app">
    <cpn></cpn>
    <cpn2></cpn2>
  </div>
  <script>

 //之前我们是这样来创建组件的
 //1.创建一个组件构造器   
/* const cpnC=Vue.extend({
  template:`
     <div>
       <h2>我是哈哈</h2>
       <p>我是内容</p>
     </div>
  `
}); */
//2.全局注册组件
/* Vue.component('cpn',cpnC); */

//下面简写语法
//全局注册组件语法糖,可以直接将extend中的内容拿过来
Vue.component('cpn',{
  template:`
     <div>
       <h2>我是哈哈ha</h2>
       <p>我是内容</p>
     </div>
  `
});

  const app = new Vue({
    el: '#app',
    data: { 
      message: 'helloWorld!'
    },
    //局部注册组件语法糖
    components:{
          'cpn2':{
            template:`
             <div>
              <h2>我是哈哈ha</h2>
              <p>我是内容hhhh</p>
             </div>
             `
           }
          }
    
  });
  </script>
</body>
</html>

父组件和子组件
代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script src="../js/vue.js"></script>
  
  <div id="app">
    <cpn2></cpn2>
    <cpn1></cpn1>
  </div>
  <script>
//1.创建第一个组件构造器(子组件)
const cpnC1 = Vue.extend({
  template:`
       <div>
         <h2>我是内容1</h2>
         <p>我是段落1<p>
       </div>
  `
});
//2.创建第二个组件构造器(父组件)
const cpnC2 = Vue.extend({
template:`
     <div>
       <h2>我是内容2</h2>
       <p>我是段落2<p>
       <cpn1></cpn1>
     </div>
`,
//在这里可以进行组件一(子组件)的注册,然后我们就可以在上边定义模板的时候使用组件一了
components:{
  cpn1:cpnC1
}
});

  const app = new Vue({
    el: '#app',
    data: { 
      message: 'helloWorld!'
    },
    //进行组件二(父组件)的局部注册(注意:这里如果没有对cpn1进行局部注册是不能在这个vue实例里面用的,还是只能在组件二里面使用)
    components:{
      cpn2:cpnC2,
      cpn1:cpnC1
    }
  });
  </script>
</body>
</html>

二、组件通信

父组件传子组件
关键字:props
代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script src="../js/vue.js"></script>
  <template id="cpn">
    <!--在这个模板里就只能用自己定义在props中的变量名-->
    <div>
      <p>{{cmessage}}</p>
      <ul>
        <li v-for=" item in childmovies">{{item}}</li>
      </ul>
    </div>
  </template>

  <div id="app">
    <!--这样就完成了父组件向子组件传递的作用,此时props中的两个变量都有了内容-->
    <!--这里注意一定要用v-bind,不然他会把后边的movies当成字符串来传给自己-->
    <cpn v-bind:childmovies="movies" :cMessage="message"></cpn>
    
  </div>

  <script>
    //父传子通过 props
    const cpn={
      template:'#cpn',
      //这是数组写法,props还有很多写法
      //props:['childmovies','cmessage'],
      props:{
        //类型限制,单独这样写
       //childmovies:Array,
       //cmessage:String,

       //还可提供默认值,另一种写法,对象写法
       cmessage:{
         //类型限制
         type:String,
         //默认值,当没设置父组件的数组传过来,就使用
         default:"aaaaa",
         //表示这个值必须传,不传会报错
         required:true
       },
       childmovies:{
         type:Array,
         //default:["saber","acher"]//如果是数组,用这样的方法来写默认值会报错
         //所以如果类型是对象或者数组就需要用函数的形式来设置默认值
         default(){
           return ["saberxxx","acher"]
         }
       }

      },
      data(){
        return { }
      }
    }

  const app = new Vue({
    el: '#app',
    data: { 
      message: "helloWorld!",
      //下面这个数据是不能给子组件用的,但如果我们要把这数据拿给子组件去展示又怎末办呢
      movies:['海王','欧拉']
    },
    components:{
      cpn
    }
  });
  </script>
</body>
</html>

子组件传父组件
关键字:$emit
代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script src="../js/vue.js"></script>
  <!--子组件模板-->
 <template id="cpn">
   <div>
   <h2>
     {{cinfo}}
   </h2>
   <button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
  </div>
 </template> 

 <!--父组件-->
  <div id="app">
    <!--父组件通过v-on 来监听接受,再通过父组件定义的一个方法来处理-->
    <!--注意这里的方法虽然没加括号但不是默认传递的event事件而是转递了item这个对象-->
    <cpn :cinfo="info" @itemclick="cpnClick"></cpn>
  </div>

  <script>
//子组件
 const cpn={
      template:'#cpn',
      data(){
        return {
          categories:[
            {id:'aaa',name:'hot',age:18},
            {id:'bbb',name:'slow',age:19},
            {id:'ccc',name:'cho',age:20}
          ]
        }   
      },
      props:{
        cinfo:{
          type:Object,
          default(){
            return {}; 
          }
        }
      },
      methods: {
        btnClick(item){
          //这里演示了下点击事件,但是我们要怎样告诉父组件这个事件?
          console.log(item.name);
          //通过这样来告知父组件,通过这种方式发射事件, 这之后还可以添加一个参数 这里是item,
          this.$emit('itemclick',item);
        }
      },
    }
//父组件
  const app = new Vue({
    el: '#app',
    data: { 
      message: 'helloWorld!',
      info:{
        name:'zhangheng',
        age:18,
        height:1.88
      }
    },
    components:{
      cpn
    },
    methods: {
      //测试接受,并打印下item对象
      cpnClick(item){
        console.log(typeof item);
        console.log("子组件你是不是点击了下",item);
      }
    },
  });
  </script>
</body>
</html>

三、组件访问

父访问子
关键字:$children和$refs
代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script src="../js/vue.js"></script>
  <template id="cpn">
    <div>
      <h2>我是子组件</h2>
    </div>
  </template>

  <div id="app">
    <cpn></cpn>
    <cpn ref="aaa"></cpn>
    <button @click="btnClick">点击一下</button>
  </div>
  <script>
  const app = new Vue({
    el: '#app',
    data: { 
      message: 'helloWorld!'
    },
    methods:{
      btnClick(){
        //1.$children的讲解
        //这里的this.$children创建的是一个数组,可以通过这种方式来访问子组件中的属性或者一些方法
        //this.$children[0].showMessage();
        //console.log(this.$children);
        for(let c of this.$children){
          //console.log(c.name);
          c.showMessage();
        }

        //2.$refs的讲解,对象类型,默认是一个空对象。当有组件标签上加上了ref="xxx",这时这个对象才会返回这个组件的一些属性
        //console.log(this.$refs);
        //console.log(this.$refs.aaa.name);
        //this.$refs.aaa.showMessage();
      }
    },
    components:{
      cpn:{
        template:'#cpn',
        data(){
          return {
            name:'我是子组件的name'
          }
        },
        methods: {
          showMessage(){
            console.log("showMessage");
          }
        },
      }
    }
  });
  </script>
</body>
</html>

子访问父
关键字:$parent
代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script src="../js/vue.js"></script>
  <template id="cpn">
    <div>
      <h2>我是子组件</h2>
      <button @click="btnClick">按钮</button>
    </div>
  </template>
  <div id="app">
    <cpn></cpn>
  </div>
  <script>
  const app = new Vue({
    el: '#app',
    data: { 
      message: '我是父的helloWorld!'
    },
    components:{
      cpn:{
        template:'#cpn',
        methods: {
          btnClick(){
            console.log(this.$parent.message);
          }
        },
      }
    }
  });
  </script>
</body>
</html>
Last modification:August 13, 2020
如果觉得我的文章对你有用,请随意赞赏