Vue-自定义组件3

好看的网页千篇一律,有趣的代码万里挑一。

一到秋天,南京就美成了金陵。

现在已经初冬了,南京街头还是深秋景象。

这种配色,看起来极度舒适。

为平淡的生活,混入一丝仙气。

四季的轮转,给熟悉的街景添加了不同的滤镜。

换个角度,完全是全新的视觉盛宴。


知识的更迭,让思维产生质变。

欣赏完美景,回归到工作。

保持学习的热情,温故而知新。

今天继续Vue自定义组件知识。



1. 深入理解v-model


// 定义一个数据加减的组件

Vue.component('b-counter', {

template: `

<div class="counter">

    <button @click="jian" :disabled="myCount===minCount">-</button>

    <input type="text" :value="myCount" readonly>

    <button @click="jia" :disabled="myCount===maxCount">+</button>

</div>

`,

props: {

// 数量

value: {

// 类型

type: Number,

// 非空

required: true,

},

// 最小值

minCount: {

type: Number,

// 默认值

default: 1

},

// 最大值

maxCount: {

type: Number,

default: 10

}

},

// 定义组件的数据

data() {

return {

// 从props里面将value的值给myCount复制一份

myCount: this.value

}

},

// 定义组件的方法

methods: {

//数量减方法

jian() {

this.myCount--

},

// 数量加方法

jia() {

this.myCount++

}

},

// 侦听器

watch: {

// 侦听myCount是否发生变化

myCount() {

// 触发自定义事件,注意:事件名称中不能采用大写字母

this.$emit('input', this.myCount)

}

}

})

new Vue({

el: "#app",

data() {

return {

name: '张三',

// 衣服的数量

yfcount:2

}

},

methods: {

},

})

2. .sync修饰符


<div id="app">

    <div>

        <h4>衣服数量:{{yfcount}}</h4>

        <h4>裤子数量:{{kzcount}}</h4>

        <h4>鞋子数量:{{xzcount}}</h4>

        <!-- <b-box :yfcount="yfcount" :kzcount="kzcount" :xzcount="xzcount"

        @update:yfcount="yfcount=$event" @update:kzcount="kzcount=$event"

        @update:xzcount="xzcount=$event"></b-box> -->

        <hr>

        <!-- 如果触发的事件名称是update:属性名,那么就可以使用..sync修饰符简化调用的过程。 -->

        <!-- 总结:如果组件只回传一份数据,用v-model。如果组件回传多份数据,用.sync修饰符。 -->

        <b-box :yfcount.sync="yfcount" :kzcount.sync="kzcount" :xzcount.sync="xzcount"></b-box>

    </div>

</div>

// 定义一个数据加减的组件

Vue.component('b-counter', {

template: `

<div class="counter">

    <button @click="jian" :disabled="myCount===minCount">-</button>

    <input type="text" :value="myCount" readonly>

    <button @click="jia" :disabled="myCount===maxCount">+</button>

</div>

`,

props: {

// 数量

value: {

// 类型

type: Number,

// 非空

required: true,

},

// 最小值

minCount: {

type: Number,

// 默认值

default: 1

},

// 最大值

maxCount: {

type: Number,

default: 10

}

},

// 定义组件的数据

data() {

return {

// 从props里面将value的值给myCount复制一份

myCount: this.value

}

},

// 定义组件的方法

methods: {

//数量减方法

jian() {

this.myCount--

},

// 数量加方法

jia() {

this.myCount++

}

},

// 侦听器

watch: {

// 侦听myCount是否发生变化

myCount() {

// 触发自定义事件,注意:事件名称中不能采用大写字母

this.$emit('input', this.myCount)

}

}

})

// 定义一个b-box组件

Vue.component('b-box', {

// 模板中必须包含一个根标签

template:`

<div>

    <div>衣服:<b-counter v-model="myyfcount"></b-counter>

    </div>

    <div>裤子:<b-counter v-model="mykzcount"></b-counter>

    </div>

    <div>鞋子:<b-counter v-model="myxzcount"></b-counter>

    </div>

</div>

`,

props:['yfcount','kzcount','xzcount'],

data() {

return {

// 将props传进来的数据,在data中备份一下,从此以后操作data中的数据

myyfcount:this.yfcount,

mykzcount:this.kzcount,

myxzcount:this.xzcount

}

},

watch:{

myyfcount(){

// 注意:这里触发事件的名称是:update:属性名;

// 如果满足该规则,那么在触发事件时,就可以使用sync修饰符简化调用的过程。

this.$emit('update:yfcount',this.myyfcount)

},

mykzcount(){

this.$emit('update:kzcount',this.mykzcount)

},

myxzcount(){

this.$emit('update:xzcount',this.myxzcount)

}

}

})

new Vue({

el: "#app",

data() {

return {

// 衣服的数量

yfcount:2,

// 裤子的数量

kzcount:3,

// 鞋子的数量

xzcount:5

}

},

methods: {

},

})


3. 具名插槽

<div id="app">

    <b-box>

        <!-- template标签指定它里面的内容在哪一个具体的插槽中呈现 -->

        <template v-slot:header>

            <h4>好好学习</h4>

            <h4>天天向上</h4>

        </template>

        <template v-slot:default>

            <img src="https://img0.baidu.com/it/u=2293835918,4228668324&fm=253&fmt=auto&app=120&f=JPEG?w=556&h=500">

            <img

                src="https://ss0.baidu.com/-Po3dSag_xI4khGko9WTAnF6hhy/image/h%3D300/sign=e25abb7779061d95624631384bf50a5d/5ab5c9ea15ce36d39e62417f2df33a87e950b11f.jpg">

        </template>

        <!-- v-slot:的简写是# -->

        <template #footer>

            <a href="http://www.baidu.com">百度</a>

            <a href="http://www.taobao.com">淘宝</a>

        </template>

    </b-box>

</div>

// 在组件内部通过slot标签定义插槽,在通过name属性给插槽定义名字,这样的插槽称之为:具名插槽。// 插槽的默认名称是:default。如果有多个插槽,允许其中一个插槽不定义名称。Vue.component('b-box',{template:` <div class="box">

    <h2>我是组件</h2>

    <div class="header">

    <slot name="header"></slot>

    </div>

    <div class="main">

    <slot></slot>

    </div>

    <div class="footer">

    <slot name="footer"></slot>   

    </div>

    </div>

    `})newVue({el:'#app',})


4. 作用域插槽

<div id="app">

    <b-box>

        <!-- 注意:一定要用使用具名插槽的方式去接收作用域插槽传递回来的数据,

        通常我们会定义scope变量,就收传回来的数据。 -->

        <template v-slot:edit="scope">

            <button @click="scope.item.name='苹果'">修改</button>

            <button @click="scope.list.splice(scope.index,1)">删除</button>

        </template>

    </b-box>

</div>

Vue.component('b-box', {

    // 可以在slot标签上绑定属性,这样外面在使用该插槽时,就可以获取到上面绑定的数据。

    // 这样的插槽,我们称之为:作用域插槽

    template:`

    <div class="box">

    <ul>

    <li v-for="(item,index) in list" :key="index">

    {{item.id}}--{{item.name}}

    <slot name="edit" v-bind:item="item" v-bind:list="list" v-bind:index="index"></slot>

    </li>

    </ul>

    </div>

    `,

    data() {

        return {

            list:[

                {

                    id:1001,

                    name:'薯片'

                },

                {

                    id:1002,

                    name:'饼干'

                },

                {

                    id:1003,

                    name:'面包'

                },

                {

                    id:1004,

                    name:'糖果'

                },

            ]

        }

    },

})

new Vue({

    el:'#app',

})

5. 混入


突然想到了炒鸡蛋,😄,鸡蛋打散混入葱花,搅拌均匀。

哈哈,代码中也可以混入,密钥是mixin

<div id="app1">

    <h2>app1</h2>

    <h4>姓名:{{name}},年龄:{{age}},工资:{{money}}</h4>

    <button @click="sayHi">sayHi</button>

    <button @click="updateMoney">修改工资</button>

    <b-box></b-box>

</div>

<hr>

<div id="app2">

    <h2>app2</h2>

    <h4>姓名:{{name}},年龄:{{age}},工资:{{money}}</h4>

    <button @click="sayHi">sayHi</button>

    <button @click="updateMoney">修改工资</button>

    <b-box></b-box>

</div>

// 全局混入 -- 注意:必须要先执行

Vue.mixin({

    // mixin()方法的参数是配置对象,Vue实例可以配置的东西,它都可以配置。

    // 比如:数据,方法,生命周期钩子函数,计算属性,侦听器,过滤器,等等...

    data() {

        return {

            name:'张三',

            age:20,

            money:10000,

        }

    },

    methods: {

        sayHi(){

            alert('大家好!')

        },

        // 更新工资的方法

        updateMoney(){

            this.money+=1000

        }

    },

    mounted() {

        console.log('mixin里面定义的生命周期钩子函数----我已经挂载完毕....');

    },

    computed:{

        usMoney(){

            return '$'+(this.money/6).toFixed(2)

        }

    },

})

// 在全局混入的内容,之后创建的所有Vue实例包括组件实例都将拥有。

// 在创建Vue实例时,会将mixin里面的成员跟Vue实例自身的成员进行合并,如果冲突了,最终采用Vue实例身上的成员。

// 特别注意:生命周期钩子不是合并,是叠加执行,是先执行mixin里面的生命周期钩子,再执行Vue实例里面的生命周期钩子。

// 定义组件

Vue.component('b-box', {

    template:`

    <div class="box">

    <h4>姓名:{{name}},年龄:{{age}},工资:{{money}},美元工资:{{usMoney}}</h4>

    <button @click="sayHi">sayHi</button>

    <button @click="updateMoney">修改工资</button>

    </div>

    `,

    methods: {

        updateMoney(){

            this.money+=10000

        }

    },

    mounted() {

        console.log('组件自己定义的生命周期钩子函数----我已经挂载完毕....');

    },

})

// 创建第一个Vue的实例--操作的容器是#app1

new Vue({

    el:'#app1',

})

// 创建第二个Vue的实例--操作的容器是#app2

new Vue({

    el:'#app2',

})

6. 混入ajax的基本操作

<div id="app1">{{students}}</div>

<hr>

<div id="app2">{{subjects}}

    <hr>

    <p>课程名称:<input type="text" v-model="subject.subjectName"></p>

    <p>课程年级:<input type="text" v-model="subject.gradeId"></p>

    <p>课程课时:<input type="text" v-model="subject.classHour"></p>

    <p><button @click="add">添加</button></p>

</div>

// 将ajax请求相关的操作,通过mixin混入给Vue

Vue.mixin({

    data() {

        return {

            // 接口根路径

            base_url:'http://www.bingjs.com:81'

        }

    },

    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

        }

    },

})

new Vue({

    el:'#app1',

    data() {

        return {

            // 学生信息

            students:[]

        }

    },

    created() {

        this.getStudents()

    },

    methods: {

        async getStudents(){

            let students = await this.$get('/Student/GetAll')

            this.students = students.map(s=>s.StudentName)

        }

    },

})

new Vue({

    el:'#app2',

    data() {

        return {

            // 课程信息

            subjects:[],

            subject:{

                subjectName:'',

                classHour:'',

                gradeId:''

            }

        }

    },

    created() {

        this.getSubjects()

    },

    methods: {

        async getSubjects(){

            let subjects = await this.$get('/Subject/GetAll')

            this.subjects = subjects.map(s=>s.SubjectName)

        },

        async add(){

            let r = await this.$post('/Subject/Add',this.subject)

            if(r){

                alert('添加成功!')

            }

        }

    },

})

是不是越来越有趣了,试试看敲出来的效果吧。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容