使用组件的细节点
is属性: 有些html标签如table,ul,ol,select对哪些标签可以出现在其内部是有着严格的要求的。 因此当这些标签内部出现了自定义组件,有可能会被作为无效的内容提升到外部,导致页面渲染出错。 而是用is属性则可以解决这个问题,在子级标签中用is属性来使用自定义组件。
子组件中的data必须是一个函数,并且返回一个对象,当一个组件被多次使用的时候,组件间的数据不会相互影响。
Vue.component('row', { data:function () { return{ content:'this is row' } }, template:"{{content}}"})
通过ref 获取dom节点
hello world
handdle:function(){ console.log(this.$refs.hello)}
父子组件传值
- 父组件向子组件传值
父组件通过属性绑定将值绑定到子组件上,子组件通过 props 属性来接收,然后子组件就可以使用父组件中传递过来的数据了。props是一个数组。
- 子组件向父组件传值:
子组件通过this.$emit()方法向父组件传值;
$emit("事件名",args)第一个参数是自定义事件名,第二个参数是需要传递的数据
父组件使用v-on监听子组件
- 单向数据流
父组件可以随意向子组件传递参数,子组件不可以改变父组件的数据,否则会报警告。 解决办法:要想改变父组件的参数,在子组件的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特性
简单校验:限定传入的值的类型,可以是单个类型,也可以是一个数组。
props:{ content: [String,Number]}
复杂校验:
props:{ content:{ type: String,//数据类型 required: false,//是否是必传 default: 'default content',//如果没传值,默认值 validator: function(val){//自定义校验器,数据必须>5 return (val.length>5) } }}
给组件绑定原生事件
在父组件上绑定事件(如:@click.native="handleClick")
在vue实例中的methods下定义事件函数。
<child @click.native="handleClick" >
传统方法绑定事件:
在子组件上绑定事件
在子组件中的methods中设置相应的事件函数,并在函数中定义自定义事件函数,将自定义事件函数传给父组件(如 this.$emit('click'))
在父组件上绑定子组件methods函数中传来的自定义函数
在父组件methods中设置对应的事件函数
非父子组件间的传值
vuex,
发布订阅模式(总线模式)
给 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中使用插槽
插槽:可以使父组件很容易向子组件传递DOM元素
匿名插槽:父组件内部的DOM元素,可以通过子组件的标签渲染,slot标签中可以写默认的内容,如果父组件中不传递就显示默认内容
Vue.component('child',{ template:'
' + '默认内容' + '
', })具名插槽:有名字的插槽,父组件中为slot属性设置值,子组件slot中使用name属性接收父组件slot的属性值可以实现具名插槽。
header
footer
作用域插槽
使用场景:当子组件做循环的数据和结构需要外部传入时
父组件中必须以
作为包裹的标签,slot-scope接受子组件传递过来的值
作用是:可以使父组件灵活的控制样式
动态组件与v-once指令
使用is与使用:is的区别:
is:如果这里使用is,is=后面跟的是字符串,就是指将当前使用is替换为名为type的组件,
:is:如果使用:is,其实,就是v-bind:is,:is=后面跟的就是一个JS表达式,表达式为type指向了type这个对象
vue自带的动态标签
根据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' } } })复制代码
- v-once只对内部渲染一次,如果模板发生变化,也不会理会