项目代码地址:https://github.com/chenfenbgin/vue-component/tree/master
一、父子组件
1、父组件传递给子组件
两种方式: 数组 和 对象类型
注意:带有默认值的对象,对象或数组默认值必须从一个工厂函数中获取 ,因为如果有多次引用该组件,防止他指向的对象不变。(引用赋值的关系),这里需要不同的对象。
非props注意点:
1.继承 非props的属性
2.禁用 非props的属性
父组件:
<template>
<div id="app">
<show-message
class="chen"
id="idchen"
title="哈哈哈"
content="我是哈哈哈"
></show-message>
<show-message title="嘻嘻嘻" content="我是嘻嘻嘻"></show-message>
<show-message :title="title" :content="content"></show-message>
<show-message
:title="message.title"
:content="message.content"
></show-message>
<show-message v-bind="message"></show-message>
</div>
</template>
<script type="text/javascript">
import ShowMessage from "./ShowMessage.vue";
export default {
data() {
return {
title: "嘻嘻嘻",
content: "嘻嘻嘻",
message: {
title: "嘿嘿嘿",
content: "我是嘿嘿嘿",
},
};
},
components: {
ShowMessage,
},
};
</script>
<style scoped></style>
子组件:
<template>
<div>
<h2 :="$attrs">{{ title }}</h2>
<p>{{ content }}</p>
</div>
</template>
<script type="text/javascript">
export default {
name: "ShowMessage",
inheritAttrs: false,
props: {
title: String,
content: {
type: String,
required: true,
default: "2134",
},
message: [String, Number],
messageObject: {
type: Object,
default() {
return {
messageObject: "hello messageObject",
};
},
},
validatorFunction: {
validator(value) {
return ["success", "warning", "danger"].includes(value);
},
},
propG: {
type: Function,
default() {
return "Default function";
},
},
},
data() {
return {};
},
components: {},
};
</script>
<style scoped></style>
2、子组件传递给父组件
父组件:
<template>
<div id="app">
<h2>当前计数: {{ counter }}</h2>
<counter-operation
@add="increment"
@sub="decrement"
@addN="incrementN"
></counter-operation>
</div>
</template>
<script type="text/javascript">
import CounterOperation from "./CounterOperatin.vue";
export default {
name: "app",
data() {
return {
counter: 100,
};
},
components: {
CounterOperation,
},
methods: {
increment() {
this.counter++;
},
decrement() {
this.counter--;
},
incrementN(num, name, age) {
console.log(name, age);
this.counter += num;
},
},
};
</script>
<style scoped></style>
子组件:
<template>
<div id="app">
<button @click="increment">+1</button>
<button @click="decrement">-1</button>
<input type="text" v-model.number="num" />
<button @click="incrementN">+n</button>
</div>
</template>
<script type="text/javascript">
export default {
name: "CounterOperation",
emits: {
add: null,
sub: null,
addN: (num, name, age) => {
if (num > 10) {
return true;
}
console.log(num, name, age);
return false;
},
},
data() {
return {
num: 3,
};
},
components: {},
methods: {
increment() {
console.log("+1");
this.$emit("add");
},
decrement() {
console.log("-1");
this.$emit("sub");
},
incrementN() {
this.$emit("addN", this.num, "chen", 24);
},
},
};
</script>
<style scoped></style>
3、组件间通行案例 - 商品切换
父组件:
<template>
<div id="app">
<tab-control :titles="titles" @titleClick="titleClick"></tab-control>
<h2>{{ content[currentIndex] }}</h2>
</div>
</template>
<script type="text/javascript">
import TabControl from "./TabControl.vue";
export default {
name: "app",
data() {
return {
titles: ["衣服", "鞋子", "裤子"],
content: ["衣服页面", "鞋子页面", "裤子页面"],
currentIndex: 0,
};
},
components: {
TabControl,
},
methods: {
titleClick(index) {
console.log(index);
this.currentIndex = index;
},
},
};
</script>
<style scoped>
</style>
子组件:
<template>
<div class="tab-control">
<div
:class="{ active: currentIndex === index }"
class="tab-control-item"
v-for="(item, index) of titles"
:key="index"
@click="itemClick(index)"
>
<span> {{ item }} </span>
</div>
</div>
</template>
<script type="text/javascript">
export default {
name: "TabControl",
emits: ["titleClick"],
props: {
titles: {
type: Array,
default: () => {
return [];
},
},
},
data() {
return {
currentIndex: 0,
};
},
components: {},
methods: {
itemClick(index) {
this.currentIndex = index;
this.$emit("titleClick", index);
},
},
};
</script>
<style scoped>
.tab-control {
display: flex;
}
.tab-control-item {
flex: 1;
text-align: center;
}
.tab-control-item.active {
color: red;
}
.tab-control-item.active span {
border-bottom: 5px solid red;
padding: 5px 5px;
}
</style>
二、非父子组件
注:Vuex也是可以使用的(复杂数据使用)。provide和inject主要用在子孙组件
1、Provide 和 Inject
App.vue:
<template>
<div>
<home></home>
<button @click="addName">+name</button>
</div>
</template>
<script type="text/javascript">
import Home from "./Home.vue";
import { computed } from "vue";
export default {
name: "App",
provide() {
console.log(this);
return {
name: "chen",
age: 23,
length: computed(() => this.names.length),
};
},
data() {
return {
names: ["abc", "dfb", "dfdr"],
};
},
components: {
Home,
},
methods: {
addName() {
this.names.push("cen");
console.log(this.names);
},
},
};
</script>
<style scoped></style>
Home.vue :
<template>
<div>
<home-content></home-content>
</div>
</template>
<script type="text/javascript">
import HomeContent from "./HomeContent.vue";
export default {
name: "Home",
data() {
return {};
},
components: {
HomeContent,
},
};
</script>
<style scoped></style>
HomeContent.vue:
<template>
<div>HomeContent: {{ name }}-{{ age }} - {{ length.value }}</div>
</template>
<script type="text/javascript">
export default {
name: "HomeContent",
inject: ["name", "age", "length"],
data() {
return {};
},
components: {},
};
</script>
<style scoped></style>
2、事件总线
三、slot
注:我们希望父组件中访问子组件的data,需要使用作用域插槽。
四、动态组件
如果是简单的东西,就没有必要使用路由了呢, 应该使用动态组件。
五、组件保留状态、webpack代码分包、异步组件
注:一般配合router一起使用。
注:一般使用异步组件也是配合路由使用异步
开发中异步组件一般和suspens一起使用。 异步组件的使用是为了做代码分包。
六、引用元素和组件
七、生命周期
|