vue 插槽slot與provide/inject跨元件傳值
阿新 • • 發佈:2018-11-06
vue 插槽slot
1. 預設插槽
const component = {
template: `
<div :style="style">
<slot></slot>
</div>
`,
data () {
return {
style: {
width: '200px',height: '100px',border: '1px solid #aaa'
}
}
}
}
new Vue({
el: '#root',
data () {
return {
value: '123'
}
},
template: `
<div>
<comp>
<span>I am slot</span>
</comp>
</div>
`,
components: {Comp: component}
})
*/
2. 具名插槽
const component = {
template: `
<div :style="style">
<div class="header">
<slot name="header"></slot>
</div>
<div class="body">
<slot name="body"></slot>
</div>
<div>common footer</div>
</div>
`,
data () {
return {
style: {
width: '200px',height: '100px',border: '1px solid #aaa'
}
}
}
}
new Vue({
el: '#root',
data () {
return {
value: '123'
}
},
template: `
<div >
<comp>
<span slot="header">I am header</span>
<span slot="body">I am body</span>
</comp>
</div>
`,
components: {Comp: component}
})
3. 作用域插槽
const component = {
template: `
<div :style="style">
<slot :value="value" abc="111"></slot>
</div>
`,
data () {
return {
style: {
width: '200px',height: '100px',border: '1px solid #aaa'
},
value: '456'
}
}
}
new Vue({
el: '#root',
data () {
return {
value: '123'
}
},
template: `
<div>
<comp ref="comp">
<span slot-scope="pp" ref="span">{{pp.value}} {{pp.abc}}</span>
</comp>
</div>
`,
mounted () {
console.log(this.$refs.comp) // VueComponent物件
console.log(this.$refs.comp.value) // 456
console.log(this.$refs.span) // span節點
},
components: {Comp: component}
})
4.inject provide 子孫元件(跨元件)傳值
onst ChildComp = {
template: `<div>
<span>child component</span>
<span> {{value}}</span>
</div>`,
inject: ['grandParent', 'value'],
mounted () {
console.log(this.$parent.$options.name) // Vue 物件
console.log(this.grandParent, this.value) // '123'
}
}
const component = {
name: 'comp',
components: {
ChildComp
},
template: `
<div>
<slot :value="value" abc="111"></slot>
<child-comp></child-comp>
</div>
`,
data () {
return {
value: 'component value'
}
}
}
new Vue({
el: '#root',
data () {
return {
value: '123'
}
},
provide () {
return {
grandParent: this,
value: this.value
}
},
template: `
<div>
<comp ref="comp">
<span slot-scope="pp" ref="span">{{pp.value}} {{pp.abc}} {{value}}</span>
</comp>
<input v-model="value" >
</div>
`,
components: {Comp: component}
})
根元件input用v-model更改value,並不會導致孫元件ChildComp的value值實時更改
5.跨元件的資料繫結
在跟元件的provide中,使用defineProperty,getter獲取value,這樣孫元件ChildComp就能實時獲取到根元件的value,達到v-model的效果
const ChildComp = {
template: `<div>
<span>child component : </span>
<span> {{data.value}}</span>
</div>`,
inject: ['grandParent', 'data']
}
const component = {
name: 'comp',
components: {
ChildComp
},
template: `
<div>
<slot :value="value" abc="111"></slot>
<child-comp></child-comp>
</div>
`,
data () {
return {
value: 'component value'
}
}
}
new Vue({
el: '#root',
data () {
return {
value: '123'
}
},
provide () {
const data = {}
Object.defineProperty(data, 'value', {
get: () => this.value,
enumerable: true
})
return {
grandParent: this,
data
}
},
template: `
<div>
<comp ref="comp">
<span slot-scope="pp" ref="span">{{pp.value}} {{pp.abc}} {{value}}</span>
</comp>
<input v-model="value" >
</div>
`,
mounted () {
},
components: {Comp: component}
})