Vue学习-组件中的数据通信

目录
  • 组件可以访问Vue实例数据吗?
  • 组件的data参数
  • 组件中的methods函数
  • 父子组件
    • 使用场景
    • 如何通信(传递数据)
    • 父传子
    • 子传父
  • 组件中的双向绑定
  • 父组件访问子组件($children或$refs)
  • 子组件访问父组件($parent)
  • 组件的扩展-slot
    • 基本使用
    • 具名插槽

组件可以访问Vue实例数据吗?

  • 组件是一个单独功能模块的封装,有属于自己的HTML模板,也有自己的数据data

  • 组件中不能直接访问Vue实例里的数据,以下代码在组件是不能访问到message的

组件的data参数

  • 组件定义时也有一个data参数,但这个data参数不像Vue实例的data是一个对象类型,它这里是一个函数类型,如果你定义成了一个对象类型,会报以下错误
    Vue学习-组件中的数据通信_第1张图片
  • 该data函数需要返回一个对象,对象内部保存着数据
  • 示例代码:https://jsrun.net/EevKp/edit
const cpnC = Vue.extend({
    template: "#cpn",
    data(){
        return {
            title:"这里是标题吧",
            content:"这里是内容哦!~~"
        }
    }
})

组件中的methods函数

  • 用于定义一些事件处理的函数,同Vue实例里的methods函数类型
  • 示例代码:https://jsrun.net/JevKp/edit
const cpnC = Vue.extend({
    template: "#cpn",
    data(){
        return {
            counter:0
        }
    },
    methods:{
        increment:function(){
            this.counter++
        },
        decrement:function(){
            this.counter--
        }
    }
})

父子组件

使用场景

  • 比如一个商城的首页,上面有一个轮播图,下面有一个商品的列表
    Vue学习-组件中的数据通信_第2张图片
  • 像这种页面,我们在开发时,会在最外层组件(父组件)里,向服务端一次请求到轮播图,商品列表数据,然后将数据分别传给轮播图组件,商品列表组件;然后商品列表组件在将数据传传商品组件来进行整个页面的渲染

如何通信(传递数据)

  • Vue实例也可以看作一个父组件
    Vue学习-组件中的数据通信_第3张图片

父传子

  • 通过prots向子组件传数据(protsproterties的简写,意为属性
  • props的二种方式
    1.一种是可以传一个字符串数组,里面第一项对应变量名
    将godos和message传给子组件进行渲染,示例代码:http://jsrun.net/5PvKp/edit
//1.Vue.extend创建组件 const cpnC = Vue.extend({ template: "#cpn1", props:['cgoods','cmessage'] }) //2.注册组件 Vue.component('my-cpn', cpnC) const app = new Vue({ el: "#app", data: { message: "我是message", goods:["衣服","鞋子","帽子","短裤"] } })

2.第二种是传一个对象类型,可以进行类型限制type和默认值default,是否必需reauired
type-指定参数的类型,有:String,Array,Boolean,Number,Date,Function,Symbol
default-指定默认值
reauired-指定是否必须要传该参数,是boolean类型,传(true或false)

const cpnC = Vue.extend({
    template: "#cpn1",
    props: {
        //1.类型限制
        // cgoods: Array,
        // cmessage: String

        //2.提供默认值,没传时显示
        cgoods:{
            type:Array,
            default:[]
        },
        cmessage:{
            type:String,
            default:"这里是默认值",
            required:true
        }
    }
})

  • props的一些使用示例
Vue.component('cnp',{
      props:{
            //1.基础的类型检查(null匹配任何类型)
            propA:Number,
            //2.多个可能的类型
            propB:[String,Number],
            //3.必填的字符串
            propC:{
                  type:String,
                  required:true
            },
            //4.带有默认值的数字
            propD:{
                  type:Number,
                  default:100
            },
            //5.默认值的对象,数组或对象的需要返回一个函数
            propE:{
                  type:Object,
                  default:function(){
                        return {name:"hello"}
                  }
            },
            //6.带自定义验证函数
            propF:{
                  validator:function(val){
                        //这个val必须匹配下列数组中的一个
                        return ['张三','李四','王五'].indexOf(val) !== -1
                  }
            }
      }
})
  • 组件中驼峰标识,props中定义了cTitle,但在组件使用是需要变为:c-title,子组件中使用时又为cTitle

//1.Vue.extend创建组件
const cpnC = Vue.extend({
    template: "#cpn1",
    props: {
        //驼峰标识
        cTitle:{
            type:String
        }
    }
})

//2.注册组件
Vue.component('my-cpn', cpnC)

const app = new Vue({
    el: "#app",
    data: {
        title:"我是驼峰标识"
    }
})

子传父

  • 通过emit发送自定义事件向父组件发送消息
    示例代码:http://jsrun.net/J7vKp/edit
    Vue学习-组件中的数据通信_第4张图片

{{message}}

//1.Vue.extend创建组件
const cpnC = Vue.extend({
    template: "#cpn1",
    data: function () {
        return {
            students: [
                { id: "001", name: "关晓彤",imgUrl:"https://5b0988e595225.cdn.sohucs.com/images/20181224/ecf125cb199d4808a067f682c6c5e6c6.jpeg" },
                { id: "002", name: "迪丽热巴",imgUrl:"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1593861542943&di=9fe9365124a4aae6cc6cf483aa2a9e18&imgtype=0&src=http%3A%2F%2Fb.hiphotos.baidu.com%2Fzhidao%2Fwh%253D680%252C800%2Fsign%3Dbb541c4377f40ad115b1cfe56f1c3de7%2F50da81cb39dbb6fde349ce5d0524ab18972b37be.jpg" },
                { id: "003", name: "郑爽",imgUrl:"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1593861570612&di=60b6d39dcbac9e1ea77b747d42f9f19d&imgtype=0&src=http%3A%2F%2Ftc.sinaimg.cn%2Fmaxwidth.800%2Ftc.service.weibo.com%2Fmmbiz_qpic_cn%2F1ab918195e7c8a94cc6c95182fbde786.jpg" },
                { id: "004", name: "杨幂",imgUrl:"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1593861759697&di=6771e7279c145513968ce221a29a6b0e&imgtype=0&src=http%3A%2F%2Fphotocdn.sohu.com%2F20130816%2FImg384334041.jpg" }
            ]
        }
    },
    methods: {
        btnclick(item) {
            //发射事件,自定义事件
            this.$emit("itemclick", item)
        }
    }
})

const app = new Vue({
    el: "#app",
    components: {
        "my-cpn": cpnC
    },
    data: {
        message: "",
        imgUrl:""
    },
    methods: {
        btnClick: function (item) {
            this.message = "你选择了:" + item.name + ",学号:" + item.id
            this.imgUrl=item.imgUrl
        }
    }
})

组件中的双向绑定

  • 不能直接绑定props里的属性,要绑定data里定义的属性
  • 示例:http://jsrun.net/R7vKp/edit
//1.Vue.extend创建组件
const cpnC = Vue.extend({
    template: "#cpn",
    data(){
        return {
            dnumber:this.number1
        }
    },
    props:{
        number1:{
            type:Number,
            default:0
        }
    },
    methods:{
        numInput:function(event){
            this.dnumber=event.target.value
        }
    }
})

const app = new Vue({
    el: "#app",
    components:{
        'my-cpn':cpnC
    },
    data: {
        num: 1
    }
})

父组件访问子组件($children或$refs)

  • $children-是一个数组,通过下标访问,这种方式不建议使用,因为组件变化维护后,相应的下标也要变化,后期难维护
    示例代码:http://jsrun.net/VcvKp/edit
const app = new Vue({ el: "#app", methods:{ btnClick:function(){ //1.$children是一个数组 alert(this.$children[0].title) }, }, components:{ 'my-cpn':{ template:"#cpn", data(){ return { title:"我是子组件的标题" } } } } })
  • $refs-通过在组件上定义ref进行访问
    示例代码:http://jsrun.net/7cvKp/edit
const app = new Vue({ el: "#app", methods:{ btnClick:function(){ //1.$children是一个数组 //alert(this.$children[0].title) alert(this.$refs.aaa.title) }, }, components:{ 'my-cpn':{ template:"#cpn", data(){ return { title:"我是子组件的标题" } } } } })

子组件访问父组件($parent)

  • 子组件通过$parent访问父组件
  • $root可以用来访问根组件,一般是Vue实例
    示例代码:http://jsrun.net/dcvKp/edit

{{message}}

const app = new Vue({
    el: "#app",
    data: {
        message: "我是Vue标题"
    },
    components: {
        'my-cpn': {
            template: "#cpn",
            methods: {
                btnClick: function () {
                    alert(this.$parent.message)
                    //访问根组件还可以使用$root,根组件一般是Vue实例
                    //我们这里的parent就等于根组件
                    //alert(this.$root.message)
                }
            }
        }
    }
})

组件的扩展-slot

基本使用

  • 使组件具有更好的扩展性,引入了slot插槽的概念
  • slot可以有默认值
  • 示例代码:http://jsrun.net/DcvKp/edit
    Vue学习-组件中的数据通信_第5张图片

{{message}}

我是slot 我是slot span
const app = new Vue({
    el: "#app",
    data: {
        message: "我是Vue标题"
    },
    components: {
        'my-cpn': {
            template: "#cpn"
        }
    }
})

具名插槽

  • 使用场景-一个组件中有需要多个插槽的情况
  • 示例代码:http://jsrun.net/DcvKp/edit
    Vue学习-组件中的数据通信_第6张图片

{{message}}

center right right
const app = new Vue({
    el: "#app",
    data: {
        message: "我是Vue标题"
    },
    components: {
        'my-cpn': {
            template: "#cpn"
        }
    }
})

你可能感兴趣的:(Vue学习-组件中的数据通信)