vue之组件与通信

组件化开发基础

组件是什么?有什么用

扩展 HTML 元素,封装可重用的代码,目的是复用
	-例如:有一个轮播,可以在很多页面中使用,一个轮播有js,css,html
	-组件把js,css,html放到一起,有逻辑,有样式,有html

注意事项

1 自定义组件需要有一个root element,一般包裹在一个div中
2 父子组件的data是无法共享
3 组件可以有data,methods,computed....,但是data 必须是一个函数

组件注册方式

1 全局组件
	Vue.component('组件名', {
                template:`html代码`,
        	   // 这里的data必须是方法所以要加() 在return里写变量
                data(){
                    return {
                        变量:值
                    }
                },
                methods:{
					方法(){}
                    }
                }
            },)
2 局部组件  在Vue对象内  和el、data、methods同级写components
	components:{
            '组件名':{
                template:`html代码`,
                data(){
                    return {
                        变量:值
                    }
                },
                methods:{
                    方法(){}
                    }
                }
            },
        }

局部组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
    <Top></Top>  // 在这里调用局部组件
    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
    <Bottom></Bottom>
</div>

</body>
<script>
    var vm = new Vue({
        // el  data  methods watch computed 8个生命周期函数
        el: '#app',
        data: {},
        // 定义再这里面的叫局部组件,只能再局部使用,只能再id为app的标签内使用
        components: {
            'Top': {
                template: `<div><h1 style="background: pink;font-size: 60px;text-align: center">{{name}}</h1><hr><button @click="handleC">点我看美女</button>
                    </div>`,
                data() {
                    return {
                        name: "我是头部"
                    }
                },
                methods: {
                    handleC() {
                        alert('美女')
                    }
                },
            },
            'Bottom': {
                template: `<div>
                <hr><h1 style="background: green;font-size: 60px;text-align: center">{{name}</h1>
                    </div>`,
                data() {
                    return {
                        name: "我是尾部"
                    }
                },
            },
        },
    })
</script>
</html>

全局组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
    <top></top>   // 在这里调用全局组件
</div>

</body>
<script>
    // 定义全局组件--->任意位置都可以用
    Vue.component('top', {
            template: `
                <div>
                    <h1 style="background: pink;font-size: 60px;text-align: center">{{name}}</h1>
                    <hr>
                    <button @click="handleC">点我看美女</button>
                </div>
            `,
            data() {
                return {
                    name: "我是头部"
                }
            },
            methods: {
                handleC() {
                    alert('美女')
                }
            },

        },)
    var vm = new Vue({
        // el  data  methods watch computed 8个
        el: '#app',
        data: {},
    })
</script>
</html>

组件通信之父传子(自定义属性)

通过自定义属性实现

步骤:

1.给组件自定义属性绑定一个父中定义的变量eg:

2.在定义组件内写props属性,对应一个数组,数组内包含组件自定义属性名eg: props:['fathername',]

3.这样组件(子)就可以使用Vue对象(父)内的变量啦,实现了通信.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>

<div id="div_id">
	// 给组件自定义属性绑定一个父中的变量
    <top :fathername="headName"></top>
    <hr>
    {{headName}}
    <hr>
    <input type="text" v-model="headName">

</div>

<script>
    Vue.component('top', {
                template:`
                <div><h1 style="background-color: pink;font-size: 60px;text-align: center">{{fathername}}</h1>
                </div>
                `,
                data(){
                    return {
                        name:'我是头部'
                    }
                },
                props:['fathername',]

            },)
    let vm = new Vue({
        el:'#div_id',
        data:{
            headName:'哈哈',
        },
    })
</script>
</body>
</html>

组件通信之子传父(自定义事件)

通过自定义事件实现

步骤:

1.给组件绑定自定义事件对应一个函数eg: <top @myevent="handleRev">

2.在另一个标签上绑定事件通过this.$emit('自定义事件名', 要传递的参数...)来触发其对应函数的执行

3.这样就在Vue对象中获得了组件传来的参数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>

<div id="div_id">
    <top @myevent="handleRev"></top>
    <hr>
    接收到的参数:{{revText}}
</div>

<script>
    Vue.component('top', {
                template:`
                <div><h1 style="background-color: pink;font-size: 60px;text-align: center">{{name}}</h1>
                <input type="text" v-model="text"><button @click="handleSend">点我传数据</button>
                </div>`,
                data(){
                    return {
                        name:'我是头部',
                        text:''
                    }
                },
                methods:{
                    // 触发绑定在该组件上的事件,myevent,然后传参.父组件中会执行事件对应的函数handelRecv
                    handleSend(){
                        this.$emit('myevent', this.text)
                    }
                }
            },)
    let vm = new Vue({
        el:'#div_id',
        data:{
            revText:'',
        },
        methods:{
            handleRev(text){
                // 接收一个参数,赋值给父组件的revText
                this.revText = text
            }
        }
    })
</script>
</body>
</html>

ref属性实现双向通信

ref放在标签上,拿到的是标签对象,可以点属性拿到对应的值
ref放在组件上,拿到的是组件对象,可以点属性拿到对应的值
通过这种方式实现子传父(this.$refs.mychild.text)
通过这种方式实现父传子(调用子组件方法传参数)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="box">
<!--    通过ref,获取input的值-->
    <input type="text" ref="mytext">
    <button @click="handleClick">点我</button>
    <child ref="mychild"></child>
</div>
</body>
<script>
    Vue.component('child',{
        template:`<div>child</div>`,
        data(){
            return {
                text:'子组件数据'
            }
        },
        methods:{
            add(){
               console.log('子组件的add方法')
            }
        }
    })
 var vm = new Vue({
        el: '#box',
        data: {

        },
        methods: {
            handleClick() {
                console.log(this)
                //this.$refs.mytext 获取到input控件,取出value值
                console.log(this.$refs.mytext.value)
                console.log(this.$refs.mychild.text)
                // this.$refs.mychild.add()
                this.$refs.mychild.add('传递参数')

            }
        }

    })
</script>
</html>

动态组件和keep-alive

keep-alive:组件不销毁(页面切换之前输入的数据会保留)

component:有个is属性,指定显示的组件是哪个

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>

<div id="div_id">
    <ul>
        <li @click="handleC('index')">首页</li>
        <li @click="handleC('order')">订单</li>
        <li @click="handleC('good')">商品</li>
    </ul>
    <keep-alive>
        <component :is="who"></component>
    </keep-alive>
</div>

<script>
    Vue.component('index', {
        template: `
                <div><h1>我是首页</h1>
                </div>`,
    },)
    Vue.component('order', {
        template: `
                <div><h1>我是订单</h1><input type="text">
                </div>`,
    },)
    Vue.component('good', {
        template: `
                <div><h1>我是商品</h1>
                </div>`,
    },)
    let vm = new Vue({
        el: '#div_id',
        data: {
            who: ''
        },
        methods: {
            handleC(func) {
                this.who = func
            }
        }
    })
</script>
</body>
</html>

image

插槽

插槽就是可以在组件标签中间插入标签或内容,比如我自定义一个index标签,那么直接写是不行的,需要在定义index标签的时候加slot标签就行了

基本使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="box">
    <!-- 不使用插槽写的aaa不会显示,使用就会显示-->
    <child1>aaa</child1>

</div>
</body>
<script>
    var bus = new Vue() //new一个vue的实例,就是中央事件总线
    Vue.component('child1', {
        template: `<div>
          首页
          <slot></slot>
        </div>`,

    })
 var vm = new Vue({
        el: '#box',

    })
</script>
</html>

插槽应用场景1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="box">
<!--    写了一个轮播组件,用户想轮播什么就放什么-->
    <swiper>
        <p v-for="data in 4">{{data}}</p>
    </swiper>

       <swiper>
           <img :src="data" v-for="data in 5">
    </swiper>

</div>
</body>
<script>
    var bus = new Vue() //new一个vue的实例,就是中央事件总线
    Vue.component('swiper', {
        template: `<div>
          <slot></slot>
        </div>`,

    })
 var vm = new Vue({
        el: '#box',

    })
</script>
</html>

插槽应用场景2

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="box">
    <!--通过插槽实现在一个组件中控制另一个组件的显示隐藏-->
    <navbar> <button @click="isShow=!isShow">点我显示隐藏</button></navbar>

    <swiper v-if="isShow"></swiper>
</div>
</body>
<script>
    Vue.component('navbar', {
        template: `<div>
          navbar
          <slot></slot>
        </div>`,

    })
    Vue.component('swiper', {
        template: `<div>
          <p>111</p>
          <p>222</p>
          <p>333</p>
        </div>`,

    })
    var vm = new Vue({
        el: '#box',
        data:{
            isShow:true
        }
    })
</script>
</html>

具名插槽

具名插槽的意思就是给插槽起名字,然后使用的时候把指定的标签或内容插到指定的插槽中,这样可以指定不同的插槽使用不同的内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>

<div id="div_id">
<index>
    <p slot="a">我来替换插槽a</p>
    <div slot="b">我来替换插槽b</div>
</index>

</div>

<script>
    Vue.component('index', {
        template: `
                <div>
                <slot name="a"></slot>
                <h1>我是首页</h1>
                <slot name="b"></slot>
                </div>`,
    },)
    let vm = new Vue({
        el: '#div_id',
        data: {
        },
    })
</script>
</body>
</html>

image

posted @ 2022-05-03 14:52  zong涵  阅读(58)  评论(0编辑  收藏  举报