• vue2与vue3的使用区别与组件通信


    参考视频:https://www.bilibili.com/video/BV1484y1m7av/?spm_id_from=333.1007.tianma.16-1-59.click&vd_source=5c584bd3b474d579d0bbbffdf0437c70

    1. 脚手架创建项目的区别:

    • vue2: vue init webpack 项目名称
    • vue3: vue create 项目名称 或者vue3一般与vite结合使用:
    npm create vite@latest
    yarn create vite
    
    • 1
    • 2

    2. template中结构

    • vue2: template下只有一个元素节点
    <template>
    	<div>
    		<div></div>
    		<div></div>
    	</div>
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • vue3:template下可以有多个元素节点
    <template>
    	<div></div>
    	<div></div>
    	<div></div>
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3. main.js入口文件挂载App.vue文件

    • vue2:
    new Vue({
       app: '#app',
       router,
       ...
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • vue3:使用createApp
    import App from './App.vue'
    import router from '../src/router/index.js'
    
    createApp(App).use(router).mount('#app')
    // const app = createApp(App)
    // app.use(router) // 挂载路由
    // app.mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4. router的区别

    • vue2:
    在这里插入代码片
    
    • 1
    • vue3: 使用createRouter,使用createRouter必须要写history
    import { createRouter, createWebHistory } from 'vue-router'
    
    const router = createRouter({
        history: createWebHistory(),
        // history: createWebHistory(import.meta.env.BASE_URL),
        routes: [
            {
                path: '/',
                component: () => import('@/App.vue'),
            },
            {
                path: '/props_pre',
                component: () => import('@/components/props_test/PropsTest.vue'),
            },
        ]
    })
    
    export default router
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    5. setup的使用

    • vue2: 引入子组件需要使用compontents{}挂载
    import xx from '..子组件...'
    <script>
    	export default {
    		components: { xx }
    	}
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • vue3:
      引入子组件:
    <template>
    	<xx />
    </template>
    
    <script setup>
    	import xx from '..子组件...';  // 引入子组件不需要再compontents{}挂载,在template中直接使用即可
    	// 使用setup就不能使用export default{}导出了
    </script>
    
    如果需要使用export default则:
    <script>
    	export default {
    	  setup() {
    	    ...
    	  },
    	}
    </script>        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    6. props的使用

    • vue2
    子组件中:
    	export default{
    		props: {
    			xx: {
    				type: String/Number/Object/Array,
    				default: ''/0/()=>{}/()=()=>{}
    			}
    		},
    		// props:['xx1', 'xx2']
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • vue3: 如果报错 ‘defineProps’ is not defined则在package.json文件eslintConfig{env: {‘vue/setup-compiler-macros’: true }}中添加’vue/setup-compiler-macros’: true
    defineProps(['xx1', 'xx2'])不需要引入直接使用,返回一个对象,数组或者对象写法都可
    	子组件中使用   let  props = defineProps(['xx1', 'xx2']), // 在template中props可以省略{{props.xx1}} => {{xx1}},props名字可以随便取
    
    <template>
    	<span>{{props.name}}</span> // 可以省略props,直接使用name {{name}}
    </template>
    <script setup>
    	let props = defineProps(['name', 'age']);
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    7. ref的使用

    • vue2:
    <template>
    	<Child ref="child1" />
    </template>
    // 使用
    <script>
    	export default {
    		mouted() {
    			console.log(this.$refs.child1); // 获取child1的ref有关数据
    		}
    	}
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • vue3: 需要先从vue中引入 ref, vue3中不可使用this
    <template>
    	<Child :money = money /> // 子组件也是用defineProps(['money'])接收
    </template>
    
    <script setup>
    	import { ref } from 'vue'
    	let money = ref(10000)
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    8. 自定义事件

    下面这个Event1组件上的@click:

    • 在vue2框架当中,这种写法是自定义事件,可以通过.native修饰符变为原生DOM事件
    • 在vue3框架当中,这种写法就是原生DOM事件,绑定自定义事件为
    <template>
    	<Event1 @click="" />
    </template>
    
    • 1
    • 2
    • 3

    自定义事件父子组件传值:

    • vue2中子组件用this.$emit(‘updateList’, 参数1, 参数2)调用
    • vue3使用setup组合式APIZ没有实例不能用this.$emit,vue3中使用defineEmits方法返回函数触发自定义事件
    <script setup>
    	// 利用defineEmits方法返回函数触发自定义事件
    	// defineEmits方法不需要引入直接使用
    	let $emit = defineEmits(['updateList']);
    	const handleUpdateList = () => {
    		$emit('updateList', 参数1, 参数2);
    	}
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    注意:

    <template>
    	<Event2 @updateList="handle1" @click="handle2" />
    </template>
    
    <script setup>
    	const handle1 = (参数1, 参数2) => {
    		...
    	}
    
    	// click原生dom事件,点击就会执行
    	const handle2 = (参数1, 参数2) => { // 子组件调用了父组件的click类型的方法,需要接收参数, 没调用传参时不用接收参数
    		// alert(123) // 这是之前DOM事件时,点击就会执行
    		...
    	}
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Event2子组件中

    <template>
    	<button @click="$emit('click', 参数1, 参数2)">子组件调用父组件click自定义事件</button>
    <template>
    
    <script setup>
    	let $emit = defineEmits(['updateList']); // 此时在父组件点击子组件会执行alert(123)
    	let $emit = defineEmits(['updateList', 'click']); // 此时在父组件点击子组件不会执行alert(123),这里把click类型的DOM事件变成了自定义事件
    	...
    	$emit('updateList', 参数1, 参数2)
    <script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    9. 组件通信方式之全局事件总线

    • vue2:兄弟组件通信 b u s ( bus( bus(on, $emit)
    • vue3:没有实例,没有this,所以不能使用$bus,使用插件mitt
    1.安装mitt
    npm i --save mitt
    2.新建bus/index.js文件
    mitt是一个方法(),方法执行会返回bus对象
    import mitt from 'mitt'; // 引入mitt插件
    const $bus = mitt(); // 名字随意取
    export default $bus;
    3.使用
    在父组件中使用两个子组件
    eventBus.vue中
    <template>
        <div class="box">
            <h1>全局事件总线$bus</h1>
            <div class="dis-flex">
                <ChildBus1 />
                <ChildBus2 />
            </div>
        </div>
    </template>
    
    <script setup>
    import ChildBus1 from "./ChildBus1.vue";
    import ChildBus2 from "./ChildBus2.vue";
    </script>
    
    
    
    在ChildBus1子组件中监听接收
    <template>
        <div class="child1">
            <h3>我是子组件1: 曹植</h3>
        </div>
    </template>
    
    <script setup>
    import $bus from '../../bus/index.ts';
    // 组合式API函数
    import { onMounted } from "vue";
    // 当组件挂载完毕时,当前组件绑定一个事件,接收将来兄弟组件传递的数据
    onMounted(() => {
        // 第一个参数:即为事件类型,第二个参数:即为事件回调
        $bus.on('car', (car) => {
            console.log(car, '在回调函数内可以做这个组件相应的操作');
        })
    })
    </script>
    
    
    
    在ChildBus2子组件中发送
    <template>
        <div class="child2">
            <h2>我是子组件2:曹丕</h2>
            <button @click="handleClick">点击我给我的兄弟送火箭</button>
        </div>
    </template>
    
    <script setup>
        // 引入$bus对象
        import $bus from '../../bus/index.ts'; 
        // 点击按钮回调
        const handleClick = () => {
            $bus.emit('car', {car: '火箭'});
        }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    10. 组件通信方式之v-model

    • vue2:
    • vue3: 使用v-model, v-model不仅可以用来收集表单数据,实现数据双向绑定还可以用来父子组件之间通信
    <template>
    	<input type="text" v-model="name" />
    </template>
    
    <script setup>
    // v-model指令:收集表单数据,数据双向绑定
    // v-model也可以实现组件之间的通信,实现父子组件数据同步的业务
    import { ref } from 'vue';
    let name = ref('');
    </script>
    
    在vue的3.3版本中新加了defineModel,但是跟ref一样需要引入
    import { defineModel } from 'vue';
    let xx = defineModel();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    v-model组件身上使用

    <Child :modelValue="money" @update:moneyModel="handleMoney" /> 等价与
    /**
    	v-model组件身上使用
    	第一:相当于给子组件传递props['modelValue'], 名字一定要叫modelValue
    	第二:相当于给子组件绑定自定义事件update:modelValue
    */
    <Child v-model="money" />
    // 如果是v-model:money="money"这样的话,子组件传递props['money'], 名字不一定要叫modelValue了
    <Child v-model:money="money" /> // 跟多个v-model一样的,然后这样的不用再绑定自定义事件,$emit那边就能更改
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    父组件

    <template>
        <!-- <ChildModel1 :modelValue="money" @update:modelValue="handleUpdate" /> -->
        <ChildModel1 v-model="money" /> // 这句就相当于上面那行代码,用了这行代码可能会有报错,handleUpdate声明了却没使用,页面上叉掉报错是能正常增加的
    </template>
    
    <script setup>
    
    import ChildModel1 from './ChildModel1.vue';
    let money = ref(100);
    
    const handleUpdate = (num) => {
        money.value = num;
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    子组件

    <template>
        <div>父组件的钱:{{modelValue}}</div>
        <button @click="handleClick">点击更改父组件钱</button>
    </template>
    
    <script setup>
    const props = defineProps(['modelValue']);
    const $emit = defineEmits(['update:modelValue']);
    const handleClick = () => {
        $emit('update:modelValue', props.modelValue + 1);
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    设置多个v-model

    <template>
    	<Child v-model:pageNo="pageNo" v-model:pageSize="pageSize" />
    </template>
    
    <script setup>
    	import { ref } from 'vue';
    	let pageNo = ref(1);
    	let pageSize = ref(10);
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    11. 组件通信方式之useAttrs方法

    vue3框架提供一个方法useAttrs方法,它可以获取组件身上的属性与事件

    • 父组件中调用子组件并传参:
    <template>
    	<HintButton type="primy" :size="small" :icon="edit" />
    </template>
    
    <script setup>
    	import HintButton from './HintButton.vue';
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 在HintButton子组件中:
    <template>
    	// 使用$attrs
    	<el-button :type="$attrs.type"></el-button>
    	// 还可以使用语法
    	<el-button :="$attrs"></el-button> // 这种写法相当于

    => 可以简写为

    </template> <script setup> // 1.这样可以获取子组件上的参数 let props = defineProps(['type', 'size', 'icon']); // 2.引入useAttrs方法:获取组件标签身上的属性与事件, 此方法执行会返回一个对象 import { useAttrs } from 'vue'; let $attrs = useAttrs(); </script>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    注意:使用defineProps接收过的参数,useAttrs()就接收不到了,defineProps(['xxx'])的优先级更高,useAttrs方法不仅能接收到父组件传过来的参数,还能接收事件(DOM原生click事件和自定义事件),比如

    12. 组件通信方式之ref与$parent

    ref: 可以获取真实的DOM节点,可以获取到子组件实例VC
    $parent:可以在子组件内部获取到父组件的实例
    获取子组件的实例,ref需要与组件名称同名: 比如

    <Son ref="son" /> // ref的名称需要与ref获取的名字一样 比如 下面获取时需要名字相同 let account = ref();
    
    import { ref } from 'vue';
    import Son from "./refSon.vue";
    let son = ref();
    console.log(son.value);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这样能拿到子组件实例,但拿不到子组件内部的数据,因为:
    组件内部数据对外关闭的,别人不能访问,如果想让外部访问需要通过defineExpose方法对外暴露,这个方法不仅能暴露属性还能暴露方法
    $parent,子组件必须使用这个名称可以拿到父组件的实例,父组件的属性也需要暴露出去

    • 父组件代码
    <template>
        <div class="box">
            父组件的钱:{{money}}
            <button @click="handler">父组件加10</button>
            <Son ref="son" />
            <Daughter />
        </div>
    </template>
    
    <script setup>
    import Son from "./refSon.vue";
    import Daughter from "./refDaughter.vue";
    import { ref } from "vue";
    let money = ref(10000);
    let son = ref();
    const handler = () => {
        money.value += 10;
        // 儿子减10
        son.value.money -= 10;
        son.value.flyFun();
    }
    defineExpose({
        money // 暴露出去给daughter.vue组件使用
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • son组件代码:
    <template>
        <div class="son">儿子组件钱:{{money}}</div>
    </template>
    
    <script setup>
    import { ref } from "vue";
    let money = ref(666);
    
    // 组件内部数据对外关闭的,别人不能访问
    // 如果想让外部访问需要通过defineExpose方法对外暴露,这个方法不仅能暴露属性还能暴露方法
    const flyFun = () => {
        console.log('想飞咯');
    }
    defineExpose({
        money,
        flyFun
    })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • daughter组件代码
    <template>
        <div>女孩的钱:{{money}}
            <button @click="handler($parent)">点击+100</button> // 把父组件$parent实例作为参数传入函数中
        </div>
    </template>
    
    <script setup>
    import { ref } from "vue";
    let money = ref(999);
    const handler = ($parent) => {
        money.value += 100;
        $parent.money -= 100;
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    13.组件通信方式之Provide与Inject

    vue3提供provide(提供)与inject(注入),可以实现隔辈组件传递数据
    在爷爷组件使用provide(传递),在孙子组件inject(获取);

    • 爷爷组件:
    <template>
        <div class="box">provide: {{car}}
            <ChildPage />
        </div>
    </template>
    
    <script setup>
    import ChildPage from "./childPage.vue";
    import { ref, provide } from "vue";
    let car = ref('豪车');
    // vue3提供provide(提供)与infect(注入),可以实现隔辈组件传递数据
    // 祖先组件给后代组件提供数据
    // 两个参数:第一个参数就是提供的数据key
    // 第二个参数:祖先组件提供数据
    provide('TOKEN', car)
    </script>
    
    <style scoped>
    .box {
        height: 500px;
        background: skyblue;
    }
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 父亲组件ChildPage.vue:中间组件:只需要导入孙子组件就行了
    <template>
        <div class="child">子组件
            <GrandChildPage />
        </div>
    </template>
    
    <script setup>
    import GrandChildPage from "./grandChildPage.vue";
    </script>
    
    <style scoped>
    .child {
        height: 300px;
        background: pink;
    }
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 孙子组件GrandChildPage.vue中使用inject()来获取,如果需要更改爷爷组件传递过来的属性值,直接修改 xx.value = ‘’即可。
    <template>
        <div class="box">孙子组件:{{car}}
            <button @click="updateCar">更新数据</button>
        </div>
    </template>
    
    <script setup>
    import { inject } from "vue";
    // 注入祖先组件提供数据
    // 需要参数:即为祖先提供数据的key
    let car = inject('TOKEN');
    console.log(car);
    
    const updateCar = () => {
        car.value = '自行车'; // 更改爷爷组件的car属性值
    }
    </script>
    
    
    <style scoped>
    .box {
        height: 100px;
        background: salmon;
    }
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    13.组件通信之pinia组合式API

    使用pinia需要先安装piaia: npm i pinia -D;
    在src目录下新建store目录,创建index.js文件作为大仓库,需要在main.js入口文件中引入index.js文件并用使用use挂载

    /**

    • vuex:集中式管理状态容器,可以实现任意组件之间的通信
    • 核心概念:state, mutations, actions, getters, modules
      */

    /**

    1. pinia:集中式管理状态容器,可以实现任意组件之间通信
    2. 核心概念:state, actions, getters
    3. pinia写法:选择器API,组合式API
      */
    4. 选择器API
    main.js入口文件...........
    import { createApp } from 'vue'
    import App from './App.vue'
    import router from '../src/router/index.js'
    import store from "./store/index.ts";
    createApp(App).use(router).use(store).mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在store目录下创建modules目录用来装小仓库:
    src
    ----store文件夹
    -------modules文件夹用来存放小仓库
    ---------------info.js小仓库使用defineStore:import { defineStore } from “pinia”;
    -------index.js文件用来存放大仓库, 大仓库使用createPinia:import { createPinia } from “pinia”;

    修改store数据:

    • 直接修改
    import useInfoStore from '../store/modules/info.js'; 
    let info = useInfoStore();
    info.count ++ ; // 会改变store.count的值
    
    • 1
    • 2
    • 3
    • 使用$patch修改
    infoStore.$patch({
        count: 1111
     })
    
    • 1
    • 2
    • 3
    • 直接调用仓库内的方法来修改值,可以传参
    infoStore.updateNum();
    infoStore.updateNum(66);
    
    • 1
    • 2
    • 在info小仓库内:
    // 创建小仓库
    import { defineStore } from "pinia";
    
    // 第一个参数: 小仓库名字, 第二个参数:小仓库配置对象
    // defineStore方法会返回一个函数,函数作用就是让组件可以获取到仓库数据
    let useInfoStore = defineStore('info', {
        // 存储数据: state
        state: () => {
            return {
                count: 99,
                arr: [1,2,3,4,5,6,7,8,9]
            }
        },
        actions: {
            // 注意:函数没有context上下文对象,但是有this,this指向的是这个小仓库
            updateNum() {
                this.count++;
            }
        },
        getters: {
            total() { // 有点像computer,需要return返回值
                let result = this.arr.reduce((pre, next) => {
                    return pre + next;
                }, 0)
                return result;
            }
        }
    });
    
    // 对外暴露方法
    export default useInfoStore;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 在组件中使用info小仓库
    <template>
        <div class="child1">
            子组件1: {{infoStore.count}}------{{infoStore.total}}
            <button @click="updateCount">点击我,修改store数据</button>
        </div>
    </template>
    
    <script setup>
    import useInfoStore from "../../store/modules/info.ts";
    // 获取小仓库对象
    let infoStore = useInfoStore();
    const updateCount = () => {
        // infoStore.count ++; // 这样是可以修改的
        // infoStore.$patch({
        //     count: 1111
        // }) // 这个方法也是可以修改的
        // 仓库调用自身的方法去修改仓库数据
        infoStore.updateNum();
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    1. 组合式API
      todo.js代码
    // 定义组合式API仓库
    import { defineStore } from "pinia";
    import { ref, computed } from "vue";
    
    // 创建小仓库
    let useTodoStore = defineStore('todo', () => {
        let todos = ref([
            {
                id: 1,
                title: '吃饭'
            },
            {
                id: 2,
                title: '睡觉'
            }
        ]);
        // let arr = [1,2, 3, 4, 5];
        let arr = ref([1, 2, 3, 4, 5]);
    
        const total = computed(() => {
            return arr.value.reduce((pre, next) => pre + next, 0);
        })
        // 务必要返回一个对象:属性与方法可以提供给组件使用
        return {
            todos,
            arr,
            total,
            updateTodo(){
                todos.value.push({
                    id: 3,
                    title: '打豆豆'
                })
            }
        }
    });
    
    export default useTodoStore;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    在组件中使用:

    <template>
    <p @click="updateTodo">{{todoStore.todos}}------{{todoStore.total}}</p>
    </template>
    
    <script setup>
    import useTodoStore from "../../store/modules/todo.js";
    let todoStore = useTodoStore();
    // 点击p段落去修改仓库的数据
    const updateTodo = () => {
        todoStore.updateTodo();
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    14. 组件通信方式之插槽

    默认插槽,具名插槽,作用域插槽

    • 默认插槽:传递组件
      内容
      ,接收组件
    父组件内:
    <template>
    <Child>
    	<div>
    		<pre>想要在子组件slot插槽展现的内容</pre>
    	</div>
    </Child>
    </template>
    
    <script setup>
    import Child from './Child.vue';
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    子组件内:
    <template>
    	<slot></slot>
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 具名插槽:传递组件使用或者