一,组件细节
1,代码测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue组件细节</title>
<script src="vue.js"></script>
</head>
<body>
<div id="root">
<!--is,既保证正确使用组件,又保证符合html5的编码规范-->
<!--直接写<row></row>组件标签,dom元素会错位-->
<!--所谓html5的编码规范,就是tbody下必为tr标签,ul下必为li标签,select下必为option等-->
<table>
<tbody>
<tr is='row'></tr>
<tr is='row'></tr>
<tr is='row'></tr>
</tbody>
</table>
<!--ref引用,用于dom -->
<div
ref='hello'
@click="handleClick"
>
hello world
</div>
<!--ref引用,用于组件 -->
<counter ref="one" @change="handleChange"></counter>
<counter ref="two" @change="handleChange"></counter>
<div>{{total}}</div>
</div>
<!-- 子组件data必须为函数,便于独立每个子组件的数据-->
<script>
Vue.component('row',{
data:function(){
return {
content: 'this is content'
}
},
template:'<tr><td>{{content}}</td></tr>'
})
Vue.component('counter',{
data:function(){
return {
number: 0
}
},
template:'<div @click="handleCounter">{{number}}</div>',
methods:{
handleCounter: function(){
this.number ++
this.$emit('change')
}
}
})
var vm = new Vue({
el:'#root',
data:{
total: 0
},
methods:{
handleClick:function(){
console.log(this.$refs.hello.innerHTML)
},
handleChange:function(){
this.total = this.$refs.one.number +
this.$refs.two.number
}
}
})
</script>
</body>
</html>
2,总结
is
,既保证正确使用组件,又保证符合html5的编码规范- 直接写
<row></row>
组件标签,dom元素会错位 - 所谓html5的编码规范,就是tbody下必为tr标签,ul下必为li标签,select下必为option等
- 直接写
子组件data必须为函数,便于独立每个子组件的数据
- ref引用可以用于dom元素,也可用于组件,再进行对元素或组件的操作
二,父子组件传值
1,代码测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue父子组件传值</title>
<script src="vue.js"></script>
</head>
<body>
<div id="root">
<!-- 父->子 通过属性传值,子组件只能使用父组件传来的值,不能直接修改,可以复制为自己的参数再修改 -->
<counter :count="1" @inc="handleIncrease"></counter>
<counter :count="2" @inc="handleIncrease"></counter>
<div>{{total}}</div>
</div>
<!-- 子->父 通过$emit传值 -->
<script>
var counter = {
props: ['count'],
data: function(){
return {
number : this.count
}
},
template: '<div @click="handleClick">{{number}}</div>',
methods:{
handleClick: function(){
this.number = this.number + 2;
this.$emit('inc' ,2)
}
}
}
var vm = new Vue({
el:'#root',
data:{
total: 5
},
components:{
counter: counter
},
methods:{
handleIncrease:function(step){
this.total += step
}
}
})
</script>
</body>
</html>
2,总结
- 父->子 通过属性传值。(子组件只能使用父组件传来的值,不能直接修改,可以复制为自己的参数再修改)
- 子->父 通过$emit传值。
三,组件参数检验与非props特性
1,代码测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>组件参数检验与非props特性</title>
<script src="vue.js"></script>
</head>
<body>
<div id="root">
<!-- 设置参数检验,字符串和数字可以 -->
<child content="abc"></child>
<child :content="1"></child>
<child :content="'abc'"></child>
<!--<child :content="{1}"></child>-->
</div>
<!--type参数类型,required是否传参,default默认值,validator参数校验方法 -->
<!--非props特性就是没有props,不接收参数,父组件传的属性参数直接在子组件template中显示-->
<script>
Vue.component('child',{
props:{
// content: [String, Number]
content:{
type: [String, Number],
required: false,
default: 'default value',
validator:function(value){
return (value.length > 5)
}
}
},
template:'<div>{{content}}</div>'
})
var vm = new Vue({
el: '#root'
})
</script>
</body>
</html>
2,总结
- type参数类型,required是否传参,default默认值,validator参数校验方法
- 非props特性就是没有props,不接收参数,父组件传的属性参数直接在子组件template中显示(没啥用)
四,给组件绑定原生事件
1,代码测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>给组件绑定原生事件</title>
<script src="vue.js"></script>
</head>
<body>
<div id="root">
<child @click.native="handleClick"></child>
</div>
<script>
Vue.component('child',{
// template:'<div @click="handleChildClick">child</div>',
// methods:{
// handleChildClick:function(){
// alert('child click')
// this.$emit('click')
// }
// }
template:'<div>child</div>',
methods:{
handleChildClick:function(){
alert('child click')
}
}
})
var vm = new Vue({
el: '#root',
methods:{
handleClick:function(){
alert('click')
}
}
})
</script>
</body>
</html>
2,总结
- native绑定原生事件可以代替从
子组件事件
跳转到父组件事件
的过程
五,非父子组件传值
1,代码测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>非父子组件传值(Bus/总线/发布订阅模式/观察者模式)</title>
<script src="vue.js"></script>
</head>
<body>
<div id="root">
<child content="dell"></child>
<child content="lee"></child>
</div>
<script>
Vue.prototype.bus = new Vue()
Vue.component('child',{
data:function(){
return{
selfContent: this.content
}
},
template:'<div @click="handleClick">{{selfContent}}</div>',
props:{
content:String
},
methods:{
handleClick:function(){
this.bus.$emit('change',this.selfContent)
}
},
mounted:function(){
var this_ = this
this.bus.$on('change',function(msg){
//this的作用域变成function内了
//所以在外部提前引用
this_.selfContent = msg
})
}
})
var vm = new Vue({
el: '#root',
methods:{
handleClick:function(){
alert('click')
}
}
})
</script>
</body>
</html>
2,总结
bus.$emit
发送,bus.$on
监听
六,vue的插槽(slot)
1,代码测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue的插槽(slot)</title>
<script src="vue.js"></script>
</head>
<body>
<!--可以用属性传dom元素,复杂情况要用插槽-->
<!--如果插槽不命名,组件内整个dom元素,传入插槽-->
<!--插槽内可设默认值<slot name='header'>default header</slot>,
如果没有<div class="header" slot='header'>header</div>的引用,
则会取默认值-->
<div id="root">
<body-content>
<child content="<p>dell</p>"></child>
<div class="header" slot='header'>header</div>
<div class="footer" slot='footer'>footer</div>
</body-content>
</div>
<script>
// Vue.component('child',{
// props:['content'],
// //用顿号可以格式化dom,不用每行都加了
// template:`<div>
// <p>hello</p>
// <div v-html="this.content"></div>
// </div>`
// })
Vue.component('body-content',{
template:`<div>
<slot name='header'></slot>
<div class='content'>content</div>
<slot name='footer'></slot>
</div>`
})
var vm = new Vue({
el: '#root'
})
</script>
</body>
</html>
2,总结
- 可以用属性传dom元素,复杂情况要用插槽
- 如果插槽不命名,组件内整个dom元素,传入插槽
- 插槽可设默认值
七,vue的作用域插槽
1,代码测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue的作用域插槽</title>
<script src="vue.js"></script>
</head>
<body>
<!--子组件向父组件传值,通过slot-scope,
由父组件去定义item。
template固定写法
-->
<div id="root">
<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 vm = new Vue({
el: '#root'
})
</script>
</body>
</html>
2,总结
- 子组件向父组件传值,通过slot-scope,
- 由父组件去定义item。
- template固定写法
八,动态组件与v-once指令
1,代码测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>动态组件与v-once指令</title>
<script src="vue.js"></script>
</head>
<body>
<!--动态组件可以根据组件的名称进行切换组件-->
<!--v-once可以提高性能,它把元素存入内存,方便下次调用-->
<div id="root">
<component :is="type"></component>
<!--<child-one v-if="type === 'child-one'"></child-one>
<child-two v-if="type === 'child-two'"></child-two>-->
<button @click="handleBtnClick">change</button>
</div>
<script>
Vue.component('child-one',{
template:'<div v-once>child-one</div>'
})
Vue.component('child-two',{
template:'<div v-once>child-two</div>'
})
var vm = new Vue({
el: '#root',
data:{
type:'child-one'
},
methods:{
handleBtnClick:function () {
this.type = this.type === 'child-one' ?
'child-two':'child-one';
}
}
})
</script>
</body>
</html>
2,总结
- 动态组件可以根据组件的名称进行切换组件
- v-once可以提高性能,它把元素存入内存,方便下次调用