一,組件細節
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可以提高性能,它把元素存入內存,方便下次調用