vue component 调用父方法 is not a function_深入理解vue组件

d5d8f327b9f696534281bb1e9edc8b8f.png

使用组件的细节点

  1. is属性: 有些html标签如table,ul,ol,select对哪些标签可以出现在其内部是有着严格的要求的。 因此当这些标签内部出现了自定义组件,有可能会被作为无效的内容提升到外部,导致页面渲染出错。 而是用is属性则可以解决这个问题,在子级标签中用is属性来使用自定义组件。
  1. 子组件中的data必须是一个函数,并且返回一个对象,当一个组件被多次使用的时候,组件间的数据不会相互影响。
Vue.component('row', {
    data:function () {
          return{
              content:'this is row'
          }
    },
    template:"<tr><td>{{content}}</td></tr>"
})
  1. 通过ref 获取dom节点
<div @click="handdle" ref="hello">
    hello world
</div>

handdle:function(){
    console.log(this.$refs.hello)
}

父子组件传值

  1. 父组件向子组件传值

父组件通过属性绑定将值绑定到子组件上,子组件通过 props 属性来接收,然后子组件就可以使用父组件中传递过来的数据了。props是一个数组。

  1. 子组件向父组件传值:
  • 子组件通过this.$emit()方法向父组件传值;
  • $emit("事件名",args)第一个参数是自定义事件名,第二个参数是需要传递的数据
  • 父组件使用v-on监听子组件
  1. 单向数据流

父组件可以随意向子组件传递参数,子组件不可以改变父组件的数据,否则会报警告。 解决办法:要想改变父组件的参数,在子组件的data属性中拷贝一份父组件的数据,然后可以对数据进行操作。

<div id="app">
    <counter :count="1" @change="handleAdd"></counter>
    <counter :count="2" @change="handleAdd"></counter>
    <div>{{total}}</div>
</div>
<script>
    var counter = {
        props:['count'],
        data:function(){
          return{
              number:this.count
          }
        },
        template:'<div @click="handdle">{{number}}</div>',
        methods:{
            handdle:function(){
                this.number++;
                this.$emit('change',1)
            }
        }
    }
    var app = new Vue({
        el:'#app',
        data:{
          total:3
        },
        components:{
            counter:counter
        },
        methods: {
            handleAdd:function(step){
                this.total+=step
            }
        }
    })
</script>

组件参数校验与非props特性

  1. 简单校验:限定传入的值的类型,可以是单个类型,也可以是一个数组。
props:{
  content: [String,Number]
}
  1. 复杂校验:
props:{
 content:{
  type: String,//数据类型
  required: false,//是否是必传
  default: 'default content',//如果没传值,默认值
  validator: function(val){//自定义校验器,数据必须>5
    return (val.length>5)
  }
 }
}

给组件绑定原生事件

  1. 在父组件上绑定事件(如:@click.native="handleClick")
  2. 在vue实例中的methods下定义事件函数。
<child @click.native="handleClick" ></child>

传统方法绑定事件:

  1. 在子组件上绑定事件
  2. 在子组件中的methods中设置相应的事件函数,并在函数中定义自定义事件函数,将自定义事件函数传给父组件(如 this.$emit('click'))
  3. 在父组件上绑定子组件methods函数中传来的自定义函数
  4. 在父组件methods中设置对应的事件函数

非父子组件间的传值

  1. vuex,
  2. 发布订阅模式(总线模式)
  • 给 Vue 类加上原型属性 bus, 这样每个 Vue 实例都能访问到原型属性 bus
 Vue.prototype.bus = new Vue()
  • 利用 bus 的实例方法 $emit 触发事件
this.bus.$emit('触发事件', this.selfContent)
  • 再利用生命周期方法(钩子) mounted 给 bus 绑定监听函数, 在事件触发时执行
 this.bus.$on('eventName', cellback)
  • 建议使用箭头函数做为回调函数,不会影响回调函数中this的指向问题
 this.bus.$on('eventName',(msg) => {
     this.selfContent = mag;
 })

完整代码

<div id="app">
    <child  content="Dell"></child>
    <child  content="Lee"></child>
</div>
<script>
 Vue.prototype.bus = new Vue()
    Vue.component('child',{
        data:function(){
          return{
              selfContent:this.content
          }
        },
        props:{
            content:{
                type:String,
            }
        },
        template:'<div @click="handClick">{{selfContent}}</div>',
        methods: {
            handClick:function () {
                this.bus.$emit('change',this.selfContent)
            }
        },
        mounted:function(){
            var that = this;
           this.bus.$on('change',function(msg){
             that.selfContent = msg
           })
        }
    })
    var app = new Vue({
        el:'#app',
    })
</script>

vue中使用插槽

  1. 插槽:可以使父组件很容易向子组件传递DOM元素
  2. 匿名插槽:父组件内部的DOM元素,可以通过子组件的标签渲染,slot标签中可以写默认的内容,如果父组件中不传递就显示默认内容
Vue.component('child',{
        template:'<div>' +
            '<slot>默认内容</slot>' +
            '</div>',
    })
  1. 具名插槽:有名字的插槽,父组件中为slot属性设置值,子组件slot中使用name属性接收父组件slot的属性值可以实现具名插槽。
<div id="app">
    <body-content>
       <div class="header" slot="header">header</div>
       <div class="footer" slot="footer">footer</div>
    </body-content>
</div>
<script>
Vue.component('body-content',{
    template:'<div>' +
        '<slot name="header">默认</slot>' +
        '<div class="content">content</div>' +
        '<slot name = "footer"></slot>' +
        '</div>'
})
    var app = new Vue({
        el:'#app',
    })
</script>
  1. 作用域插槽
  • 使用场景:当子组件做循环的数据和结构需要外部传入时
  • 父组件中必须以
<template slot-scope='自定义'></template>

作为包裹的标签,slot-scope接受子组件传递过来的值

  • 作用是:可以使父组件灵活的控制样式
<div id="app">
    <child>
     <template slot-scope="props">
         <h1>{{props.item}}</h1>
     </template>

    </child>
</div>
<script>
Vue.component('child',{
    data:function(){
      return{
          list:[1,2,3,4]
      }
    },
    template:"<div><ul>" +
        "<slot v-for='item of list' :item = item></slot>" +
        "</ul></div>"
})
    var app = new Vue({
        el:'#app',
    })
</script>

动态组件与v-once指令

  1. 使用is与使用:is的区别:
  • is:如果这里使用is,is=后面跟的是字符串,就是指将当前使用is替换为名为type的组件,
  • :is:如果使用:is,其实,就是v-bind:is,:is=后面跟的就是一个JS表达式,表达式为type指向了type这个对象
  1. vue自带的动态标签
<component></component>

根据type的值变换为相应的组件 如果点击按钮前是type=“one”则会显示vue.component(“one”,{})这个组件 如果点击前按钮是type=“two”则会显示vue.component(“two”,{})这个组件

<div id="app">
    <component :is="type"></component>
    <button @click="handclick">点击</button>
</div>
<script>
Vue.component('child-one',{
    template:'<div>one</div>'
})
Vue.component('child-two',{
    template:'<div>two</div>'
})
    var app = new Vue({
        el:'#app',
        data:{
            type:'child-one'
        },
        methods:{
            handclick:function(){
                this.type = this.type =='child-one'?'child-two':'child-one'
            }
        }
    })

  1. v-once只对内部渲染一次,如果模板发生变化,也不会理会
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值