组件使用细节点
解决元素标签位置错误的问题:is 属性
<div id="app">
<table>
<tbody>
<!--tbody里要用一个组件,但不能直接写组件名
会导致位置错误问题,使用 is 属性将自定义组件row
与 tr 标签绑定在一起
-->
<tr is=‘row‘></tr>
<tr is=‘row‘></tr>
<tr is=‘row‘></tr>
</tbody>
</table>
<ul>
<li is=‘row‘></li>
<li is=‘row‘></li>
<li is=‘row‘></li>
</ul>
</div>
<script>
Vue.component(‘row‘, {
template: ‘<tr><td>this is a row</td></tr>‘
});
var vm = new Vue({
el: "#app"
});
</script>
组件data函数
在子组件中,data 必须是一个函数,有可能一个子组件会被调用很多次,每个子组件数据不能产生冲突,通过一个函数返回一个对象的目的,就是让每个子组件都拥有独立的数据存储。
Vue.component(‘row‘, {
//在子组件中,data 必须是一个函数
data: function(){
return {
content: ‘this is a row‘
}
},
template: ‘<tr><td>{{content}}</td></tr>‘
});
ref的使用
<div id="app">
<counter ref="one" @change="handleChange"></counter>
<counter ref="two" @change="handleChange"></counter>
<div>{{total}}</div>
</div>
<script>
Vue.component(‘counter‘,{
template: ‘<div @click="handleClick">{{number}}</div>‘,
data: function(){
return {
number: 0
}
},
methods: {
handleClick: function() {
this.number ++;
// $emit() 自定义事件向父组件通信
this.$emit(‘change‘);
}
}
});
var vm = new Vue({
el: "#app",
data: {
total: 0
},
methods: {
handleChange: function() {
//可以使用自加一方法
//this.total++;
//也可以求二者之和
// 通过 $refs 获取子组件的引用,再获取数据
this.total = this.$refs.one.number + this.$refs.two.number;
}
}
});
父子组件的数据传递
父组件通过属性的形式向子组件传递数据
Vue 中的单项数据流:父组件可以向子组件传递参数,该参数在父组件可随便修改,子组件绝对不能反过来去修改父组件传递过来的参数,只用不改
<div id="app">
<!--父往子传递-->
<!--父组件通过绑定属性的形式向子组件传递数据-->
<counter :count="3" @inc="handleIncrease"></counter>
<counter :count="2" @inc="handleIncrease"></counter>
<!--子往父传递-->
<!--子组件通过事件触发的形式向父组件传递数据-->
<div>{{total}}</div>
</div>
<script>
var counter = {
props: [‘count‘],
data: function() {
return {
//定义一个number 把获取来的数据克隆一个传进去
number: this.count
}
},
template: ‘<div @click="handleClick">{{number}}</div>‘,
methods: {
handleClick: function() {
this.number += 2;
//子组件通过点击将事件触发出去
this.$emit(‘inc‘, 2)
}
}
}
var vm = new Vue({
el: "#app",
components: {
counter: counter
},
data: {
total: 5
},
methods: {
// 父组件执行的函数里可以直接接收到 $emit()的参数
handleIncrease: function(step) {
this.total += step;
}
}
});
组件参数校验与非props特性
<div id="app">
<child :content="123"></child>
</div>
<script>
Vue.component(‘child‘,{
props: {
//设定子组件接收的content 属性,
// 要么是数字,要么是字符串
content: [String, Number]
/*
也可以这样写:
content: {
//类型
type: String,
//设定这个属性是必须的
required: true,
//如果不给default 传数值,默认default
default: ‘default value‘,
//对传入 content属性 添加校验
//规定长度必须大于5
validator: function(value) {
return (value.length > 5)
}
}
*/
},
template: ‘<div>{{content}}</div>‘
})
var vm = new Vue({
el: "#app"
});
props 特性:
父组件传递了content 子组件又声明了一个content接收; 二者有一个对应关系。该属性不会在DOM中出现,子组件可直接通过插值表达式调用content内的内容。
非props 特性
父组件传递一个属性,但是子组件并没有props的内容,没有声明,无法获取父组件内容。该属性会在子组件DOM中出现
给组件绑定原生事件
<div id="app">
<!--
加native修饰符,监听原生点击事件,
方法同子组件设置自定义事件向父组件触发
-->
<child @click.native=‘handleClick‘></child>
</div>
<script>
Vue.component(‘child‘,{
template: ‘<div>child</div>‘
})
var vm = new Vue({
el: "#app",
methods: {
handleClick: function() {
alert(‘click‘)
}
}
});
</script>
非父子组件间的传值
- 借助官方的数据框架 vuex解决
- 发布订阅模式 总线机制 Bus 观察者模式
<!--非父子组件传值
Bus / 总线 / 发布订阅模式 / 观察者模式
-->
<div id="app">
<!--点击一个,另一个变成相同的-->
<child content=‘anqw‘></child>
<child content=‘joe‘></child>
</div>
<script>
//每一个Vue 实例都会有bus 属性
Vue.prototype.bus = new Vue()
Vue.component(‘child‘,{
data: function() {
return {
//父组件传过来的数据只能用不能改,
//所以需要拷贝一份
selfContent: this.content
}
},
props: {
content: String
},
template: ‘<div @click="handleClick">{{selfContent}}</div>‘,
methods: {
handleClick: function() {
//实例上挂载的bus ,这个bus 又是Vue 实例,
//所以会有$emit()方法,同时把内容传进参数
this.bus.$emit(‘change‘,this.selfContent);
}
},
//借助生命周期钩子,被挂载时执行
//$on 方法监听自定义事件
mounted: function() {
//固定this的指向
var this_ = this;
this.bus.$on(‘change‘, function(msg) {
this_.selfContent = msg
})
}
})
var vm = new Vue({
el: "#app"
});
在Vue中使用插槽 slot
<div id="app">
<child>
<!--插槽-->
<!--如果不传标签会显示默认内容-->
<h1>Anqw</h1>
</child>
</div>
<script>
Vue.component(‘child‘,{
//slot插槽中显示的是父组件插入的标签
template: ‘<div><p>hello</p><slot>默认内容</slot></div>‘
})
var vm = new Vue({
el: "#app"
});
</script>
将多个插槽一一对应
<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‘,{
//将插槽一一对应,用slot 与 name 属性绑定
template: `<div>
<slot name=‘header‘></slot>
<div class="content">
content
</div>
<slot name=‘footer‘></slot>
</div>`
});
var vm = new Vue({
el: "#app"
});
</script>
<!--
显示结果:
header
content
footer
-->
Vue 中的作用域插槽
<div id="app">
<child>
<!--首先父组件内传了一个插槽,
作用域插槽,必须用 template 标签包裹,
同时声明从子组件接收的数据都放在props中,
slot-scope 对应的属性名接收到数据后,
以li的形式进行展示.
-->
<template slot-scope="props">
<!--由父组件传递循环对应的模板-->
<li>{{props.item}} - hello</li>
</template>
</child>
</div>
<script>
Vue.component(‘child‘,{
data: function() {
return {
list: [1,2,3,4]
}
},
//当子组件做循环,DOM结构需要由外部传递时
template: `<div>
<ul>
<slot
v-for="item of list"
:item="item">
</slot>
</ul>
</div>`
});
var vm = new Vue({
el: "#app"
});
</script>
动态组件与v-once指令
<div id="app">
<!--动态组件-->
<!--会根据 is 中数据的变化去加载不同的组件-->
<!--<component :is="type"></component>-->
<child-one v-if="type === ‘child-one‘"></child-one>
<child-two v-if="type === ‘child-two‘"></child-two>
<button @click="handleClick">change</button>
<!--当点击button时 两个组件 toggle显示-->
</div>
<script>
Vue.component(‘child-one‘,{
// v-once 可以把组件暂时放到内存里,
// 点击之后直接从内存里取出就行,提高了性能
template: ‘<div v-once>child-one</div>‘
});
Vue.component(‘child-two‘,{
template: ‘<div v-once>child-two</div>‘
});
var vm = new Vue({
el: "#app",
data: {
type: ‘child-one‘
},
methods: {
handleClick: function() {
this.type = (this.type === ‘child-one‘?
‘child-two‘: ‘child-one‘);
}
}
});
</script>
原文地址:https://www.cnblogs.com/anqwjoe/p/9053431.html
时间: 2024-10-10 02:16:53