Vue 组件通信

一:组件

全局组件

组件使用的规则:创建组件,引用组件,使用组件

创建组件

调用Vue.extend()方法  创建组件构造器

调用Vue.component()方法  ,祖册组件

在Vue实例的范围内使用组件

<body>
    <div id="app">
        <test-comp></test-comp>
    </div>

    <script>
    //创建组件
    //返回一个构造函数
    var comp = Vue.extend({//选项对象,对组件进行描述
        template:`<div>hello</div>`
        
    });  
    //全局注册组件
    Vue.component('test-comp',comp)

    //使用组件
    new Vue({
        el:"#app"
        
    })
    
</script>
    
</body>

<body>
    <div id="app">
        <test-comp></test-comp>
    </div>
    <script type="text/x-template" id="temp">
        <div>hello</div>
    </script>
    //或者直接用html的原生模板 template
    <template id="temp">
        <div>hello</div>
    </template>
    <script>
     //模板的内容多的时候 定义在  外部
    var comp = Vue.extend({//选项对象,对组件进行描述
        template:"#temp"
    });  
    //全局注册组件
    Vue.component('test-comp',comp)//可以直接写成下面的格式

    //可以直接写成  自动调用 vue.extend()
     Vue.component('test-comp',{
        template:"#temp"
     })

    //使用组件
    new Vue({
        el:"#app"
        
    })
    
</script>
</body>

 

局部组件

<body>
    <div id="app">
        <test-comp></test-comp>
    </div>
<script>
        //局部组件 只能用在 这个实例的范围的模板中
    new Vue({
        id:"#app",
        components:{
            'test-comp':{
                template:"<div>我是局部组件,只能用在app中 </div>"
            }
        }
    })
</script>
</body>

总结:

1:每个组件的选项对象没有el

2:data不同,每个组件的选项对象的data是一个工厂函数,返回一个对象

多个组件的title不能共用同一个对象,每次调用 data函数,都会返回一个新的对象

<body>
    <div id="app">
        <test-comp></test-comp>
    </div>
    <template id="temp">
        <p>{{title}}</p>
    </template>
<script>
    Vue.component("test-comp",{
        data(){
            return {
                title:"你好"
            }
        },
        template:"#temp"
    })
    new Vue({
        el:"#app"
        
    })
</script>
</body>

 

二:props  父组件--->子组件 传参

<body>
    <div id="app">
        <test-comp :title='news.title' :list='news.list'></test-comp>
        //组件是公用的 ,通过props传递不同的参数
        <test-comp :title='yule.title' :list='yule.list'></test-comp>
    </div>
    <template id="temp">
        
        <div>
            <h2>{{title}}</h2>
            <ul>
                <li v-for="item in list">{{item}}</li>
            </ul>
        </div>
    </template>
    <script type="text/javascript">
        // props 传递参数   父组件-->子组件  使用子组件标签时写在行间
        // :key = "数据"  key是子组件规定
        Vue.component('test-comp',{
            props:['title','list'],//接收父组件传过来的参数 props属性 都会放在当前组件的实例上
            template:'temp'
            
        })
        var news = {
            title:"新闻",
            list:["新闻1","新闻2"]
        }
        var list = {
            title:"娱乐",
            list:["娱乐1","娱乐2"]
        }

        new Vue({
            el:"#app",
            data:{
              news,
              yule  
            }
        })
    </script>
</body>

props验证

<body>
    <div id="app">
        <test-comp :title='news.title' :list='news.list'></test-comp>
        //组件是公用的 ,通过props传递不同的参数
        <test-comp :title='yule.title' :list='yule.list'></test-comp>
    </div>
    <template id="temp">
        
        <div>
            <h2>{{title}}</h2>
            <ul>
                <li v-for="item in list">{{item}}</li>
            </ul>
        </div>
    </template>
    <script type="text/javascript">
        // props 传递参数   父组件-->子组件  使用子组件标签时写在行间
        // :key = "数据"  key是子组件规定
        Vue.component('test-comp',{
            //props:['title','list'],//props属性 都会放在当前组件的实例上

            //props验证

            props:{
                title:{
                    type:String,
                    default:'这是标题'
                },
                list:{
                    type:Array,
                    required:true,
                    //数组/对象不填时给的默认值不能直接写成下面的
                   // default:[]
                    //写成工厂函数,把对象返回回去
            
                    default(){
                        return []
                    }
                }
            }
            template:'temp'
            
        })
        var news = {
            title:"新闻",
            list:["新闻1","新闻2"]
        }
        var list = {
            title:"娱乐",
            list:["娱乐1","娱乐2"]
        }

        new Vue({
            el:"#app",
            data:{
              news,
              yule  
            }
        })
    </script>
</body>

 修改prop传过来的某个值 不能直接修改props,可以修改自己内部属性data的值  ,把父级传过来的数据,作为data 的初始值

<body>
    <div id="app">
        <test-comp :title='news.title' ></test-comp>
        //组件是公用的 ,通过props传递不同的参数
        <test-comp :title='yule.title' ></test-comp>
    </div>
    <template id="temp">
        
        <div>
            <h2>{{title}}</h2>
            <button @click="changeTitle">改变title</button>
        </div>
    </template>
    <script type="text/javascript">
        // props 传递参数   父组件-->子组件  使用子组件标签时写在行间
        // :key = "数据"  key是子组件规定
        Vue.component('test-comp',{
            //内部不能直接修改外部传过来的 props值,可以改变自己data中的值
            props:{
                title:{
                    type:String,
                    default:'这是标题'
                },
                list:{
                    type:Array,
                    required:true,
                    default(){
                        return []
                    }
                }
            },
            data(){//这变可以改变,把父级传过来的数据,作为自己组件状态得初始值
                myTitel = this.title
                
            }
            template:'temp',
            methods:{
                changeTitle:(){
                    this.myTitel  = '我是自己组件的初始值,我可以改变了'
                }
            }
            
        })
        var news = {
            title:"新闻",
            list:["新闻1","新闻2"]
        }
        var list = {
            title:"娱乐",
            list:["娱乐1","娱乐2"]
        }

        new Vue({
            el:"#app",
            data:{
              news,
              yule  
            }
        })
    </script>
</body>

$emit  子组件发布事件,通知父组件 $emit("事件名","参数")

<body>
    <div id="app">
        //@change父组件监听
        <test-comp :title='news.title' @change="changeHandle"></test-comp>
    </div>
    <template id="temp">
        
        <div>
            <h2>{{title}}</h2>
            <button @click="changeTitle">改变title</button>
        </div>
    </template>
    <script type="text/javascript">
        
        Vue.component('test-comp',{
            // $emit()发布事件 通知父组件
            props:{
                title:{
                    type:String,
                    default:'这是标题'
                }
            },
            
            template:'temp',
            methods:{
                changeTitle(){
                    //子组件发布事件,change 自定义事件名,第二个参数,是传给父组件监听触发额方法的参数
                    this.$emit("change","传递的参数")
                }
            }
            
        })
        var news = {
            title:"新闻",
            list:["新闻1","新闻2"]
        }
        var list = {
            title:"娱乐",
            list:["娱乐1","娱乐2"]
        }

        new Vue({
            el:"#app",
            data:{
              news,
              yule  
            },
            methods:{
                changeHandle(title){
                    this.news.title = title
                }
            }
        })
    </script>
</body>

 平行组件通信 event-bus   var eventBus = new Vue();

缺点 :每个组件都能发布事件,会导致多个组件操作同一个属性

<body>
    <div id="app">
        <test1 @change="changeTest2"></test1>
        <test2 :title="title"></test2>
    </div>
   
    <script type="text/javascript">
        
        Vue.component('test1',{
            template:`
                <div>
                    <h2>我是标题1</h2>
                    <button @click="changeTitle">改变title</button>
                </div>
                `,
            methods:{
                changeTitle(){
                    this.$emit("change","我来自test1")
                }
            }
            
        })
        Vue.component('test2',{
            props:['title']
            template:`
                <div>
                    <h2>我是标题2</h2>
                    <p>{{title}}</p>
                </div>
                `
           
        })
       
     new Vue({
            el:"#app",
            data:{
                title:"给test2"
            },
            methods:{
                changeTest2(title){
                    this.title = title
                }
            }
        })
        
    </script>
</body>

 

<body>
    <div id="app">
        <test1></test1>
        <test2 :title="title"></test2>
    </div>
   
    <script type="text/javascript">
        
        Vue.component('test1',{
            template:`
                <div>
                    <h2>我是标题1</h2>
                    <button @click="changeTitle">改变title</button>
                </div>
                `,
            methods:{
                changeTitle(){
                    //this.$emit("change","我来自test1")
                    root.$emit("change","我来自test1")
                }
            }
            
        })
        Vue.component('test2',{
            props:['title']
            template:`
                <div>
                    <h2>我是标题2</h2>
                    <p>{{title}}</p>
                </div>
                `
           
        })
       
       let root = new Vue({
            el:"#app",
            data:{
                title:"给test2"
            }
        })
        //不需要再在父组件监听change了 
        root.$on('change',function(title){
            this.title = title
        })
    </script>
</body>

slot :订制html

<body>
    <div id="app">
        <modal>
              <p slot="content">我要出入新的内容</p>
               <input slot="footer" type="button" />
        </modal>
    </div>
    <template id="temp">
        <div class="modal">
            <h2>这是标题</2>
            //订制 对应  slot="content"
            <slot name="content">
                <div class="content">
                    <p>内容</p>
                </div>
            </slot>
            //对这边订制 slot="footer"
            <slot name="footer">
                <div class="footer">
                    <button>确定</button>
                </div>
            </slot>
        </div>
    <template>
    <script type="text/javascript">
        //对组件进行内容的订制  slot
        Vue.component('modal',{
            template:'#temp'
        })
        new Vue({
            el:'#app'
        })
    </script>
</body>

双向数据绑定

1:.sync 

<body>
    <div id="#app">
        <p>父组件:{{title}}</p>
        <hr/>
        //双向数据绑定
        <custom :title.sync='title'></custom>
        // 内部实现如下,此时要改变title需要发布事件
        <custom @update:title='title'></custom>
    </div>
    
    <script>
        Vue.component('custom',{
            props:['title']
            template:`
                <div>
                    <p>{{title}}</p>
                    <button @click='changeTitle'>改变title</button>
                </div>
            `,
            methods:{
                changeTitle(){
                    //任然要发布一个是事件   此时是  update事件
                    this.$emit('update:title','子组件修改了值')

                }
            }

        })
        new Vue({
            el:'#app',
            data:{

                title:'这是父组件的标题'
            }
        })
        
    </script>
</body>

2: v-model 

<body>
    <div id="#app">
        <input type='text' v-model='title' />
        {{title}}
        //本质上实现  v-model语法糖
        //<input type='text' :vlue='title'  @input='title=$event.target.value'/>

        //v-model 在组件上的应用
        <custom v-model='title'></custom>
        //  本质上的实现
        <custom :vlue='title'  @input='title=$event.target.value'>
        </custom>
    </div>
    
    <script>
        Vue.component('custom',{
            props:['value'] //此时传递的参数是value 因为父组件绑定 的是value
            template:`
                <div>
                    <p>{{value}}</p>//使用是也是 value
                    <button @click='changeTitle'>改变title</button>
                </div>
            `,
            methods:{
                changeTitle(){
                    //任然要发布一个是事件   此时是  input 事件
                    this.$emit('input','子组件修改了值')

                }
            }

        })
        new Vue({
            el:'#app',
            data:{

                title:'这是父组件的标题'
            }
        })
        
    </script>
</body>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值