组件学习:基本知识,选项式API&组合式API,组件通信 props,组件通信 $emit

main
roger_home_pc 1 year ago
parent d6823c8996
commit a96c6c2109
  1. 29
      demo/component-api/App.vue
  2. 42
      demo/component-api/components/ChildComponentA.vue
  3. 45
      demo/component-api/components/ChildComponentB.vue
  4. 36
      demo/component-api/components/ChildComponentC.vue
  5. 38
      demo/component-emit/App.vue
  6. 38
      demo/component-emit/components/ChildComponentA.vue
  7. 24
      demo/component-props/App.vue
  8. 33
      demo/component-props/components/ChildComponentA.vue
  9. 26
      src/App-org.vue
  10. 46
      src/App.vue
  11. 38
      src/components/ChildComponentA.vue
  12. 58
      src/components/HelloWorld.vue
  13. 8
      src/main-org.js
  14. 3
      vue.config.js

@ -0,0 +1,29 @@
<template>
<!-- 第三步使用 -->
<ChildComponentA :name="name1"></ChildComponentA>
<ChildComponentB :name="name2"></ChildComponentB>
<ChildComponentC :name="name3"></ChildComponentC>
</template>
<script>
// import
import ChildComponentA from "@/components/ChildComponentA.vue";
import ChildComponentB from "@/components/ChildComponentB.vue";
import ChildComponentC from "@/components/ChildComponentC.vue";
export default {
//
components: {ChildComponentA, ChildComponentB, ChildComponentC},
data() {
return {
name1: "组件A名称",
name2: "组件B名称",
name3: "组件C名称"
}
}
}
</script>
<style scoped>
</style>

@ -0,0 +1,42 @@
<template>
<div>{{ name }}: {{ counter }} {{ obj.title }}</div>
<div>{{ twiceTheCounter }}</div>
<button @click="action">点击</button>
</template>
<script>
export default {
props: {
name: String
},
data() {
return {
counter: 0,
obj: {title: "组件A标题"}
}
},
computed: {
twiceTheCounter() {
return this.counter * 2
}
},
watch: {
counter(newValue, oldValue) {
console.log(newValue, oldValue);
this.obj.title = "组件A标题---新"
}
},
methods: {
action() {
this.counter = this.counter + 3;
}
},
mounted() {
console.log('mounted')
}
}
</script>
<style scoped>
</style>

@ -0,0 +1,45 @@
<template>
<div>{{ name }}: {{ counter }} {{ obj.title }}</div>
<div>{{ twiceTheCounter }}</div>
<button @click="action">点击</button>
</template>
<script>
import {ref, reactive, onMounted, watch, computed} from "vue";
export default {
props: {
name: String,
},
setup() {
// data
const counter = ref(0);
const obj = reactive({title: "组件B标题"});
// computed
const twiceTheCounter = computed(() => counter.value * 2);
// watch
watch(counter, (newValue, oldValue) => {
console.log(newValue, oldValue);
obj.title = "组件B标题---新"
});
// methods
const action = () => {
counter.value = counter.value + 3;
};
// hook
onMounted(() => console.log("onMounted"));
return {
counter,
obj,
twiceTheCounter,
action
};
}
};
</script>
<style scoped>
</style>

@ -0,0 +1,36 @@
<template>
<div>{{ name }}: {{ counter }} {{ obj.title }}</div>
<div>{{ twiceTheCounter }}</div>
<button @click="action">点击</button>
</template>
<script setup>
import {ref, reactive, onMounted, watch, computed} from "vue";
// props
const props = defineProps({
name: String,
})
// data
const counter = ref(0);
const obj = reactive({title: "组件C标题"});
// computer
const twiceTheCounter = computed(() => counter.value * 2);
// watch
watch(counter, (newValue, oldValue) => {
console.log(newValue, oldValue);
obj.title = "组件C标题---新"
}
);
// methods
const action = () => {
counter.value = counter.value + 3;
}
// hook
onMounted(() => {
console.log("onMounted")
})
</script>
<style scoped>
</style>

@ -0,0 +1,38 @@
<template>
<!-- 3. 添加自定义事件selected -->
<ChildComponentA title="list—data" :list_data="todos" @selected="onSelected"></ChildComponentA>
<div>
<h3>您选中了{{ selected_status }}</h3>
</div>
</template>
<script>
import ChildComponentA from "@/components/ChildComponentA.vue";
export default {
components: {ChildComponentA},
data() {
return {
todos: [
'todo-1',
'todo-2',
'todo-3',
'todo-4',
'todo-5'
],
// 1.
selected_status: ''
}
},
methods: {
// 2. 使
onSelected(item) {
this.selected_status = item;
}
}
}
</script>
<style scoped>
</style>

@ -0,0 +1,38 @@
<template>
<h3>{{ title }}</h3>
<ul>
<!-- 触发事件 -->
<li v-for="(item, index) in list_data" :key="index" @click="handleClick(item)">{{ index }} - {{ item }}</li>
</ul>
</template>
<script>
export default {
props: {
title: String,
list_data: {
type: Array,
default: () => [],
required: true,
validator: value => {
return value.length >= 0
}
}
},
// 1.
emits: ['selected'],
methods: {
// 2. $emit, $emit()
handleClick(item) {
this.$emit("selected", item);
}
},
mounted() {
console.log(this.list_data)
}
}
</script>
<style scoped>
</style>

@ -0,0 +1,24 @@
<template>
<!-- 第三步使用 -->
<ChildComponentA :parent_param="param" :parent_param_full="param2"></ChildComponentA>
</template>
<script>
// import
import ChildComponentA from "@/components/ChildComponentA.vue";
export default {
//
components: {ChildComponentA},
data() {
return {
param: "这是父组件传递的参数1",
param2: "这是父组件传递的参数2"
}
}
}
</script>
<style scoped>
</style>

@ -0,0 +1,33 @@
<template>
<h1>{{parent_param}}</h1>
<h2>{{parent_param_full}}</h2>
<h3>这是子组件h3标签</h3>
</template>
<script>
export default {
name: "ChildComponentA",
//
// props: ['parent_param', ]
//
props: {
parent_param: String,
parent_param_full: {
type: String,
default: "子组件的默认值",
//
// default: function () {
// return { message: 'hello' }
// },
required: true,
validator: value => {
return value.length > 0
}
}
}
}
</script>
<style scoped>
</style>

@ -1,26 +0,0 @@
<template>
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

@ -1,44 +1,38 @@
<template>
<div>{{ name }}: {{ counter }} {{ obj.title }}</div>
<div>{{ twiceTheCounter }}</div>
<button @click="action">触发action方法</button>
<!-- 3. 添加自定义事件selected -->
<ChildComponentA title="list—data" :list_data="todos" @selected="onSelected"></ChildComponentA>
<div>
<h3>您选中了{{ selected_status }}</h3>
</div>
</template>
<script>
import ChildComponentA from "@/components/ChildComponentA.vue";
export default {
// name: "App",
props: {
name: String,
},
components: {ChildComponentA},
data() {
return {
counter: 0,
obj: {title: "标题"}
}
},
computed: {
twiceTheCounter() {
return this.counter * 2
}
},
watch: {
counter(newValue, oldValue) {
console.log(newValue, oldValue);
this.obj.title = "标题变了"
todos: [
'todo-1',
'todo-2',
'todo-3',
'todo-4',
'todo-5'
],
// 1.
selected_status: ''
}
},
methods: {
action() {
this.counter = this.counter + 3;
// 2. 使
onSelected(item) {
this.selected_status = item;
}
},
mounted() {
console.log('mounted')
}
}
</script>
<style scoped>
</style>

@ -0,0 +1,38 @@
<template>
<h3>{{ title }}</h3>
<ul>
<!-- 触发事件 -->
<li v-for="(item, index) in list_data" :key="index" @click="handleClick(item)">{{ index }} - {{ item }}</li>
</ul>
</template>
<script>
export default {
props: {
title: String,
list_data: {
type: Array,
default: () => [],
required: true,
validator: value => {
return value.length >= 0
}
}
},
// 1.
emits: ['selected'],
methods: {
// 2. $emit, $emit()
handleClick(item) {
this.$emit("selected", item);
}
},
mounted() {
console.log(this.list_data)
}
}
</script>
<style scoped>
</style>

@ -1,58 +0,0 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

@ -1,8 +0,0 @@
import {createApp} from 'vue'
import ElementPlus from 'element-plus' // 完整引入Element-Plus
import 'element-plus/dist/index.css' // 引入样式文件
import App from './App-org.vue'
const app = createApp(App)
app.use(ElementPlus, {size: 'small', zIndex: 3000})
app.mount('#app')

@ -1,4 +1,5 @@
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true
transpileDependencies: true,
lintOnSave: false
})

Loading…
Cancel
Save