vue学习笔记5 组件

全局组件的使用

        //1 创建组件构造器对象
        const cpnContructor =  Vue.extend({
            template:`
                        <div>
                            <h2>我是标题</h2>
                            <p>我是内容</p>
                        </div>`
        })
        //2 注册组件
        Vue.component('my-cpn',cpnContructor)
        
        
        const app = new Vue({
            el:"#app"
        })
<div id="app">
            <my-cpn></my-cpn>
            <my-cpn></my-cpn>
        </div>

全局组件,意味着可以在多个Vue实例下面使用

局部组件

只能在单个实例里使用

    <body>
        <div id="app">
            <cpn></cpn>
        </div>
        
    </body>
    <script>

        //1 创建组件构造器对象
        const cpnContructor =  Vue.extend({
            template:`
                        <div>
                            <h2>我是标题</h2>
                            <p>我是内容</p>
                        </div>`
        })
        //2 注册组件(全局组件,意味着可以在多个Vue实例下面使用)
        //Vue.component('my-cpn',cpnContructor)
        const app = new Vue({
            el:"#app",
            components:{
                //使用组件时的标签名:组件构造器
                cpn:cpnContructor
            }
        })
    </script>
View Code
const app = new Vue({
            el:"#app",
            components:{
                //使用组件时的标签名:组件构造器
                cpn:cpnContructor
            }
        })

 父组件与子组件

    <body>
        <div id="app">
            <cpn2></cpn2>
        </div>
    </body>
    <script>
        //1 创建第一个组件构造器(子组件)
        const cpnC1 = Vue.extend({
            template:`
            <div>
                <h2>我是标题1</h2>
                <p>我是内容 哈哈哈</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",
            components:{
                //使用组件时的标签名:组件构造器
                cpn2:cpnC2
            }
        })
    </script>
View Code

组件的语法糖注册方式

主要省去了Vue.extend()的步骤,可以直接使用一个对象代替

   <body>
        <div id="app">
            <cpn1></cpn1>
            <cpn2></cpn2>
        </div>
    </body>
    <script>
        const cpn1 = {
            template:`
            <div>
                <h2>我是标题1</h2>
                <p>我是全局组件的语法糖</p>
            </div>
            `
        }
        const cpn2 = {
                        template:`
                        <div>
                            <h2>我是标题2</h2>
                            <p>我是局部组件的语法糖</p>
                        </div>
                        `
                     }
        Vue.component('cpn1',cpn1) //注册全局组件语法糖的写法
        const app = new Vue({
            el:"#app",
            components:{ //注册局部组件的语法糖
                'cpn2':cpn2
                }
        })
    </script>
View Code

 模板分离写法(推荐)

    <body>
        <div id="app">
            <cpn1></cpn1>
            <cpn2></cpn2>
        </div>
    </body>
    <script type="text/x-template" id='cpn1'>
        <div>
            <h2>我是标题1</h2>
            <p>text/x-template写法</p>
        </div>
    </script>
    <template id='cpn2'>
        <div>
            <h2>我是标题2</h2>
            <p>template标签写法</p>
        </div>
    </template>
    <script>
    //Vue.component('cpn',cpn) //注册全局组件语法糖的写法
    Vue.component('cpn1',{
        template:"#cpn1"
    })
    const app = new Vue({
        el:"#app",
        components:{ //注册局部组件
            'cpn2':{template:"#cpn2"}
            }
        
    })
    </script>
View Code

 组件的data赋值

    <body>
        <div id="app">
            <cpn1></cpn1>
            <cpn2></cpn2>
        </div>
    </body>
    <script type="text/x-template" id='cpn1'>
        <div>
            <h2>我是标题1{{title}}</h2>
            <p>text/x-template写法</p>
        </div>
    </script>
    <template id='cpn2'>
        <div>
            <h2>我是标题2</h2>
            <p>template标签写法</p>
        </div>
    </template>
    <script>
    //Vue.component('cpn',cpn) //注册全局组件语法糖的写法
    Vue.component('cpn1',{
        template:"#cpn1",
        data(){
            return {
                title:'我是组件里的{{动态数据  必须是函数 返回动态对象'
            }
        }
    })
    const app = new Vue({
        el:"#app",
        components:{ //注册局部组件
            'cpn2':{template:"#cpn2"}
            }
        
    })
    </script>
View Code

 为什么数组data必须是函数

··1、

data:{
            counter:0
        },

直接报错

the "data" option should be a function that returns a per-instance value in component definitions.

2、

const obj = {
        counter:0
    }
    Vue.component('cpn1',{
        template:"#cpn1",
        data:{
            counter:0
        },
        data(){
            return obj
        },
        methods:{
            increment(){
                this.counter++
            },
            decrement(){
                this.counter--
            }
        }
    })
View Code

组件调用三次,数据共享 引起连锁反应

3 函数式返回

组件里的data必须是函数

data(){//创建新的函数对象在不同的内存栈空间里  
            return {
                counter: 0
            }
        },

父子组件通信

props 从父组件-——》子组件的数据

props的值有两种方式:

方式1 :字符串数据,数组中的字符串就说传递时的名称

    
    <body>
        <div id="app">
            把变量movies(['海王','海贼王','海尔兄弟']) 当做字符串 传递到子组件
            <cpn v-bind:cmovies='movies' :cmessage='message'> </cpn>
        </div>
    </body>
    <template  id='cpn'>
        <div>
            <h2>{{cmovies}}</h2>
            <ul>
                <li v-for='cmovie in cmovies'>{{cmovie}}</li>
            </ul>
            <p>{{cmessage}}</p>
        </div>
    </template>
    <script>
    const cpn = {
        template:'#cpn',
        props:['cmovies','cmessage'],
        data(){
            return {}
        }
    }
    const app = new Vue({
        el:"#app",
        data:{
            message:'你好啊',
            movies:['海王','海贼王','海尔兄弟']
        },
        components:{ 
            cpn
            //相当于cpn:cpn
        }
    })
    </script>
View Code

方式2:对象。对象可以设置传递时的类型,也可以设置默认值等。

props数据验证

验证都支持哪些类型呢

Srting

Number

boolean

Array

Object

Date

Function

Symbol

   <body>
        <div id="app">
            把变量movies(['海王','海贼王','海尔兄弟']) 当做字符串 传递到子组件
            <!-- <cpn v-bind:cmovies='movies' :cmessage='message'> </cpn>-->
            <cpn  > </cpn>
        </div>
    </body>
    <template  id='cpn'>
        <div>
            <h2>{{cmovies}}</h2>
            <ul>
                <li v-for='cmovie in cmovies'>{{cmovie}}</li>
            </ul>
            <p>{{cmessage}}</p>
        </div>
    </template>
  <script>
  const cpn = {
    template:'#cpn',
    //props:['cmovies','cmessage'],
    props:{
      //1 类型的限制(简单写法)
      //cmovies:Array,//要求数据必须是array类型
            //cmessage:String
            
            //2 提供默认值(复杂写法)
            cmessage:{
                type : String,
                default:'aaaaaaaaaa',//没有传值的情况下默认值
                //required:true//传值的时候必须传入数值
            },
            cmovies:{
              type:Array,//类型是对象或者数组时,默认值必须是一个函数
              //default:[]//vue2.5以下
              default(){//vue2.5以上
                return []
              }
            }
        },
        data(){
            return {}
        }
    }
    
    const app = new Vue({
        el:"#app",
        data:{
            message:'你好啊',
            movies:['海王','海贼王','海尔兄弟']
        },
        components:{ 
            cpn
            //相当于cpn:cpn
        }
    })

    </script>
View Code

props中的驼峰标识

    <body>
        <div id="app">
          传递参数
          <cpn v-bind:c-info="info" :child-my-message="myMessage"></cpn>
        <hr/> 
          不传入 显示默认值
          <cpn> </cpn>
        </div>
    </body>
    
    
  <template  id='cpn'>
    <!--
      如果不加根标签 会报错
      [Vue warn]: Error compiling template:
Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
      -->
      <div>
        <h2>{{cInfo}}</h2>
        <h2>{{childMyMessage}}</h2>
      </div>
  </template>
  <script>
  const cpn = {
    template:'#cpn',

    props:{
     cInfo:{
       type:Object,
       default(){
         return {}
       }
     },
     childMyMessage:{
       default(){
         return 'aaaaaaa'
       }
     }
        },
        data(){
            return {}
        }
    }
    
    const app = new Vue({
        el:"#app",
        data:{
            info:{
              name:'aaa',
              age:16,
              height:1.88
            },
            myMessage:'bbbb'
        },
        components:{ 
            cpn
            //相当于cpn:cpn
        }
    })

    </script>
View Code

注意点1  v-bind的时候 大写不支持 要改成-

注意点2 template下有多个{}时,要添加根标签 不然会报错

 [Vue warn]: Error compiling template:
Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.

$emit从子组件-——》父组件的数据

子组件发射事件 通过$emit()来触发事件

methods:{
          btnClick(category){
            //console.log(category)
            //发射(事件名,传递的参数)
            this.$emit('categoryclick',category)
          }
        }

父组件接收事件 通过v-on来监听子组件事件

methods:{
          cpnClick(category){
            console.log('cpnClick',category)
          }
        }
    <body>
        <div id="app">
          <cpn @categoryclick='cpnClick'> </cpn>
        </div>
    </body>
  <!--子组件模板-->
  <template  id='cpn'>
      <div>
            子组件
        <button v-for = "category in categories" 
                @click='btnClick(category)'>
                {{category.name}}
        </button>
      </div>
  </template>
  <script>
  //子组件
  const cpn = {
    template:'#cpn',
        data(){
            return {
              categories:[
               {id:'1',name:'热门推荐'},
               {id:'2',name:'手机数码'},
               {id:'3',name:'家用家电'},
               {id:'4',name:'电脑办公'}
              ]
            }
        },
        methods:{
          btnClick(category){
            //console.log(category)
            //发射(事件名,传递的参数)
            this.$emit('categoryclick',category)
          }
        }
    }
    //父组件
    const app = new Vue({
        el:"#app",
        components:{ 
            cpn
        },
        methods:{
          cpnClick(category){
            console.log('cpnClick',category)
          }
        }
    })
    </script>
View Code

原文地址:https://www.cnblogs.com/polax/p/12895711.html