上一篇博客中已经介绍了 Vue 组件的一些基础 及 单项的数据传递,在实际的使用中,往往需要做到数据的双向传递。
这篇博客主要是介绍 实现数据双向传递的方法。
将之前的单项数据传递的方法结合起来使用
:自定义属性名="想要传递的数据"
的方式,将自身的数据绑给子组件标签props:["相同的自定义属性名"]
的方式接收数据,使用方法和data数据的方法一致this.$emit("自定义监听事件",想要传递的数据)
@子组件的自定义监听事件="新的方法名"
的方式,获取到传递的数据,自行决定是否使用 <div id="app">
<test-div :emm="name" @gg="fn"></test-div>
<span>子组件的回传数据:{{text}}</span>
</div>
<script>
Vue.component("test-div",{
template:`
接收的父组件数据:{{emm}}
`,
props:["emm"],
data:function(){
return {
name:"子组件",
text:"测试数据"
}
},
methods:{
go(){
console.log(11)
this.$emit("gg",this.name)
}
}
})
let app = new Vue({
el:"#app",
data:{
name:`我来自父组件`,
text:"父组件测试数据"
},
methods:{
fn(n){
console.log(n)
this.text = n;
}
}
});
</script>
v-model 实现
this.$emit( )
来自定义事件,但是需要使用model属性来保存, <div id="app">
<test-p v-model="data2"></test-p>
<hr/>
<p>父组件{{data2}}</p>
</div>
<script>
Vue.component("test-p",{
props:["emm","data2"],
model:{
// prop 告诉 v-model 绑定的 prop 是哪个
prop:"data2",
// event 告诉 v-model 触发指定事件时
// 自动去修改绑定的值
event:"back" // 封装的了监听和回调,以及赋值
},
data:function(){
return {
name:"子数据",
text:"测试数据",
}
},
template:`
{{text}}
子组件的数据:{{data2}}
`,
methods:{
went(){
// console.log(11)
this.$emit("back",this.name)
}
}
})
let app = new Vue({
el:"#app",
data:{
name:`我来自父组件`,
text:"父组件测试数据",
data2:"双向数据2"
},
methods:{
fn(n){
console.log(n)
this.text = n;
}
}
});
</script>
.sync 实现
:自定义变量名="传递数据"
的方式传递数据给子组件props:["自定义变量名"]
方式的接收数据:自定义名称.sync="传递数据"
,this.$emit("update:自定义名称",回传数据)
<div id="app">
<my-try :nowpage.sync="uPage" > </my-try>
<div>{{uPage}}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 测试说明 .sync 使用
Vue.component("my-try",{
props:["nowpage"],
template:`
`,
methods:{
test(){
// console.log("测试数据启用");
console.log("当前第"+this.nowpage+"页");
this.$emit("update:nowpage",this.nowpage +1);
}
}
})
let app = new Vue({
el: '#app',
data: {
uPage: 1,
}
});
组件模板解析后会替换整个组件内容,( 原先写在页面上所有内容都会被覆盖 )
改善了修改组件内容,需要去组件内部的操作的繁琐步骤
相当于在组件上留下接口,便于后续增添内容
使用内置组件 template
与 v-slot
指令进行配置
Vue.component("page-div", {
template: `
写什么不重要,反正不实现
`,
})
slot
来实现 <div id="app">
<page-div>
<span slot="default">默认插槽span>
page-div>
div>
默认插槽
上述的方法即为 默认插槽 的实现
具名插槽
通过设置 name 属性实现,例:
调用的时候 通过 template
标签添加 v-slot:name名='数据'
实现
Vue.component("page-div", {
template: `
1234
`,
})
<div id="app">
<page-div>
<template v-slot:all="{all}">
<a class="tj" >共……页a>
template>
page-div>
div>
其实已经在具名插槽时实现了
template
标签添加 v-slot:name名='数据'
实现数据传递
只是传递的 数据类型为对象形式,需要解构赋值或者通过点语法使用
<div id="app">
<page-div @get-data="play" :txt="default_page" :total="allpages">
<template v-slot:now="props" >
<a class="tj">第{{props.now}}页a>
template>
<template v-slot:all="{all}">
<a class="tj" >共{{all}}页a>
template>
page-div>
div>
<script>
Vue.component("page-div", {
props: ["txt", "total"],
template: `
`,
// 维持数据的独立性
data: function () {
return {
users: [
{ id: 1, name: "兰博", talk: "谁说我是小个子" },
{ id: 2, name: "鑫涛", talk: "我是最强壮的男人" },
{ id: 3, name: "光达", talk: "对对对,是是是" },
{ id: 4, name: "宝峰", talk: "我尼玛人都傻了" },
{ id: 5, name: "祥子", talk: "那必不可能是那样" },
{ id: 6, name: "亚托克斯", talk: "我是噬神者" },
{ id: 7, name: "女警", talk: "砰,脑洞!" },
{ id: 8, name: "洛", talk: "是谁在那儿?!" },
{ id: 9, name: "锤石", talk: "出来玩玩?" },
{ id: 10, name: "秦兟", talk: "?!……" },
],
perpage: 3,
nowpage: 1
}
},
computed: {
showUsers: {
get() {
return JSON.parse(JSON.stringify(this.users)).splice((this.nowpage - 1) * this.perpage, this.perpage)
}
},
pages() {
return Math.ceil(this.users.length / this.perpage)
}
},
methods: {
goOn(p) {
this.nowpage = p;
let obj = {
page: this.nowpage,
data: this.showUsers,
all: this.pages
}
this.$emit("get-data", obj);
}
}
})
let app = new Vue({
el: "#app",
data: {
users: [
{ id: 1, name: "兰博", talk: "谁说我是小个子" },
{ id: 2, name: "鑫涛", talk: "我是最强壮的男人" },
{ id: 3, name: "光达", talk: "对对对,是是是" },
],
default_page: 1,
allpages:"…"
},
methods: {
play: function (v) {
this.users = v.data;
this.default_page = v.page;
this.allpages = v.all;
}
}
});
script>
是指数据传向一个组件,但是该组件并没有相应 prop
定义的特性
这些 props
会被自动添加到组件的根元素上
可以通过this.$attrs.属性名
调用
<div id="app">
<k-div :myname="name" :mypage="pages" :mytry="text"> k-div>
div>
this.$attrs.属性名
直接使用 Vue.component("k-div",{
// props: 没有接收 mypage 非 常规操作
// mypage会出现在 this.$attrs 中 (即 根元素上)
props:["myname"],
inheritAttrs:false, // 默认是 true 处理 子组件继承的问题
template:`
props没接收的数据 mypage{{this.$attrs.mypage}}
`,
data:function(){
return {
name:`kids`,
mypage:"hello,我在这"
}
},
methods:{
getData(){
console.log(this.$attrs)
}
}
})
适用于检查数据类型的场景,
不符合的情况下,会提示错误信息,但不会阻断程序运行
<div id="app">
<k-div :msg="pages"> k-div>
div>
<script>
let app = new Vue({
el:"#app",
data:{
text:"测试文本信息",
pages:20
}
});
script>
Vue.component("k-div",{
props:{
// 验证传递的数据类型
// 不满足数据类型时,会报错只是不会阻断运行
msg:[String]
},
template:`
测试而已{{msg}}
`
})