Blazor和Vue对比学习(基础1.6):祖孙传值,联级和注入
前面章节,我们实现了父子组件之间的数据传递。大多数时候,我们以组件形式来构建页面的区块,会涉及到组件嵌套的问题,一层套一层。这种情况,很大概率需要将祖先的数据,传递给子孙后代去使用。我们当然可以使用父传子的方式,使用属性一级级往下传,但这样真得很麻烦。所以在Vue和Blazor都提供了祖孙传值的方案。
插个话题:有人会问,子传父是不是也可以一级级往上传?当然可以,但你绝不要这么去做。子传父就已经够绕了,不要为难自己。如果有这种需求,应该考虑数据状态从组件中剥离出来,我们将在进阶章节,一起学习“状态管理”。
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可以是字符串,也可以是一个Symbol
provide('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是在根组件提供数据,我们就可以传递全局数据了,而且这个数据的生命周期是实例范围的】
Blazor和Vue对比学习(基础1.6):祖孙传值,联级和注入的更多相关文章
- Blazor和Vue对比学习(基础1.9):表单输入绑定和验证,VeeValidate和EditFrom
这是基础部分的最后一章,内容比较简单,算是为基础部分来个HappyEnding.我们分三个部分来学习: 表单输入绑定 Vue的表单验证:VeeValidate Blazor的表单验证:EditForm ...
- Blazor和Vue对比学习(基础1.4):事件和子传父
Blazor和Vue的组件事件,都使用事件订阅者模式.相对于上一章的组件属性,需要多绕一个弯,无论Blazor还是Vue,都是入门的第一个难点.要突破这个难点,一是要熟悉事件订阅模式<其实不难& ...
- Blazor和Vue对比学习:说在开始前
1.Vue:现代前端三大框架之一(Vue/React/Angualr),基于HTML.CSS和JavaScript,2014年正式对外发布,目前已发展到3.X版本.值得说道的是,Vue的创始人作者是华 ...
- Blazor和Vue对比学习(进阶2.2.4):状态管理之持久化保存(2),Cookie/Session/jwt
注:本节涉及到前后端,这个系列的对比学习,还是专注在前端Vue和Blazor技术,所以就不撸码了,下面主要学习概念. 我们知道,Http是无状态协议,客户端请求服务端,认证一次后,如果再次请求,又要重 ...
- Blazor和Vue对比学习(基础1.8):Blazor中实现计算属性和数据监听
1.7章<传递UI片断>,需要做几个案例,这部分暂停消化几天.我们先把基础部分相对简单的最后两章学习了. 计算属性和数据监听是Vue当中的概念,本质上都是监听数据的变化,然后做出响应.两者 ...
- Blazor和Vue对比学习(基础1.2):模板语法和Razor语法
Vue使用模板语法,Blazor使用祖传的Razor语法,从逻辑和方向上看,两者极为相似,比如: 都基于HTML 都通过声明式地将组件实例的状态(数据/方法)绑定到呈现的DOM上 都通过指令实现更加丰 ...
- Blazor和Vue对比学习(基础1.3):属性和父子传值
组件除了要解决视图层展示.视图层与逻辑层的数据绑定,还需要解决一个重大问题,就是在组件树中实现数据传递,包括了父到子.子到父.祖到孙,以及任意组织之间.而我们上一章讲到的实现双向绑定的两个指令,Vue ...
- Blazor和Vue对比学习(基础1.5):双向绑定
这章我们来学习,现代前端框架中最精彩的一部分,双向绑定.除了掌握原生HTML标签的双向绑定使用,我们还要在一个自定义的组件上,手撸实现双向绑定.双向绑定,是前两章知识点的一个综合运用(父传子.子传父) ...
- Blazor和Vue对比学习(基础1.1):组件结构
难度:★ 简单说一说: 1.Vue和Blazor都遵循单文件结果,即HTML(视图模板).CSS(样式).JS/C#(代码逻辑)写在一个文件里,Vue的文件后缀为.vue,Blazor的文件后缀为.r ...
随机推荐
- java-等待唤醒机制(线程中的通信)-线程池
为什么需要线程间的通信 多个线程并发执行时,在默认情况下CPU时随机切换线程的,当我们需要多个线程共同完成一件任务,并且 希望他们有规律的执行,那么多线程之间需要一些协调通信,以此来帮我们达到多线程共 ...
- MyBatis Plus 2.3 个人笔记-01-代码生成器
sb_mybatis_puls2.3 <?xml version="1.0" encoding="UTF-8"?> <project xmln ...
- [译]HTML&CSS Lesson5: 定位
CSS最大的用处之一就是可以将内容和元素定位到任何我们想要的位置,使我们的设计具有结构,使内容更加易懂. CSS有好几种不同的定位属性,每种都有自己的使用场景.在这节课中我们会通过不同的案例--可复用 ...
- kbengine开源分布式游戏服务端引擎
一款开源的支持多人同时在线实时游戏的服务端引擎,使用简单的约定协议就能够使客户端与服务端进行交互,使用KBEngine插件能够快速与(Unity3D.OGRE.Cocos2d.HTML5,等等)技术结 ...
- 《JavaScript Dom编程艺术》读书笔记(二)
算术操作符 加减乘除这些算术操作中的每一种都必须借助于相应的操作符才能完成.操作符是JavaScript为完成各种操作而定义的一些符号.等号(=).加号(+).减号(-).乘号(*).除号(/). 下 ...
- SQL Server中如何让SQL语句对字符串大小写敏感
在SQL Server中默认对大小写是不敏感的,例如fname='peter'和fname='PETER'结果是一样的.但有时候用户会要求区分大小写,如验证密码等.这种情况下的处理办法就是在字段后加上 ...
- linux安装sbt
1.官网下载tgz sbt - Download (scala-sbt.org) 2.解压 tar zxvf sbt-0.13.5.tgz -C /opt/scala/ 3.建立启动sbt脚本 /*选 ...
- Android 遮罩层效果--制作圆形头像
(用别人的代码进行分析) 不知道在开发中有没有经常使用到这种效果,所谓的遮罩层就是给一张图片不是我们想要的形状,这个时候我们就可以使用遮罩效果把这个图片变成我们想要的形状,一般使用最多就是圆形的效果, ...
- jsp基础、el技术、jstl标签、javaEE的开发模式
一.jsp技术基础 1.jsp脚本和注释 jsp脚本: 1)<%java代码%> ----- 内部的java代码翻译到service方法的内部 2)<%=java变量或表达式> ...
- Python入门-内置对象函数
1.callable() 查看函数知否可调用,可调用返回True,不可用返回False print("input函数:", callable(input)) #input函数: T ...