好看的网页千篇一律,有趣的代码万里挑一。
一到秋天,南京就美成了金陵。
现在已经初冬了,南京街头还是深秋景象。
这种配色,看起来极度舒适。
为平淡的生活,混入一丝仙气。
四季的轮转,给熟悉的街景添加了不同的滤镜。
换个角度,完全是全新的视觉盛宴。
知识的更迭,让思维产生质变。
欣赏完美景,回归到工作。
保持学习的热情,温故而知新。
今天继续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 >百度</a>
? ? ? ? ? ? <a >淘宝</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('添加成功!')
? ? ? ? ? ? }
? ? ? ? }
? ? },
})
是不是越来越有趣了,试试看敲出来的效果吧。