npm install -g @vue/clivue --versionvue create project-demo
<template><div><h1>Parent</h1><p>Parent - Demo</p><p><button @click="parentNum++">ParentNum++</button>= {{ parentNum }}</p><child-com :parentNum="parentNum"></child-com></div></template><script>// 自定义组件// 1. 导入组件import ChildCom from '../components/ChildCom.vue'export default {name: 'Parent',data() {return {parentNum: 10,}},// 祖传孙 provide 提供(响应式)provide() {// 传递一个引用return {cParentNum: this.cParentNum,}},methods: {cParentNum() {return this.parentNum}},// 2. 注册组件components: {ChildCom,}}</script><style lang="scss" scoped></style>
<template><div><h1>Child Com</h1><p>ChildCom - Parent - Demo</p><p>ChildCom props receive father: parentNum = {{ parentNum }}</p><p><button @click="addChildNum()">childNum++</button>= {{ childNum }}</p><!-- 父接收子,通过子声明的自定义事件 --><grand-son :childNum="childNum" @grandSonChangeFather="grandSonChangeMe"></grand-son><!-- 默认插槽 --><!-- <slot-com>Slot value</slot-com> --><!-- 具名插槽,使用模板 --><!-- <slot-com><template v-slot:testSlot>TestSlot value</template></slot-com> --><!-- 具名插槽,接收子传参 --><slot-com><template v-slot:testSlot="{test1, test2}">TestSlot value, params: {{ test1 }} {{ test2 }}</template></slot-com></div></template><script>import GrandSon from './children/GrandSon.vue'import SlotCom from './children/SlotCom.vue'export default {name: 'ChildCom',data() {return {childNum: 100,}},props: ['parentNum'],// props: {// parentNum: {// type: Number,// default: 0// }// },components: {GrandSon, SlotCom},methods: {// 子变量自增addChildNum() {this.childNum++},// 子改变父的自定义事件grandSonChangeMe(n) {this.childNum += n}}}</script><style lang="scss" scoped></style>
<template><div><h1>Grand son</h1><p>GrandSon - ChildCom - Parent - Demo</p><p>GrandSon props receive father: childNum = {{ childNum }}</p><p>GrandSon inject receive grandfather: parentNum = {{ parentNum }}</p><!-- 子传父,通过自定义方法 --><p><button @click="emitGrandSonChangeFather(10)">changeFather childNum + 10</button>= {{ childNum }}</p></div></template><script>export default {name: 'GrandSon',// 父传子 props 接收props: ['childNum'],// props: {// childNum: {// type: Number,// default: 0,// }// },// 祖传孙 inject 注入inject: ['cParentNum'],// inject: {// parentNum: {// type: Number,// default: 0// }// },computed: {parentNum() {return this.cParentNum()}},methods: {emitGrandSonChangeFather(n) {this.$emit('grandSonChangeFather', n)}}}</script><style lang="scss" scoped></style>
<template><div><h1>Slot Com</h1><!-- 默认插槽 --><!-- <slot>Slot default</slot> --><!-- 具名插槽 --><!-- <slot name="testSlot">TestSlot default</slot> --><!-- 具名插槽,向父传数据 --><slot name="testSlot" test1="Hello" test2="vue">TestSlot default</slot></div></template><script>export default {name: 'SlotCom',}</script><style lang="scss" scoped></style>
<template><div><h1>Router</h1><p><router-link :to="router">Router</router-link></p><p><router-link :to="query">query</router-link></p><p>query: a = {{ paramA }}, b = {{ paramB }}</p><p><button @click="changeQuery(10, 20)">query</button></p><p>change a = 10, b = 20</p></div></template><script>export default {name: 'Router',data() {return {router: {name: 'Router',},query: {path: '/router',query: {a: 1,b: 2,}}}},computed: {paramA() {return this.$route.query.a},paramB() {return this.$route.query.b}},methods: {changeQuery(a, b) {this.$router.push({path: '/router',query: {a,b,}})}}}</script><style lang="scss" scoped></style>
<template><div><h1>State management</h1><p>store num: {{ num }}</p><p>commit mutations change state<button @click="commitNum(10)">state.num + 10</button></p><p>dispatch actions commit change mutations change state<button @click="dispatchNum(100)">state.num + 100</button></p><p>getters property: {{ sum }}</p></div></template><script>export default {name: 'State',computed: {num() {return this.$store.state.num},sum() {return this.$store.getters.sum}},methods: {commitNum(n) {this.$store.commit('num', n)},dispatchNum(n) {this.$store.dispatch('num', n)}}}</script><style lang="scss" scoped></style>
import {createRouter, createWebHistory} from 'vue-router'import Home from '../views/Home.vue'const routes = [{path: '/',name: 'Home',component: Home,meta: {title: 'Home - Demo'}},{path: '/about',name: 'About',// route level code-splitting// this generates a separate chunk (about.[hash].js) for this route// which is lazy-loaded when the route is visited.component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),meta: {title: 'About - Demo'}},// 父组件{path: '/parent',name: 'Parent',component: () => import('../views/Parent.vue'),meta: {title: 'Parent - Demo'},// 子组件children: [{path: 'child-com',name: 'ChildCom',component: () => import('../components/ChildCom.vue'),meta: {title: 'ChildCom - Parent - Demo'},// 孙组件children: [{path: 'grand-son',name: 'GrandSon',component: () => import('../components/children/GrandSon.vue'),meta: {title: 'GrandSon - ChildCom - Parent - Demo'}},{path: 'slot-com',name: 'SlotCom',component: () => import('../components/children/SlotCom.vue'),meta: {title: 'SlotCom - ChildCom - Parent - Demo'}},]}]},// 路由测试{path: '/router',name: 'Router',component: () => import('../views/Router.vue'),meta: {title: 'Router - Parent - Demo'}},// 状态管理测试{path: '/state',name: 'State',component: () => import('../views/State.vue'),meta: {title: 'State - Parent - Demo'}}]const router = createRouter({history: createWebHistory(process.env.BASE_URL),routes})// 前置导航守卫router.beforeEach((to, from) => {document.title = to.meta.title})export default router
<template><div id="nav"><router-link to="/">Home</router-link>|<router-link to="/about">About</router-link>|<router-link :to="{name: 'Parent'}">Parent</router-link>|<router-link :to="{name: 'Router'}">Router</router-link>|<router-link :to="{name: 'State'}">State</router-link></div><router-view/></template><style lang="scss">#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;}#nav {padding: 30px;a {font-weight: bold;color: #2c3e50;&.router-link-exact-active {color: #42b983;}}}</style>
import {createStore} from 'vuex'export default createStore({state: {num: 100,},mutations: {num(state, n) {state.num += n}},actions: {// 解构上下文 contextnum({state, commit, getters}, n) {commit('num', n)}},modules: {},// 计算属性getters: {sum(state, getter) {let sum = 0;for (let i = 1; i <= state.num; i++) sum += ireturn getter.str + sum;},str(state, getter) {return `1 + 2 + ... + ${state.num} = `;},}})
npm run serve
父子孙组件通信 - 插槽及传值

路由测试

状态管理和异步更新

<template><div><h1>Parent</h1><p>Parent - Demo</p><p><button @click="parentNum++">ParentNum++</button>= {{ parentNum }}</p><child-com :parentNum="parentNum"></child-com></div></template><script>// 自定义组件// 1. 导入组件import ChildCom from '../components/ChildCom.vue'import {ref, reactive, toRefs, provide} from 'vue'export default {name: 'Parent',// data() {// return {// parentNum: 10,// }// },// // 祖传孙 provide 提供(响应式)// provide() {// // 传递一个引用// return {// cParentNum: this.cParentNum,// }// },// methods: {// cParentNum() {// return this.parentNum// }// },// 2. 注册组件components: {ChildCom,},// 组合 apisetup() {// 响应式绑定const parentNum = ref(10)// 祖传孙 provide 提供(响应式)provide('parentNum', parentNum)// 使用的数据或方法返回return {parentNum,}}}</script><style lang="scss" scoped></style>
<template><div><h1>Child Com</h1><p>ChildCom - Parent - Demo</p><p>ChildCom props receive father: parentNum = {{ parentNum }}</p><p><button @click="addChildNum()">childNum++</button>= {{ childNum }}</p><!-- 父接收子,通过子声明的自定义事件 --><grand-son :childNum="childNum" @grandSonChangeFather="grandSonChangeMe"></grand-son><!-- 默认插槽 --><!-- <slot-com>Slot value</slot-com> --><!-- 具名插槽,使用模板 --><!-- <slot-com><template v-slot:testSlot>TestSlot value</template></slot-com> --><!-- 具名插槽,接收子传参 --><slot-com><template v-slot:testSlot="{test1, test2}">TestSlot value, params: {{ test1 }} {{ test2 }}</template></slot-com></div></template><script>import GrandSon from './children/GrandSon.vue'import SlotCom from './children/SlotCom.vue'import {ref, reactive, toRefs} from 'vue'export default {name: 'ChildCom',// data() {// return {// childNum: 100,// }// },props: ['parentNum'],// props: {// parentNum: {// type: Number,// default: 0// }// },components: {GrandSon, SlotCom},// methods: {// // 子改变父的自定义事件// grandSonChangeMe(n) {// this.childNum += n;// }// }// 组合 apisetup() {const data = reactive({childNum: 100,})// 子变量自增const addChildNum = () => data.childNum++// 子改变父的自定义事件const grandSonChangeMe = n => data.childNum += n// 使用的数据或方法返回return {...toRefs(data), addChildNum, grandSonChangeMe}}}</script><style lang="scss" scoped></style>
<template><div><h1>Grand son</h1><p>GrandSon - ChildCom - Parent - Demo</p><p>GrandSon props receive father: childNum = {{ childNum }}</p><p>GrandSon inject receive grandfather: parentNum = {{ parentNum }}</p><!-- 子传父,通过自定义方法 --><p><button @click="emitGrandSonChangeFather(10)">changeFather childNum + 10</button>= {{ childNum }}</p></div></template><script>import {ref, reactive, toRefs, inject} from 'vue'export default {name: 'GrandSon',// 父传子 props 接收props: ['childNum'],// props: {// childNum: {// type: Number,// default: 0,// }// },// 祖传孙 inject 注入// inject: ['cParentNum'],// inject: {// parentNum: {// type: Number,// default: 0// }// },// computed: {// parentNum() {// return this.cParentNum()// }// },// 组合 apisetup(props, {emit}) {let parentNum = inject('parentNum')const emitGrandSonChangeFather = n => emit('grandSonChangeFather', n)return {parentNum,emitGrandSonChangeFather}}}</script><style lang="scss" scoped></style>
<template><div><h1>Router</h1><p><router-link :to="router">Router</router-link></p><p><router-link :to="query">query</router-link></p><p>query: a = {{ paramA }}, b = {{ paramB }}</p><p><button @click="changeQuery(10, 20)">query</button></p><p>change a = 10, b = 20</p></div></template><script>import {useRoute, useRouter} from 'vue-router'import {ref, reactive, toRefs, computed} from 'vue'export default {name: 'Router',// data() {// return {// router: {// name: 'Router',// },// query: {// path: '/router',// query: {// a: 1,// b: 2,// }// }// }// },// computed: {// paramA() {// return this.$route.query.a// },// paramB() {// return this.$route.query.b// }// },// methods: {// changeQuery(a, b) {// this.$router.push({// path: '/router',// query: {// a,// b,// }// })// }// }setup() {const route = useRoute()const router = useRouter()const data = reactive({router: {name: 'Router',},query: {path: '/router',query: {a: 1,b: 2,}},})const paramA = computed(() => route.query.a),paramB = computed(() => route.query.b),changeQuery = (a, b) => router.push({path: '/router',query: {a,b,}})return {...toRefs(data),paramA,paramB,changeQuery,}}}</script><style lang="scss" scoped></style>
<template><div><h1>State management</h1><p>store num: {{ num }}</p><p>commit mutations change state<button @click="commitNum(10)">state.num + 10</button></p><p>dispatch actions commit change mutations change state<button @click="dispatchNum(100)">state.num + 100</button></p><p>getters property: {{ sum }}</p></div></template><script>// 状态管理import {useStore} from 'vuex'import {computed} from 'vue'export default {name: 'State',// computed: {// num() {// return this.$store.state.num// },// sum() {// return this.$store.getters.sum// }// },// methods: {// commitNum(n) {// this.$store.commit('num', n)// },// dispatchNum(n) {// this.$store.dispatch('num', n)// }// }setup() {const store = useStore()const num = computed(() => store.state.num),sum = computed(() => store.getters.sum),commitNum = n => store.commit('num', n),dispatchNum = n => store.dispatch('num', n)return {num,sum,commitNum,dispatchNum,}}}</script><style lang="scss" scoped></style>
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号