vue

vue 自定义组件(三) .sync、插槽 、混入

2021-12-06  本文已影响0人  _ou

自定义组件 v-model的深入使用

    <z-counter :label="yf.label" :value="yf.count" @input="yf.count=$event"></z-counter>
    <z-counter :label="kz.label" v-model="kz.count"></z-counter>

比如在普通的input 的标签中,我们可以用v-model来实现数据的双向绑定,在自定义组件中,我们也可以使用v-model的双向绑定。
首先我们把属性名改成value,自定义的方法名为input,这个时候我们的格式很像v-model的实现原理,这个时候我们就可以缩写成v-model来实现数据的双向绑定
在多个数据需要传回页面的时候,这个方法不能够使用。

Vue.component("z-counter", {
            template:
                `
                <div class="counter">
                    <div  class="label">{{label}}</div>
                    <div class="btns">
                        <button @click="mydata--" :disabled="mydata===mincount">-</button>
                        <input type="text" v-model="mydata" class="text" readonly>
                        <button @click="mydata++" :disabled="mydata===maxcount">+</button>
                    </div>
                </div>
                `,
            // props 是只读的不能修改
            //prop 也可以是数组[属性名]
            props: {
                label: {
                    type: String,
                    //允许为空
                    required: false,
                },
                value: {
                    type: Number,
                    //不可为空
                    required: true
                },
                maxcount: {
                    type: Number,
                    default: 999
                },
                mincount: {
                    type: Number,
                    default: 1
                }
            },
            data() {
                return {
                    mydata: this.value
                }
            },
            watch: {
                mydata(val) {
                    this.$emit('input', val)
                }
            },
        })
        new Vue({
            el: '#app',
            data() {
                return {
                    yf:{
                        label:'衣服',
                        count:3
                    },
                    kz:{
                        label:'裤子',
                        count:3
                    }
                }
            },
            methods: {
            }
        })

.sync修饰符

这三种方法都可以实现

<div id="app">
        <p>{{yf}}</p>
        <p>{{kz}}</p>
        <p>{{xz}}</p>
    <z-counter :yf.sync="yf" :kz.sync="kz" :xz.sync="xz"></z-counter>
    <hr>
    <z-counter :yf="yf" :kz="kz" :xz="xz" @update:yf="yf=$event" @update:kz="kz=$event" @update:xz="xz=$event"></z-counter>
    <hr>
    <z-counter :yf.sync="yf" :kz.sync="kz" :xz.sync="xz" @update:yf="yf=$event" @update:kz="kz=$event" @update:xz="xz=$event"></z-counter>

如果在组件中有多个数据需要回传,这个时候我们可以使用.sync修饰符 ,可以简化我们的调用过程。
我们的自定义回传方法yfcount(val){ this.$emit('update:yf', val) }, 加上update:的时候,我们可以在属性的后面加上.sync修饰符,这个时候,我们的回传方法可以省略


this.$emit('update:yf', val) update: 后面连接的是父类传过来的值的名称 ,需要保持一致

Vue.component("z-counter", {
            //模板
            template:`
                <div>
                    <div class="counter">
                        <div  class="label">衣服:</div>
                        <div class="btns">
                            <button @click="yfcount--" >-</button>
                            <input type="text" v-model="yfcount" class="text" readonly>
                            <button @click="yfcount++" >+</button>
                        </div>
                    </div>
                    <div class="counter">
                        <div  class="label">裤子:</div>
                        <div class="btns">
                            <button @click="kzcount--" >-</button>
                            <input type="text" v-model="kzcount" class="text" readonly>
                            <button @click="kzcount++" >+</button>
                        </div>
                    </div>
                    <div class="counter">
                        <div  class="label">鞋子:</div>
                        <div class="btns">
                            <button @click="xzcount--" >-</button>
                            <input type="text" v-model="xzcount" class="text" readonly>
                            <button @click="xzcount++">+</button>
                        </div>
                    </div>
                </div> `,
              //自定义属性
            props: ['yf','kz','xz'],
            data() {
                return {
              //将自定义属性值进行重新赋值给新的变量,  因为自定义属性不能够改变默认值
                    yfcount:this.yf,
                    kzcount:this.kz,
                    xzcount:this.xz,
                }
            },
            watch: {
                 //监听事件,将新值传回给页面
                yfcount(val){
                    this.$emit('update:yf', val)
                },
                kzcount(val){
                    this.$emit('update:kz', val)
                },
                xzcount(val){
                    this.$emit('update:xz', val)
                }
            },
        })
        new Vue({
            el: '#app',
            data() {
                return {
                    yf:3,
                    kz:3,
                    xz:2
                    }
                },
            methods: {

            }
        })

如果触发的事件名称是update:属性名,那么就可以使用..sync修饰符简化调用的过程。
总结:如果组件只回传一份数据,用v-model。如果组件回传多份数据,用.sync修饰符。

具名插槽

当我们的自定义组件中有多个插槽,这个时候我们需要把信息插入到对应的插槽,这个时候我们需要使用到具名插槽。
我们给插槽添加添加一个name属性,这个就是插槽的名称。
使用方法:
我们在自定义组件中用<template ></template >把插入的标签放入到里面 用v-slot:插槽名来插入固定插槽中
v-slot可以用#来代替 v-slot必须是在<template>上使用slot` 可以直接写在标签上 如

<span slot="first"><span>
<div id="app">
        <z-box>
            <template v-slot:house>
                <p>4套房子</p>
            </template>
            <template #car>
                <p>三辆车</p>
            </template>
            <template v-slot:monyse>
                <p>1000万存款</p>
            </template>
        </z-box>
    </div>
 Vue.config.productionTip = false
        Vue.component('z-box', {
            template:`
                <div class="box">
                    <div class="item">
                        <h2>房产信息</h2>
                        <slot name="house"></slot>
                    </div>
                    <div class="item">
                        <h2>车辆信息</h2>
                        <slot name="car"></slot>
                    </div>
                    <div class="item">
                        <h2>存款信息</h2>
                        <slot name="monyse"></slot>
                    </div>
                </div>
            `,
        })
        new Vue({
            el: '#app'
        })

作用域插槽

像可以在slot标签上绑定属性,这样外面在使用该插槽时,就可以获取到上面绑定的数据。 这样的插槽,我们称之为:作用域插槽。
我们在自定义组件时,我们可以在<slot>的插槽中绑定属性 绑定的格式是v-bind:跟普通绑定的属性是相同的,v-bind 可以省略。
在使用时,我们在template的标签上用 v-slot:插槽名="变量名",通常我们的变量名用scope 来当作变量名

<div id="app">
        <z-food>
            <template v-slot:list="scope">
                <button @click="scope.list.splice(scope.index,1)">删除</button>
                <button @click="scope.list[scope.index].price+=100">加价</button>
                <button @click="scope.list[scope.index].price-=100">降价</button>
            </template>
        </z-food>
    </div>
 Vue.config.productionTip = false
        Vue.component("z-food", {
            template:`
                    <div>
                        <ul>
                            <li v-for="(item, index) in list" :key="index">{{item.id}}--{{item.name}}--{{item.price}}
                                <slot name="list" v-bind:index="index" v-bind:list="list"></slot>
                            </li>
                            
                        </ul>
                    </div>
                    `,
                    data() {
                        return {
                            list:[
                                {
                                    id:1001,
                                    name:'蛋糕',
                                    price:20
                                },
                                {
                                    id:1002,
                                    name:'蛋挞',
                                    price:30
                                },
                                {
                                    id:1003,
                                    name:'鸡腿',
                                    price:40
                                },
                                {
                                    id:1004,
                                    name:'黑巧',
                                    price:50
                                },
                            ]
                        }
                    },
        })
        new Vue({
            el:"#app"
        })

混入

全局混入 -- 注意:必须要先执行
mixin()方法的参数是配置对象,Vue实例可以配置的东西,它都可以配置。
比如:数据,方法,生命周期钩子函数,计算属性,侦听器,过滤器,等等...
在mixin()方法中,是先执行的

在全局混入的内容,之后创建的所有Vue实例包括组件实例都将拥有。
在创建Vue实例时,会将mixin里面的成员跟Vue实例自身的成员进行合并,如果冲突了,最终采用Vue实例身上的成员。
特别注意:生命周期钩子不是合并,是叠加执行,是先执行mixin里面的生命周期钩子,再执行Vue实例里面的生命周期钩子。

Vue.mixin({
            data() {
                return {
                    name: '',
                    age: 22,
                    sex: '男',
                    salary: 10000
                }
            },
            computed: {
                tosalary() {
                    return this.salary * 0.86
                }
            },
            methods: {
                jian() {
                    this.age++
                    if (this.age > 100) {
                        alert('年龄不能超过100');
                        this.age = 100
                    }
                }
            }
        })

混入ajax的基本操作

我们可以在Vue.mixin() 可以写个ajax的封装方法,这样我们在实例中可以直接调用封装过的ajax

Vue.mixin({
methods: {
        // get方法
        async $get(url,params){
            let {data} = await axios.get(this.base_url+url,{params})
          return data
        },
        // post方法
        async $post(url,params){
            let {data} = await axios.post(this.base_url+url,params)
            return data
        }
    },
})
 
上一篇 下一篇

猜你喜欢

热点阅读