vue学习笔记(六) ----- vue组件

一、模块化与组件化

  • 模块化的定义

模块化在Node中是一个规范,定义一些模块的相关的规则,从代码角度上来说,方便做区别,如果不使用模块化,写在js文件中不利于后期维护和扩展,从代码的层面上就把相关的功能脱离出来,所以模块化从从代码的角度触发,分析项目,把项目中一些功能类型的代码,单独抽离为一个个的模块,那么为了保证大家以相同的方式去封装模块,于是我们就创造了CommentJS规范

  • 模块化的优点

在我们项目中,如果需要是实现相同的功能,就不需要再重写,所以模块化从一定程度上提高我们的开发效率,有一些相关模块,直接调用就可以了,方便项目开发,和后期的维护与扩展

  • 组件化:

把页面中样式差不多的东西抽为单独的小组件,把需要经常复用的东西封装为一个单独的,今后需要用的时候直接拿就可以,不用再重写,从ui的角度触发去考虑问题,把页面中代码结构类似的区域抽离出来,封装成一个单独的小组件 ;前端的组件化,方便UI组件的重用;

  • 组件化的优点:

随着项目规模的发展,我们手中的组件会越来越多,我们今后一个页面的ui,几乎都可以从手中拿现成的组件拼接出来,方便项目的开发和维护

二、创建全局组件的方式

1. 创建全局组件的方式一

  1. 先调用 Vue.extend()得到组件的构造函数
 var com1 = Vue.extend({
     
        template: '

这是创建的第一个全局组件

'
// template 属性,表示这个组件的 UI 代码解构 })
  1. 通过vue.component('组件的名称',组件的构造函数)来注册全局组件
    Vue.component('mycom1', com1)
    //com1就是组件的构造函数

注意:
组件的名称如果是驼峰命名,那么引入的时候表名称得加连字符 -
1.如果 Vue.component(‘myCom1’,‘com1’)
对应的组件标签是
2. 如果是Vue.component(‘myCom1Test’,‘com1’)
对应组件标签为:
3. 如果Vue.component(‘my-com1’,‘com1’)
对应组件标签为:

  1. 把注册好的组件名称,以标签的形式引入到vm实例区域的页面中即可
<div id="app">

    <mycom1>mycom1>
div>

来吧展示:

vue学习笔记(六) ----- vue组件_第1张图片

2. 创建全局组件的方式二

  1. 直接使用vue.component('组件的名称','组件对象')
// Vue.component 的第二个参数,既接收 一个 组件的构造函数, 同时,也接受 一个对象
 Vue.component('mycom2', {
     
     template:'

这是直接使用 Vue.component 创建出来的组件

'
})
  1. 把注册好的组件名称,以标签的形式引入到vm实例区域的页面中即可
<div id="app">
    <mycom2>mycom2>
div>

来吧展示:

vue学习笔记(六) ----- vue组件_第2张图片

注意:
1.template 属性中,不能单独放一段文本,必须用标签包裹起来;
2. 如果在 template 属性中,想要放多个元素了,那么,在这些元素外,必须有唯一的一个根元素进行包裹;

Vue.component('mycom2', {
     
     template:'

嘿嘿嘿嘿嘿

这是直接使用 Vue.component 创建出来的组件

哈哈哈哈

'
})

vue学习笔记(六) ----- vue组件_第3张图片

3. 创建全局组件的方式三

  1. template添加一个id选择器
Vue.component('mycom3', {
     
        template: '#tpl'
})
  1. 定义一个 template 标签元素
    使用 Vue 提供的 template 标签,可以定义组件的UI模板解构
<div id="app">
   <mycom3>mycom3>
div>
<template id="tpl">
    <h2>这是创建全局组件的第三种方式h2>
template>

vue学习笔记(六) ----- vue组件_第4张图片

注意:
template标签中里面也必须有唯一的一个根元素进行包裹
也就是如果没有根元素包裹,那么下面代码是执行不出来了会报错

<template id="tmpl">
        <h2>这是创建全局组件的第三种方式h2>
        <p>哟哟哟哟哟哟p>
template>

正确写法:

<template id="tmpl">
    <div>
        <h2>这是创建全局组件的第三中方式h2>
        <p>嘿嘿嘿嘿嘿嘿嘿嘿嘿嘿p>
    div>
template>

vue学习笔记(六) ----- vue组件_第5张图片
既然是全局组件,那么就可以重复调用,栗子:

<div id="app">
<mycom3>mycom3>
div>
<div id="app2">
    <mycom3>mycom3>
div>
<template id="tmpl">
        <h2>这是创建全局组件的第三中方式h2>
template>

<script>
    Vue.component('mycom3', {
      
        template: '#tmpl'
    })
    var vm = new Vue({
      
        el: '#app',
    });
    var vm2 = new Vue({
      
        el: '#app2',
    });
script>

vue学习笔记(六) ----- vue组件_第6张图片

三、创建私有组件

创建一个私有组件

<div id="app">
    <mycom4>mycom4>
div>
var vm = new Vue({
     
      el: '#app',
      data: {
     },
      methods: {
     },
      components: {
      
      // 定义实例中私有组件的   组件的名称   和组件的 解构
        'mycom4': {
     
          template: '
这是定义的私有组件
'
} } });

创建多个私有组件:

<div id="app">
    <mycom4>mycom4>
    <mycom5>mycom5>
div>
components:{
     
            mycom4:{
     
                template:'

这是我定义的私有组件1

'
}, mycom5:{ template:'

这是我定义的私有组件2

'
} }

vue学习笔记(六) ----- vue组件_第7张图片

四、组件中相应数据和展示方法

 Vue.component('mycom', {
     
        template: '

这是自定义的全局组件 ------ { { msg }}

'
, data: function () { // // 在 组件中,可以有自己的私有数据 // 但是,组件的 data 必须是一个 function // 并且内部 return 一个 数据对象 return { msg: '我是组件的内部data' } }, methods: { // 尝试定义组件的私有方法 show() { // console.log('出发了组件的私有show方法!') alert('我是组件内部的方法') } } })

vue学习笔记(六) ----- vue组件_第8张图片

思考:
为什么要把 组件中的 data 定义为一个function呢?
因为这样做的话,每当我们在页面上引用一次组件,必然会先调用 这个 data function,
从而得到一个当前组件私有的 数据对象;

五、切换组件

1. 结合flag标识符和 v-ifv-else 实现组件的切换

<div id="app">

    <input type="button" value="显示登录" @click="flag=true"/>
    <input type="button" value="显示注册" @click="flag=false"/>
  <login v-if="flag">login>


    <res v-else="flag">res>
div>
<script>
    Vue.component('login', {
      
        template: '

登录

'
}) Vue.component('res', { template: '

注册

'
}) // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data:{ flag:false }, methods:{ } })
script>

vue学习笔记(六) ----- vue组件_第9张图片

2. 切换多个组件

<div id="app">

   <component :is="'com1'">component>
   <component :is="'com3'">component>
    
div>
Vue.component('com1', {
     
        template: '

我是第1个组件

'
}) Vue.component('com2', { template: '

我是第2个组件

'
}) Vue.component('com3', { template: '

我是第3个组件

'
}) Vue.component('com4', { template: '

我是第4个组件

'
})

vue学习笔记(六) ----- vue组件_第10张图片
进行多组件的切换

<div id="app">

    <a href="#" @click="comname='com1'">显示组件1a>
    <a href="#" @click="comname='com2'">显示组件2a>
    <a href="#" @click="comname='com3'">显示组件3a>
    <a href="#" @click="comname='com4'">显示组件4a>
    
    <component :is="comname">component> 
div>
 var vm = new Vue({
     
        el: '#app',
        data:{
     
            comname:'com1'
        },
//当vue解析文件到component标签时,如果有:is属性就会解析后面的字符串"comname"
//然后去data中寻找这个变量 
//comname:'com1'
//正好是一个字符串的变量的名称,就会显示名称叫com1的组件
        methods:{
     }
 })

vue学习笔记(六) ----- vue组件_第11张图片

3.为组件切换添加动画

 <transition>
        <component :is="comname">component>
    transition>
<style>
        .v-enter,
        .v-leave-to{
      
            opacity:0;
            transform: translate(100px);
        }
        .v-enter-active,
        .v-leave-active{
      
            transition: all 0.4s ease;      
        }
style>

vue学习笔记(六) ----- vue组件_第12张图片
如上图效果显示,有标准流的影响,所以要脱离标准流的影响,让离开的组件脱离标准流

<style>
.....

.v-enter-active,
        .v-leave-active{
      
            transition: all 0.4s ease;
            position: absolute;
 }
 style>

vue学习笔记(六) ----- vue组件_第13张图片
如图动画效果是先进入再离开,如果想要实现先离开再进入,则只需要在transition中添加mode="out-in"

 <transition mode="out-in"> -
        <component :is="comname">component>
 transition>

vue学习笔记(六) ----- vue组件_第14张图片
如果想要实现离开往左走,进入往右走的效果,则:

<style>
       .v-enter {
      
            /* 即将进入时候的坐标 */
            opacity: 0;
            transform: translateX(100px);
        }

        .v-leave-to {
      
            /* 离开时候,最终到达的位置 */
            opacity: 0;
            transform: translateX(-100px);
        }
style>

vue学习笔记(六) ----- vue组件_第15张图片

六、父组件通过属性绑定向子组件传递数据

  1. 把要传递给子组件的数据,作为自定义属性,通过v-bind绑定到子组件身上
 <com :sonmsg="pmsg">com>
  1. 在子组件中,不能直接使用父组件传递过来的数据,需要先用props 来接收一下
   props: ['sonmsg']
  1. 在接收父组件传递过来的props的时候,一定要和父组件中传递过来的自定义属性名称保持一致
 template: '

我是子组件-----{ {sonmsg}}

'
,

具体代码如下:

<body>
<div id="app">
    <com :sonmsg="pmsg">com>



div>

<script>
    var vm = new Vue({
      
        el: '#app',
        data: {
      
           pmsg:'我是父组件中的数据'
        },
        methods: {
      },
        components: {
       // 定义私有组件
            'com': {
       // 在Vue中,默认,子组件无法直接获取父组件中的数据
                template: '

我是子组件-----{ {sonmsg}}

'
, props: ['sonmsg'] // 在Vue中,只有 props 是数组,其它带 s 后缀的属性都是 对象 } } });
script> body>

vue学习笔记(六) ----- vue组件_第16张图片

七、父组件向子组件传递对象

  1. 把要传递给子组件的对象,作为自定义属性,通过v-bind绑定到子组件身上
  <com1 :msgobj123="msgObj">com1>
  1. 在子组件中,不能直接使用父组件传递过来的对象,需要先用props 来接收一下
 props: ['msgobj123']
  1. 在接收父组件传递过来的props的时候,一定要和父组件中传递过来的自定义属性名称保持一致
 template: '

后面传递的是父组件中对象 ---- { { JSON.stringify(msgobj123) }}

'
template: '<h3>哈哈 {
    { JSON.stringify(msgobj) }}h3>',

具体代码如下:

<body>
<div id="app">
    <com1 :msgobj123="msgObj">com1>
div>
<script>
    var vm = new Vue({
      
        el: '#app',
        data: {
      
            msgObj: {
      
                id:1,
                name:'千夏Chinatsu',
                age:18
            }
        },
        methods: {
      },
        components: {
      
            'com1': {
      
                template: '

后面传递的是父组件中对象 ---- { { JSON.stringify(msgobj123) }}

'
, props: ['msgobj123'] } } });
script> body>

vue学习笔记(六) ----- vue组件_第17张图片

八、父组件向子组件传递方法

  1. 把要传递给子组件的方法,通过v-on绑定事件到子组件身上
<com v-on:func="show()">com>
  1. 在子组件中,不能直接使用父组件传递过来的方法,需要先用$emit() 来接收一下
  this.$emit('func')
  1. 在接收父组件传递过来的$emit()中,一定要和父组件中传递过来的方法名称保持一致

具体代码:

<body>
<div id="app">
    <com v-on:func="show()">com>
div>

<script>
    var vm = new Vue({
      
        el:'#app',
        data:{
      },
        methods:{
      
            show(){
      
                console.log('触发了父组件中的show()方法')
            }
        },
        components: {
      
            'com': {
      
                template: '',
                methods:{
      
                    btnClick(){
      
                        // console.log('hhhh')
                        this.$emit('func')
                    }
                }

            }
        }
    })
script>
body>

vue学习笔记(六) ----- vue组件_第18张图片

总结:
1.如果要向子组件传递 data 中的数据,则 使用 属性绑定的形式 v-bind:
2. 如果要向子组件传递 methods 中的 方法,则 使用 事件绑定的形式 v-on:

九、子组件向父组件传递数据

<body>
<div id="app">

    <com v-on:func="show">com>




div>
<script>
    var vm = new Vue({
      
        el:'#app',
        data:{
      },
        methods:{
      
            show(arg){
      
                console.log('触发了父组件中的show()方法' + arg)
                // '--------'
            }
        },
        components: {
      
            'com': {
      
                template: '',
                data:function(){
      
                    return{
      
                        sonmsg:'这是子组件中的数据'
                    }
                },
                methods:{
      
                    btnClick(){
      
                        this.$emit('func','嘿嘿嘿嘿嘿')
                    }
                }

            }
        }
    })
script>
body>

vue学习笔记(六) ----- vue组件_第19张图片
所以可以直接在show()方法中传入子组件中的data数据

methods:{
     
            show(arg){
     
                console.log('触发了父组件中的show()方法' +'--------'+ arg)
                // '--------'
            }
        },
components: {
     
            'com': {
     
                template: '',
                data:function(){
     
                    return{
     
                        sonmsg:'这是子组件中的数据'
                    }
                },
                methods:{
     
                    btnClick(){
     
                        // console.log('hhhh')
                        this.$emit('func','嘿嘿嘿嘿嘿')
                        // this.$emit('func',this.sonmsg)
                    }
                }

            }
        }

vue学习笔记(六) ----- vue组件_第20张图片
把子组件传递过来的数据,保存到 父组件的 data 中

methods: {
     
        show(arg) {
     
          // console.log('触发了父组件中的show()方法' +'--------'+ arg)
          // 把子组件传递过来的数据,保存到 父组件的  data 中
          this.msgFormSon = arg
          console.log(this.msgFormSon)
        }
 },

总结:
子组件向父组件传值,本质上,还是调用了父组件传递过来的方法
只不过,子组件在调用的时候,把 数据 当作参数,传给这个方法了;

十、练习列表案例(结合父子组件传值)

<body>
  <div id="app">
    
    <cmt-box @func="addNewCmt">cmt-box>
    <ul>
      <cmt-item v-for="(item, i) in list" :item="item" :key="i">cmt-item>
    ul>
  div>
  <script>

    Vue.component('cmt-item', {
      
      template: `
  • 评论人:{ { item.name }}

    评论内容:{ { item.content }}
  • `
    , props: ['item'] }) Vue.component('cmt-box', { template: `




    `
    , data: function () { return { name: '', content: '' } }, methods: { postComment() { // 发表评论 // console.log('ok') const cmt = { name: this.name, content: this.content } // 子组件中,调用父组件传递过来的方法,然后可以把 子组件的数据,当作参数,传递给父组件的方法去使用 this.$emit('func', cmt) this.name = this.content = '' // console.log(cmt) } } }) var vm = new Vue({ el: '#app', data: { list: [ { name: 'zs', content: '沙发' }, { name: 'ls', content: '板凳' }, { name: 'qqq', content: '凉席' }, { name: 'eee', content: '砖头' } ] }, methods: { addNewCmt(cmt) { // 添加新评论 // console.log(cmt) this.list.push(cmt) } } });
    script> body>

    十一、使用ref属性来获取页面中的元素

    <body>
    
    <div id="app">
     <input value="按钮" type="button" @click="show()"/>
        
        
         <h2 id="myh2" ref="hhh">{
        {msg}}h2>
    div>
    
    <script>
        var vm = new Vue({
          
            el:'#app',
            data:{
          
            msg:'嘿嘿嘿嘿嘿'
            },
            methods:{
          
                show(){
          
                //原生想要获取h2中的数据的方法
                   // var res = document.getElementById('myh2').innerHTML
                   //console.log(res)
                    console.log(this)
                    console.log(this.$refs.hhh)
                    console.log(this.$refs.hhh.innerHTML)
                    
                }
            }
           })
    
    
    script>
    body>
    

    在h2标签中没有加入ref属性的打印console.log(this)结果

    vue学习笔记(六) ----- vue组件_第21张图片
    在h2标签加入ref属性的打印console.log(this)结果
    vue学习笔记(六) ----- vue组件_第22张图片
    所以可以通过ref可以很方便的来获取元素

     console.log(this)
     console.log(this.$refs.hhh)
     console.log(this.$refs.hhh.innerHTML)
                    
    

    vue学习笔记(六) ----- vue组件_第23张图片

    十二、使用ref属性来获取页面中的组件

    vue学习笔记(六) ----- vue组件_第24张图片
    vue学习笔记(六) ----- vue组件_第25张图片
    所以可以根据msg去修改组件内部的数据或者调用子组件中的方法

    <body>
    
    <div id="app">
        <input value="按钮" type="button" @click="getCom()" />
        <com1 ref="xxxxx">com1>
    
    div>
    <script>
        Vue.component('com1', {
          
            template:'

    这是一个小组件---{ {msg}}

    '
    , data:function () { return { msg:'这是组件内部数据' } }, methods:{ show(){ console.log('子组件中的方法被调用了') } } }) var vm = new Vue({ el:'#app', data:{ msg:'这是父组件的数据' }, methods:{ getCom(){ // console.log(this) this.$refs.xxxxx.msg = '组件内部数据被修改了' this.$refs.xxxxx.show() } } }) //页面上可以为很多元素创建ref的引用
    script> body>

    vue学习笔记(六) ----- vue组件_第26张图片

    十三、在vue组件中data和props的区别

    • data 在组件中,要被定义成一个function,并且要返回一个对象
    • props 在组件中,要被定义成数组,其中,数组的值都是字符串名,表示从父组件传递过来的数据
    • props中的数据,不要直接拿来修改,如果想要修改,必须在data上重新定义一个属性,然后把属性的值从this.props直接拿过来
    • data 上的数据,都是组件自己私有的,数据都是可读可写的
    • props都是外界传递过来的数据,数据只能读取,不能重新写入

    你可能感兴趣的:(Vue学习笔记,vue)