美文网首页
Vue组件化初体验

Vue组件化初体验

作者: cj_jax | 来源:发表于2018-12-26 23:54 被阅读0次

认识组件

组件化开发:

​ 将一个完成的页面,划分成一个个的组件,最终由一个个组件来完成整个页面你的开发,这个过程就是组件化开发

优势:复用!!

​ 也就是说组件只需要写一次,然后,用到组件的地方,只需要拿过去用就可以了

组成

一个组件由三部分组成:HTML+CSS+JS

两种注册组件的方式:

​ 1 全局组件

​ 2 局部组件

注册全局组件:

​ 第一个参数:表示组件名称

​ 第二个参数:是一个配置对象,这个配置对象类似于 Vue 构造函数中使用的配置对象

​ 也就是说:在 Vue 构造函数中能够使用的配置项,几乎都可以用在组件中

template 作用:指定组件模板

​ 注意:只能出现一个根节点

通过 data 指定组件中用到的数据

​ 注意:组件中的数据data,是一个方法,通过方法的返回对象来作为组件数据

我的第一个全局组件

<!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>
  </head>

  <body>
    <div id="app">
      <!-- 使用组件: -->
      <hello></hello> <hello></hello> <hello></hello> <hello></hello>
    </div>

    <script src="./vue.js"></script>
    <script>
      /* 
        两种注册组件的方式:
        1 全局组件
        2 局部组件

        一个组件由三部分组成:HTML+CSS+JS
      */

      // 注册全局组件:
      // 第一个参数:表示组件名称
      // 第二个参数:是一个配置对象,这个配置对象类似于 Vue 构造函数中使用的配置对象
      //  也就是说:在 Vue 构造函数中能够使用的配置项,几乎都可以用在组件中
      Vue.component('hello', {
        // template 作用:指定组件模板
        // 注意:只能出现一个根节点
        template: `
          <div>
            <h1>这是我的第一个组件 - Hello 组件</h1>
            <span @click="fn">{{ msg }}</span>
          </div>
        `,

        // 通过 data 指定组件中用到的数据
        // 注意:组件中的数据data,是一个方法,通过方法的返回对象来作为组件数据
        data() {
          return {
            msg: 'Vue Component data'
          }
        },

        // 钩子函数
        created() {
          console.log('created 钩子函数执行了')
        },
        // 方法
        methods: {
          fn() {
            console.log('方法执行了')
          }
        }
      })
      const vm = new Vue({
        el: '#app',
        data: {}
      })
    </script>
  </body>
</html>

注册局部组件

​ 通过配置项 components: {}

//html
 <div id="app">
      <item></item>
      <wang></wang>
  </div>
  
  //js
   Vue.component('wang',{
      template:`
      <p>我是王婷,<ting></ting></p>
      `,
      components:{
        //组件名称
        ting:{
          //组件模板
          template:`
            <span>我最美,{{wt}}</span>
          `,
          //组件使用的数据
          data(){
            return {
              wt:'确认过眼神,这是真的'
            }
          }
        }
      }
    });
    const vm = new Vue({
      el: '#app',
      data: {
        msg:''
      },
      components:{
        item:{
          template:`
            <p>我是一个局部的组件:{{chang}}</p>
          `,
          data(){
            return{
              chang:'验证通过'
            }
          }
        }
      }
    })
两中组件的区别

​ 1.全局组件可以在任意的地方使用

​ 2.局部组件只能在所属组件的 模板 中使用

使用组件

组件使用中的细节点:

表单/ul/ol等中指定的标签

产生的原因:在tbody中只能使用tr标签,使用其他的标签,浏览器解析的时候,会把其他标签作为table外部标签解析出去,结构就会发生分离,ul和ol也是如此

使用is解决问题,例如tr标签

//html
<table>
    <tbody>
        <tr is=chang></chang>
    </tbody>
</table>

//js

Vue.component('chang', {
    template: `
        <tr>
            <td>常杰</td>
            <td>李想</td>
            <td>老丁</td>
        </tr>
    `
});

使用ref属性获取dom对象

//html
  <div id="app">

    <table>
      <tbody>
        <tr is=chang>
          </chang>
        
      </tbody>
    </table>
  </div>

//js
Vue.component('chang', {
      template: `
        <tr>
          <td ref='hello' @click="handler">{{current}}</td>
        </tr>
      `,
      data(){
        return{
          current:'常杰'
        }
      },
      methods:{
        handler(){
          // alert('你触发了点击事件');
          console.log(this.$refs.hello)
        }
      }
    });
组件通讯:

​ 组件是一个独立且封闭的个体,也就是说:默认情况下,组件只能使用自身的数据,而不能使用外部的数据

​ 但是,在组件化开发过程中,两个组件通讯( 也就是两个组件使用对方法的数据 ),是很常见的问题。

​ 这种问题就需要通过 组件通讯 机制来解决

组件通讯的三种情况:

​ 1 父组件 传递数据给 子组件

​ 2 子组件 传递数据给 父组件

​ 3 非父子组件(兄弟组件)

父 -->子通讯:

​ 父组件: Vue实例

​ 子组件: child组件

步骤:

​ 1 在子组件标签中添加要传递的属性

  <child msg="123"></child> msg就是要传递的属性
  <child :msg="parentMsg"></child> 表示传递动态数据给子组件

​ 2 在子组件中通过 props 显示指定要接受的属性

​ props: ['msg']

​ 3 此时,就可以在子组件中直接使用 msg 这个数据了

<!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>
    <style>
      .parent {
        background-color: hotpink;
        padding: 50px;
      }

      .child {
        background-color: #daa520;
        height: 100px;
      }
    </style>
  </head>

  <body>
    <div id="app" class="parent">
      父组件:{{ parentMsg }}
      <!-- 渲染子组件: -->
      <!-- <child msg="123"></child> -->
      <!-- <child msg="parentMsg"></child> -->

      <!-- 表示将父组件中的数据 parentMsg 传递给子组件 -->
      <child :msg="parentMsg"></child>
    </div>

    <script src="./vue.js"></script>
    <script>
      // 注册子组件
      Vue.component('child', {
        template: `
          <div class="child">
            <p>这是子组件 - {{ msg }}</p>
          </div>
        `,

        // 组件中通过 props 配置项,来显示指定要接受的数据
        props: ['msg']
      })

      const vm = new Vue({
        el: '#app',
        data: {
          parentMsg: '这是父组件中的数据'
        }
      })
    </script>
  </body>
</html>

子 -->父通讯

·思路:父组件提供一个方法,让子组件调用,子组件调用方法的时候将数据作为参数传递,这样,父组件就拿到子组件中传递过来的数据了

​ function parent(data) {

​ console.log('子组件中传递过来的数据:', data)

​ }

​ 子组件调用方法: parent( '要传递给父组件的数据' )

实现子组件给父组件传值的过程

​ 1.首先给父组件注册一个方法,同时在data设置一个变量准备接收子组件传出的值

​ 2.给子组件的标签上绑定自定义事件,并把方法作为事件函数传入

​ 3.在子组件中设置模板。在模板中设置事件,触发子组件的方法,在子组件的方法中,获取到传入的自定义事件,并且触发这个事件,传递参数

​ 4.子组件触发这个方法,并把数据作为方法的参数传出

​ 5.在父组件中处理触发事件的操作

//html
  <div id="app">

    我儿子给我发的信息:{{msg}}
    <!-- 2.给子组件的标签上绑定自定义事件,并把方法作为事件函数传入 -->
    <son @pmsg="fn"></son>
  </div>
  
  //js
  Vue.component('son',{
      // 3.在子组件中设置模板。在模板中设置事件,触发子组件的方法,在子组件的方法中,获取到传入的自定义事件,并且触发这个事件,传递参数
      template:`
        <p>我要给老爸发信息
          <button @click="send">发送信息</button>
        </p>
      `,
      // 4.子组件触发这个方法,并把数据作为方法的参数传出
      methods:{
        send(){
          this.$emit('pmsg',"老爸,我资金有点....")
        }
      }
    });

    const vm = new Vue({
      el: '#app',
      data: {
        msg:'没啥用,就占个位'
      },
      // 1.首先给父组件注册一个方法,同时在data设置一个变量准备接收子组件传出的值
      methods:{
        // 5.在父组件中处理触发事件的操作
        fn(data){
          this.msg = data
        }
      }
    })
小案例:

计数器实现的步骤

  • 1.首先创建一个子组件count
  • 2.在组件中创建模板,在模板中绑定事件handler,插入数据num
  • 3.在组件中创建模板中调用的方法handler
  • 4.在模板中设置数据num
  • 5.在组件标签上注册事件change,并绑定handlerChange方法(非常重要)
  • 6.在组件标签上添加属性ref为one/two(非常重要)
  • 7.在Vue实例中,添加方法handlerChange,并通过this.$refs.绑定的名称获取数据
  • 8.获取到子组件的数据进行操作
<!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>
</head>

<body>
  <div id="app">
      <!-- 5.在组件标签上注册事件change,并绑定handlerChange方法(非常重要) -->
      <!-- 6.在组件标签上添加属性ref为one/two(非常重要) -->
    <count ref="one" @change="handlerChange"></count>
    <count ref="two" @change="handlerChange"></count>

    <div>{{total}}</div>
  </div>
  <script src="./vue.js"></script>
  <script>
    // 1.首先创建一个子组件count
    Vue.component('count',{
      // 2.在组件中创建模板,在模板中绑定事件handler,插入数据num
      template:`
        <div @click="handler">{{num}}</div>
      `,
      // 4.在模板中设置数据num
      data(){
        return {
          num: 0
        }
      },
      // 3.在组件中创建模板中调用的方法handler
      methods:{
        handler(){
          this.num++;
          this.$emit("change")
        }
      }
    });
    const vm = new Vue({
      el: '#app',
      data: {
        total: 0
      },
      // 7.在Vue实例中,添加方法handlerChange,并通过this.$refs.绑定的名称获取数据
      methods:{
        handlerChange(){
          // console.log("handlerChange执行了")
          // console.log(this.$refs.one.num)
          // console.log(this.$refs.two.num)

          // 8.获取到子组件的数据进行操作
          this.total = this.$refs.one.num + this.$refs.two.num
        }
      }
    })
  </script>
</body>

</html>
其他通讯(非父子)

思路:

1 创建一个事件总线(空的Vue实例 bus)

​ 2 哪个组件要接收数据,就注册事件

​ bus.$on(事件名称, () => {})

​ 3 哪个组件要传递数据,就触发事件

​ bus.$emit(事件名称, 要传递的数据)

注意: 注册和触发事件的 bus 是同一个,事件名称也要相同

实际上,不管两个组件是什么关系,都可以通过 bus 方式来实现通讯!

步骤:

​ 1.首先创建一个 空的vue实例的对象 bus

​ 2.然后创建两个组件,一个临时用于接收 (wang) ,一个临时用于发送数据 (chang)

​ 3.给两个组件设置好模板内容

​ 4. 组件chang设置方法,在方法中通过bus.$emit获取事件,并设置触发事件的参数

​ 5.在组件wang的钩子函数created中声明创建事件listen,并设置获取到参数后的处理

​ 注意点:虽然用不到vm但是,必须声明创建这个实例,只有指定了vue的边界,代码才能生效

//html
    <div id="app">
      <chang></chang>
      <wang></wang>
    </div>
    
//js
 // 空Vue实例
      // 事件总线
      // 1.首先创建一个 空的vue实例的对象 即事件总线bus
      let bus = new Vue();
      // 2.然后创建两个组件,一个临时用于接收 (wang) ,一个临时用于发送数据 (chang)
      Vue.component('chang',{
        // 3.给两个组件设置好模板内容
        template:`
        <p>我是常杰,我想对王婷说:<button @click="fn">加密发送</button></p>
        `,
        // 4. 组件chang设置方法,在方法中通过bus.$emit获取事件,并设置触发事件的参数
        methods:{
          fn(){
            bus.$emit('listen','那天我一直在等你')
          }
        }
      });
      Vue.component('wang',{
        template:`
        <p>我是王婷,常杰对我说:{{msg}}</p>
        `,
        data(){
          return {
            msg:'接收信息中,请等待...'
          }
        },
        // 5.在组件wang的钩子函数created中声明创建事件listen,并设置获取到参数后的处理
        created(){
          bus.$on('listen',data=>{
            this.msg = data
          })
        }
      });
    //没有用到数据,但是必须声明
      const vm = new Vue({
        el:"#app",
        data:{
        }
      });

细节补充

props的属性

​ props:是只读的,在组件中使用的时候,只能读取,不能修改props的值( 赋值

)如果修改这个值,会报错!!!

​ 如果props是一个引用类型的数据,不能直接赋值,但是,可以修改引用类型中某个属性的值。

单向数据流:

​ 是说组件之间数据流动方向是从 父组件流动到 子组件

​ 父组件可以通过 props 将数据传递给子组件,并且,当父组件中的这个数据改变

后,这个改变后的数据会自动的再流动到子组件中。也就是说:子组件会自动接收到最

新的props数据,并且自动更新

​ 总结:

​ 1.props是只读的属性,只能读取props的值,而不能直接修改props的值

​ 如果是引用类型(对象、数组),可以直接修改对象中某个属性的值,但是,如果要求很严谨,也不应该直接修改对象中某个属性的值!!!

​ 2.单项数据流: 两个组件之间的数据流动方向,方向是: 父 -> 子

命名

HTML 标签或属性都是不区分大小写的(大小写不敏感的)

​ 不管你写的是大写字母的标签名或属性名,还是小写的,最终,都会被转化为小写字母

​ 同样的,在 Vue 中,给组件传递属性的时候,如果属性名中包含大写字母,在解析的时候,也会被转化为小写字母,再作为属性传递给组件

​ 如何给props命名:

​ 1 使用纯小写字母

​ <hello :childmsg="parentMsg"></hello>

​ props: ['childmsg']

​ 2 传递属性的时候,使用短横线连接多个单词,在子组件中通过 驼峰命名法 来接收这个数据(规范)

​ 传递(短横线连接) <hello :child-msg="parentMsg"></hello>

​ 接收(驼峰命名法) props: ['childMsg']

相关文章

  • ★2019 前端进阶之路★Vue 组件间通信实战干货!

    初体验 Vue.js 在现今使用有多广泛不用多说,而 Vue 的一大特点就是组件化。本期要讲的,便是 Vue 组件...

  • Vue组件化初体验

    认识组件 组件化开发: ​ 将一个完成的页面,划分成一个个的组件,最终由一个个组件来完成整个页面你的开发,这个...

  • Vue实现前后端分离项目的初体验

    Vue实现前后端分离项目的初体验 经过之前学习的Vue的知识: vue基本指令 vue组件 vue-resourc...

  • Vue组件和父子组件

    【一】Vue组件化 创建组件构造器对象Vue.extend() 创建组件构造器const cpnc = Vue.e...

  • Vue.js的组件化思想 —上

    一、Vue中的组件 Vue视图层的灵魂 — 组件化 组件(Component)是 Vue.js 最强大的功能之一...

  • (15)打鸡儿教你Vue.js

    组件化vue.js 组件单向绑定组件双向绑定组件单次绑定 创建组件构造器注册组件使用组件 Vue.extend()...

  • 大话大前端时代(一) —— Vue 与 iOS 的组件化

    大话大前端时代(一) —— Vue 与 iOS 的组件化 大话大前端时代(一) —— Vue 与 iOS 的组件化

  • vue

    1、什么是组件化、有什么好处、vue如何创建组件、vue组件之间如何通信 什么是组件化。任何一个页面我们都可以抽象...

  • Vue组件化

    定义Vue组件化 什么是组件化:组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的...

  • vue知识回顾

    一、vue的初体验1.1 初始vue1.2 安装vue1.3 vue的初体验hello.vuejs:mustach...

网友评论

      本文标题:Vue组件化初体验

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