• 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

  • 相关阅读:
    PCL利用RANSAC自行拟合分割平面
    HDU 3062 && HDU 1824 && POJ 3678 && BZOJ 1997 2-SAT
    BZOJ 3670 && BZOJ 3620 && BZOJ 3942 KMP
    BZOJ 1500 Splay 全操作
    Manacher
    POJ 2155 2维线段树 || 2维BIT
    BZOJ 1015 并查集+离线倒序
    NOI Linux JAVA
    UVA 10407 差分思想的运用
    BZOJ 1969 树链剖分+Tarjan缩点
  • 原文地址:https://www.cnblogs.com/polax/p/12895711.html
Copyright © 2020-2023  润新知