vue组件化开发08

1. 什么是组件化

将一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,方便页面的管理和维护,且扩展性也更强。


2. 组件化的思想

  1. 我们将一个完整的页面分成很多个组件。
  2. 每个组件都用于实现页面的一个功能块。
  3. 每一个组件又可以进行细分。

Vue提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用,而任何的应用都会被抽象成一颗组件树。
在这里插入图片描述


3. 注册组件的基本步骤

  1. 调用Vue.extend创建组件构造器;
    在创建组件构造器时,传入template代表我们自定义组件的模板,即要显示的HTML代码。
    在这里插入图片描述

  2. 调用Vue.component注册组件;
    将组件构造器注册为一个组件,并为它起一个组件的标签名称。需要传递两个参数:1、注册组件的标签名;2、组件构造器。
    在这里插入图片描述

  3. 在vue实例的作用范围内使用组件。
    组件必须挂载在某个Vue实例下,否则不会生效。

    beatson1生效,beatson2未生效
    在这里插入图片描述


4.全局组件和局部组件

全局组件:通过调用Vue.component注册的组件为全局组件。全局组件可以在任意vue实例中使用。
在这里插入图片描述
局部组件:在某个vue实例中注册的组件为局部组件。局部组件只能在注册组件的那个vue实例中使用。

component:{
    
    
'组件名称': 创建的组件构造器的名称
}

在这里插入图片描述
测试
在这里插入图片描述
全局组件的效果
在这里插入图片描述
在这里插入图片描述
局部组件的效果
在这里插入图片描述

在这里插入图片描述
测试代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>1组件化的基础实现+全局、局部组件</title>
</head>
<body>
    <div id="info1">
<!--      调用组件-->
      <beatson id="beatson1"></beatson>
    </div>
<!--&lt;!&ndash;    需要挂在到某个vue实例下,才生效&ndash;&gt;-->
<!--    <beatson id="beatson2"></beatson>-->
    <div id="info2">
      <beatson id="beatson3"></beatson>
    </div>

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

      // 组件的基本实现
      // 创建组件构造器
      const beatson = Vue.extend({
     
     
        template: `
          <div>
            <p>My name is Daddy!</p>
            <p>His name is Son!</p>
            <p>I want to beat Son!!</p>
            <p>附图一张,不接受反驳!!</p>
            <img src="img/wh%20is%20sb.png" alt="wu is sb">
          </div>
        `
      });
      // // 注册组件,定义组件标签名称,通过Vue注册是组件为全局组件
      // Vue.component('beatson',beatson);

      const info1 = new Vue({
     
     
        el : "#info1",
        data : {
     
     
        },
        // 局部组件
        components: {
     
     
          'beatson': beatson,
        },
      })
      const info2 = new Vue({
     
     
        el : "#info2",
        data : {
     
     
        },
        components: {
     
     
        },
      })
    </script>
</body>
</html>

5. 父子组件

创建孩子组件构造器
在这里插入图片描述
创建父亲组件构造器,并在父组件内部注册子组件
在这里插入图片描述
在vue实例内部注册父组件
在这里插入图片描述
在vue实例中调用父子组件
在这里插入图片描述
效果:子组件实在父组件内被注册的,也只能在父组件内被调用识别。
在这里插入图片描述
在vue实例中调用子组件失败,无法识别。
在这里插入图片描述


6. 组件语法糖+模块分离

以父子组件为例

组件语法糖
在这里插入图片描述
效果
在这里插入图片描述
模块分离
方法一:利用script实现

<script type="text/x-template" id="xxx">
  html代码……
</script>

在这里插入图片描述
方法二:利用template标签实现

<template id="xxx">
</template>

在这里插入图片描述
注意:template后面要注册的组件id名,需要用``包起来!!!不是单引号!!是键盘上tab键上面那个键~ `!!!!!
在这里插入图片描述
效果
在这里插入图片描述
测试代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>3组件语法糖+模板分离</title>
</head>
<body>
<div id="info">
  <father_cpn></father_cpn>
  <child_cpn></child_cpn>
</div>

<!--<script src="../../js/vue.js"></script>-->
<!--  // 组件语法糖:-->
<!--<script>-->
<!--  const info = new Vue({-->
<!--    el : "#info",-->
<!--    data : {-->
<!--      message : "vue yyds"-->
<!--    },-->
<!--    // 在vue实例内部创建并注册父亲组件构造器-->
<!--    components: {-->
<!--      'father_cpn': {-->
<!--        template:`-->
<!--        <div id="father">-->
<!--          <p>我是父组件</p>-->
<!--          <p>我还包含了一个子组件</p>-->
<!--          <child_cpn></child_cpn>-->
<!--        </div>-->
<!--      `,-->
<!--        // 在父组件内部创建并注册孩子组件构造器-->
<!--        components: {-->
<!--          'child_cpn': {-->
<!--            template:`-->
<!--        <div id="child">-->
<!--          <p>我是子组件</p>-->
<!--          <p>我在父组件里面</p>-->
<!--        </div>-->
<!--      `-->
<!--          },-->
<!--        }-->
<!--      }-->
<!--    }-->
<!--  })-->
<!--</script>-->

<!-- 模块分离-->
<!--&lt;!&ndash;方法1:利用script实现&ndash;&gt;-->
<!--<script type="text/x-template" id="fatherCpn">-->
<!--  <div id="father">-->
<!--    <p>我是父组件</p>-->
<!--    <p>我还包含了一个子组件</p>-->
<!--    <child_cpn></child_cpn>-->
<!--  </div>-->
<!--</script>-->
<!--<script type="text/x-template" id="childCpn">-->
<!--  <div id="child">-->
<!--    <p>我是子组件</p>-->
<!--    <p>我在父组件里面</p>-->
<!--  </div>-->
<!--</script>-->

<!--方法2:利用template标签实现-->
<template id="childCpn">
  <div id="child">
    <p>我是子组件</p>
    <p>我在父组件里面</p>
  </div>
</template>
<template id="fatherCpn">
  <div id="father">
    <p>我是父组件</p>
    <p>我还包含了一个子组件</p>
    <child_cpn></child_cpn>
  </div>
</template>

<script src="../../js/vue.js"></script>
<script>
  let info = new Vue({
     
     
    el : "#info",
    data : {
     
     
      message : "vue yyds"
    },
    components: {
     
     
      'father_cpn': {
     
     
        template: `#fatherCpn`,
        components: {
     
     
          'child_cpn': {
     
     
            template: `#childCpn`
          }
        }
      }
    }
  })
</script>
</body>
</html>

7. 组件中的数据存储+组件的data属性必须是一个函数

组件实例都有data属性,该属性是一个函数,返回类型为对象,该对象中存储着组件的数据。
data属性必须是一个函数(返回一个对象,对象中存储组件所需的数据):因为Vue通过data函数使每个组件对象都返回一个新的对象。若共用同一个对象,则多次调用组件时会发生连锁反应互相影响。

以计数器为例

定义计数器组件
在这里插入图片描述
构建并注册计数器组件

通过data函数使每个组件对象都返回同一个对象
在这里插入图片描述

在这里插入图片描述

通过data函数使每个组件对象都返回一个新的对象
在这里插入图片描述

效果:
在这里插入图片描述

测试代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>4组件的数据存储</title>
</head>
<body>
  <div id="info">
    <counter id="counter1"></counter>
    <counter id="counter2"></counter>
  </div>

  <template id="counter">
    <div>
      <p>{
    
    {
    
    num}}</p>
      <button @click="decrement">-</button>
      <button @click="increment">+</button>
    </div>
  </template>
  <script src="../../js/vue.js"></script>
  <script>
    // let counterObj = {
    
    
    //   num: 0,
    // }
    // 计数器组件
    Vue.component('counter',{
    
    
      template: `#counter`,
      // date属性必须为函数,返回一个对象,对象中存储数据
      // 1.通过data函数使每个组件对象都返回一个新的对象
      // data(){
    
    
      //   return counterObj;
      // },
      // 2.通过data函数使每个组件对象都返回一个新的对象
      data(){
    
    
        return {
    
    
          num: 0,
        }
      },
      methods: {
    
    
        increment(){
    
    
          this.num++;
        },
        decrement(){
    
    
          this.num--;
        }
      }
    })

    const info = new Vue({
    
    
      el : "#info",
      data : {
    
    
        message : "vue yyds"
      },
      methods : {
    
    

      }
    })
  </script>
</body>
</html>

8. 组件通信

特别注意:v-bind不支持驼峰标识!!若使用驼峰标识,则需要转化,如:

	userName-> v-bind:user-name

记一次报错

在这里插入图片描述
原因是:不能含大写字母!!
在这里插入图片描述

改成小写字母后运行无bug
在这里插入图片描述
在这里插入图片描述

1. 父传子:props属性

  • 属性是数组: [变量名1,变量名2]
	props: ['username','password'],
  • 属性是对象:{变量名1:类型1,变量名2:类型2}
	props: {
    
    
	  username: String,
	  password: String
	},
  • 属性中包含数据验证:
    类型:type(String、Number、Boolean、Object、Function、Array、Date、Symbol)
    必填:required
    默认值:default
    自定义验证函数:validator
	props:{
    
    
	   username: {
    
    
	     // 类型
	     type: String,
	     // 必填
	     required: true,
	     // 默认值
	     default: "admin",
	     // 对象或数组默认值
          // default: function (){
    
    
          //   return {xxx: "xxx"};
          // }
	   },
	   password: {
    
    
	     type: String,
	     default: "123456",
	     // 自定义验证函数
	     validator: function (value){
    
    
	       return ['123456','root','admin'].indexOf(value) !== -1;
	     }
	   }
	 },

在这里插入图片描述
在这里插入图片描述
测试代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>5组件通信-父传子</title>
</head>
<body>
  <div id="info">
    <logininfo :username="user_name" :password="user_password"></logininfo>
      <div>
        <table>
          <thead>
            <tr>
              <th>用户名</th>
              <th>密码</th>
            </tr>
          </thead>
          <tbody>
            <tr>
              <td>{
   
   {user_name}}</td>
              <td>{
   
   {user_password}}</td>
            </tr>
          </tbody>
        </table>
      </div>
  </div>


<!--  登录组件-->
<template id="logininfo">
  <div>
    <h3>用户登录</h3>
    <form action="">
      <label>
        用户名:<input type="text" name="username" id="username" placeholder="username" :value="username">
      </label>
      <label for="password">
        密码:<input type="text" name="password"  id="password" placeholder="password" :value="password">
      </label>
      <label for="rememberMe">
        <input type="radio" id="rememberMe"> 记住我
      </label>
      <button> 登 录 </button>
    </form>
  </div>

</template>

  <script src="../../js/vue.js"></script>
  <script>
    <!--  子组件-->
    const logininfo = {
     
     
      template: `#logininfo`,
      // 属性是数组: [变量名1,变量名2]
      // props: ['username','password'],

      // 属性是对象:{变量名1:类型1,变量名2:类型2}
      // props: {
     
     
      //   username: String,
      //   password: String
      // },

      // 属性中包含数据验证
      props:{
     
     
        username: {
     
     
          // 类型
          type: String,
          // 必填
          required: true,
          // 默认值
          default: "admin",
          // 对象或数组默认值
          // default: function (){
     
     
          //   return {xxx: "xxx"};
          // }
        },
        password: {
     
     
          type: String,
          default: "123456",
          // 自定义验证函数
          validator: function (value){
     
     
            return ['123456','root','admin'].indexOf(value) !== -1;
          }
        }
      },
    }
    <!--  vue实例看作父组件-->
    let info = new Vue({
     
     
      el : "#info",
      data : {
     
     
        user_name:"wh",
        user_password:"xxxx",
      },
      components: {
     
     
        logininfo,

      },
    })
  </script>
</body>
</html>

2. 子传父:事件

子组件通过 $emit() 将自定义事件传递给父组件
父组件通过 v-on 监听子组件传递的事件
在这里插入图片描述

子组件模板
在这里插入图片描述
定义子组件
通过emit向父组件传递事件时,一定要加上 this.$emit()
在这里插入图片描述
父组件模板
此处当子组件中id为red的对象向父组件发起事件请求,则父组件会默认接收来自子组件的red对象
在这里插入图片描述
定义父组件
在这里插入图片描述
效果:
在这里插入图片描述
测试代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>组件通信-子传父</title>
</head>
<body>
<!--  父组件模板-->
  <div id="info">
    <child @childbtn="btnClick"></child>
  </div>

<!--子组件模板-->
  <template id="child">
    <div>
      <button v-for="item in color"
              @click="childClick(item)">
        {
   
   {item.name}}</button>
    </div>
  </template>

  <script src="../../js/vue.js"></script>
  <script>
    // 子组件
  const child = {
     
     
    template: `#child`,
    data(){
     
     
      return {
     
     
        color: [
          {
     
     id: 'red', name: "红色"},
          {
     
     id: 'blue', name: "蓝色"},
          {
     
     id: 'green', name: "绿色"},
          {
     
     id: 'yellow', name: "黄色"},
        ]
      }
    },
    methods: {
     
     
      childClick(item){
     
     
        this.$emit('childbtn', item);
      }
    }
  }
    // 把vue实例看作父组件
  const info = new Vue({
     
     
    el : "#info",
    components: {
     
     
      child,
    },
    methods : {
     
     
      btnClick(item){
     
     
        console.log('btnClick', item);
      }
    }
  })
  </script>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/weixin_44836362/article/details/114684919