方法1: Prop
<div id="app">
<child :content="message"></child>
</div>
// Js
let Child = Vue.extend({
template: '<h2>{{ content }}</h2>',
props: {
content: {
type: String,
default: () => { return 'from child' }
}
}
})
new Vue({
el: '#app',
data: {
message: 'from parent'
},
components: {
Child
}
})
方法2: $emit
<div id="app">
<my-button @greet="sayHi"></my-button>
</div>
let MyButton = Vue.extend({
template: '<button @click="triggerClick">click</button>',
data () {
return {
greeting: 'vue.js!'
}
},
methods: {
triggerClick () {
this.$emit('greet', this.greeting)
}
}
})
new Vue({
el: '#app',
components: {
MyButton
},
methods: {
sayHi (val) {
alert('Hi, ' + val) // 'Hi, vue.js!'
}
}
})
3. .sync 修饰符
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event">
</text-document>
可以简写为:
<text-document v-bind:title.sync="doc.title"></text-document>
// ===============
<div id="app">
<login :name.sync="userName"></login> {{ userName }}
</div>
let Login = Vue.extend({
template: `
<div class="input-group">
<label>姓名:</label>
<input v-model="text">
</div>
`,
props: ['name'],
data () {
return {
text: ''
}
},
watch: {
text (newVal) {
this.$emit('update:name', newVal)
}
}
})
new Vue({
el: '#app',
data: {
userName: ''
},
components: {
Login
}
})
4. $attrs & $listeners
// 组件A
Vue.component('A', {
template: `
<div>
<p>this is parent component!</p>
<B :messagec="messagec" :message="message" v-on:getCData="getCData" v-on:getChildData="getChildData(message)"></B>
</div>
`,
data() {
return {
message: 'hello',
messagec: 'hello c' //传递给c组件的数据
}
},
methods: {
// 执行B子组件触发的事件
getChildData(val) {
console.log(`这是来自B组件的数据:${val}`);
},
// 执行C子组件触发的事件
getCData(val) {
console.log(`这是来自C组件的数据:${val}`);
}
}
});
// 组件B
Vue.component('B', {
template: `
<div>
<input type="text" v-model="mymessage" @input="passData(mymessage)">
<!-- C组件中能直接触发 getCData 的原因在于:B组件调用 C组件时,使用 v-on 绑定了 $listeners 属性 -->
<!-- 通过v-bind 绑定 $attrs 属性,C组件可以直接获取到 A组件中传递下来的 props(除了 B组件中 props声明的) -->
<C v-bind="$attrs" v-on="$listeners"></C>
</div>
`,
/**
* 得到父组件传递过来的数据
* 这里的定义最好是写成数据校验的形式,免得得到的数据是我们意料之外的
*
* props: {
* message: {
* type: String,
* default: ''
* }
* }
*
*/
props: ['message'],
data(){
return {
mymessage: this.message
}
},
methods: {
passData(val){
//触发父组件中的事件
this.$emit('getChildData', val)
}
}
});
// 组件C
Vue.component('C', {
template: `
<div>
<input type="text" v-model="$attrs.messagec" @input="passCData($attrs.messagec)">
</div>
`,
methods: {
passCData(val) {
// 触发父组件A中的事件
this.$emit('getCData',val)
}
}
});
var app=new Vue({
el:'#app',
template: `
<div>
<A />
</div>
`
});
作者:LinFun
链接:https://juejin.im/post/5dc8bd4b6fb9a04a640d7131
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
5. provide & inject
<div id="app">
<son></son>
</div>
let Son = Vue.extend({
template: '<h2>son</h2>',
inject: {
house: {
default: '没房'
},
car: {
default: '没车'
},
money: {
// 长大工作了虽然有点钱
// 仅供生活费,需要向父母要
default: '¥4500'
}
},
created () {
console.log(this.house, this.car, this.money)
// -> '房子', '车子', '¥10000'
}
})
new Vue({
el: '#app',
provide: {
house: '房子',
car: '车子',
money: '¥10000'
},
components: {
Son
}
})
6 slot-scope & v-slot
请注意, v-slot 只能添加到 或自定义组件上,这点与弃用的 slot 属性不同
7 scopedSlots
8 EventBus
9 vuex
10 $parent $children
// 定义 parent 组件
Vue.component('parent', {
template: `
<div>
<p>this is parent component!</p>
<button @click="changeChildValue">test</button>
<child />
</div>
`,
data() {
return {
message: 'hello'
}
},
methods: {
changeChildValue(){
this.$children[0].mymessage = 'hello';
}
},
});
// 定义 child 组件
Vue.component('child', {
template:`
<div>
<input type="text" v-model="mymessage" @change="changeValue" />
</div>
`,
data() {
return {
mymessage: this.$parent.message
}
},
methods: {
changeValue(){
this.$parent.message = this.mymessage;//通过如此调用可以改变父组件的值
}
},
});
const app = new Vue({
el: '#app',
template: `
<div>
<parent />
</div>
`
});
11 $root
12 broadcast / dispatch
// broadcast 方法的主逻辑处理方法
function broadcast(componentName, eventName, params) {
this.$children.forEach(child => {
const name = child.$options.componentName;
if (name === componentName) {
child.$emit.apply(child, [eventName].concat(params));
} else {
broadcast.apply(child, [componentName, eventName].concat(params));
}
});
}
export default {
methods: {
// 定义 dispatch 方法
dispatch(componentName, eventName, params) {
let parent = this.$parent;
let name = parent.$options.componentName;
while (parent && (!name || name !== componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.componentName;
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params));
}
},
// 定义 broadcast 方法
broadcast(componentName, eventName, params) {
broadcast.call(this, componentName, eventName, params);
}
}
};
####### 13 v-model
<custom-input
v-bind:value="searchText"
v-on:input="searchText = $event"
></custom-input>
// =====
// 子组件
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})
父组件
<custom-input v-model="searchText"></custom-input>
####### 14 refs
// 父组件
<home ref="home"/>
mounted(){
console.log(this.$refs.home) //即可拿到子组件的实例,就可以直接操作 data 和 methods
}
15 Vue.observable
// 文件路径 - /store/store.js
import Vue from 'vue'
export const store = Vue.observable({ count: 0 })
export const mutations = {
setCount (count) {
store.count = count
}
}
//使用
<template>
<div>
<label for="bookNum">数 量</label>
<button @click="setCount(count+1)">+</button>
<span>{{count}}</span>
<button @click="setCount(count-1)">-</button>
</div>
</template>
<script>
import { store, mutations } from '../store/store' // Vue2.6新增API Observable
export default {
name: 'Add',
computed: {
count () {
return store.count
}
},
methods: {
setCount: mutations.setCount
}
}
</script>