Blazor和Vue对比学习(基础1.6):祖孙传值,联级和注入

博客 分享
0 184
张三
张三 2022-05-11 21:59:07
悬赏:0 积分 收藏

Blazor和Vue对比学习(基础1.6):祖孙传值,联级和注入

前面章节,我们实现了父子组件之间的数据传递。大多数时候,我们以组件形式来构建页面的区块,会涉及到组件嵌套的问题,一层套一层。这种情况,很大概率需要将祖先的数据,传递给子孙后代去使用。我们当然可以使用父传子的方式,使用属性一级级往下传,但这样真得很麻烦。所以在VueBlazor都提供了祖孙传值的方案。

插个话题:有人会问,子传父是不是也可以一级级往上传?当然可以,但你绝不要这么去做。子传父就已经够绕了,不要为难自己。如果有这种需求,应该考虑数据状态从组件中剥离出来,我们将在进阶章节,一起学习“状态管理”。

Vue中使用provide/inject这两个API来实现祖孙传值(这个概念被翻译为依赖注入,为免混淆,建议叫注入为好),Blazor则使用CascadingValue组件和[CascadingParameter] 特性来实现。Vue的实现方式,统一在逻辑层,更加简明统一,而且灵活。反观Blazor,穿插于视图层和逻辑层,比较混乱,也不灵活。下面我们通过以下两个部分来学习:

  • 传递单个值和多个值
  • 如何修改传递数据

 

 

一、传递单个值和多个值

Vue和Blazor,都可以传递任意值以及多个值

//Vue====================================================================//祖先组件Grandparent。通过provide提供数据,可以是任何值、任何响应式数据、任何方法<template>  <div class="grandparent">    <h1>这是是祖组件</h1>    <Parent>      //Parent组件里嵌套着<Child></Child>,祖传孙的任务就是将值传给Child    </Parent>  </div></template> <script setup>import Parent from './components/Parent.vue'import Child from './components/Child.vue'import {ref,provide} from 'vue'//以键值对的方式提供单个值,其中键key可以是字符串,也可以是一个Symbolprovide('name','functionMC')//如果要传递多个值,多次provide就可以const address = ref('GuangZhou')provide('age',18)//提供一个响应式数据provide('address',address)//一个key,对应多个响应式数据const likeCode = ref(['C#','JS'])const likeFruit = ref(['apple','bananer'])provide('like',{likeCode,likeFruit})</script> //子孙组件Child。任何需要数据的子孙组件,都可以inject注入数据,Parent组件一样也可以注入。<template>  <div class="child">    <h1>红色是孙组件</h1>    <h4>姓名:{{name}}</h4>    <h4>年龄:{{age}}</h4>    <h4>地址:{{address}}</h4>    <h4>喜欢代码:</h4>    <ul><li v-for = "item in likeCodes">{{item}}</li></ul>    <h4>喜欢水果:</h4>    <ul><li v-for = "item in likeFruits">{{item}}</li></ul>    <h4>老祖说:{{grandparentSay}}</h4>  </div></template><script setup>import { inject } from 'vue'//直接通过键来注入const name = inject('name')const age = inject('age')const address = inject('address')//接受一个键里的多个值const {likeCodes,likeFruits } = inject('like')//注入时可以设置默认值,如果找不到键,则使用默认值const grandparentSay = inject('grandparentSay','还没有说')</script>
//Blazor===================================================================================//祖组件grandparent。//在模板中使用<CascadingValue>组件传值。比较麻烦,传递多值时要不断的嵌套,组件放在最内层。//推荐以Name-Value键值对的形式来传递,传递的数据,可以是值,也可以是属性,可以是任何类型。//CascadingValue也可以缺省Name的方式传值,接收时,需要使用类型来匹配,自行查文档,不推荐<div class = "grandparent">    <h1>灰色是祖组件</h1>    <CascadingValue Name="name" Value="@("functionMC")">        <CascadingValue Name="age" Value="@age">            <CascadingValue Name="likeFruits" Value="@likeFruits">                <Parent>                      //Parent父组件中嵌套着孙组件<Child></Child>                </Parent>            </CascadingValue>        </CascadingValue>    </CascadingValue></div>@code {    private int age = 18;    private string[] likeFruits = new string[] { "apple", "bananer" };}//子组件<div class="Child">    <h1>红色是孙组件</h1>    <h5>姓名:@Name</h5>    <h5>年龄:@Age</h5>    <h5>喜欢的水果:</h5>    <ul>        @foreach (var item in LikeFruits)        {            <li>@item</li>        }    </ul></div>@code {    //CascadingParameter特性的Name参数,就是键    //可以设置默认值,当找不到键时,使用默认值    //强类型,提供和接收的数据类型要一致    [CascadingParameter(Name = "name")]    private string Name { get; set; } = "MC";    [CascadingParameter(Name = "age")]    private int? Age { get; set; }    [CascadingParameter(Name = "likeFruits")]    private string[]? LikeFruits { get; set; }}

 

 

 

二、如何修改传递数据

虽然Vue和Blazor都实现了祖传孙,也都表现为类似键值对的特征。但两者有一个非常大的区别:

1、Vue中,如果传递的是响应式数据【值例外】,在子孙中修改的话,祖先的数据会同步更新。provide和inject的数据,是引用同一个数据。所以,如果修改传值数据的话,都应将逻辑放在provide数据的地方,即祖组件,然后将数据和修改逻辑一起provide出去,如果孙组件需要修改数据,则通过调用inject过来的方法来完成。

2、而在Blazor中,我们是这么接收数据的【[CascadingParameter(Name = "name")] private string Name { get; set; }】,可以看出,重新定义了一个属性来接收值。所以,在子孙中修改的话,祖先的数据不会同步更新,因为它们是不同的两个变量,这和通过属性进行父传子的表现类似。如果要修改数据,就只能在祖组件中修改了,子孙数据会同步更新

3、Vue的数据修改会灵活一些,但这种灵活要特别注意控制,而Blazor的设计更加严谨合理。如果Blazor也能像Vue一样,直接在逻辑层提供联级值,那这票我一定投Blazor

下面仅提供在Vue中修改数据的推荐方法:

//Vue//祖先组件Grandparent。<template>  <div class="grandparent">    <h1>灰色是祖组件</h1>    <h1>{{look}}</h1>    <Parent></Parent>  </div></template><script setup>import Parent from './components/Parent.vue'import Child from './components/Child.vue'import {ref,provide} from 'vue'//一个键,提供一个响应式数据和相应的方法const look = ref({height:170,weight:130})function changeLook(){ look.value.height = 175 }provide('look',{look,changeLook})</script>//子孙组件Child。<template>  <div class="child">    <h1>红色是孙组件</h1>    <h4>样貌:{{look}}</h4>  </div>  <button @click="changeLook()">修改样貌</button>  //直接在子组件中调用祖先提供的方法</template> <script setup>import { inject } from 'vue';//通过解构方法,注入响应式数据及其方法const {look,changeLook} = inject('look')</script>

 

  

【最后补充一个小技巧:如果provide/CascadingValue是在根组件提供数据,我们就可以传递全局数据了,而且这个数据的生命周期是实例范围的】

posted @ 2022-05-11 21:23 functionMC 阅读(0) 评论(0) 编辑 收藏 举报
回帖
    张三

    张三 (王者 段位)

    821 积分 (2)粉丝 (41)源码

     

    温馨提示

    亦奇源码

    最新会员