一次学俩Vue&Blazor:1.4基础-响应式数据

Posted functionMC

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一次学俩Vue&Blazor:1.4基础-响应式数据相关的知识,希望对你有一定的参考价值。

一、声明式编程和响应式数据


1、声明式编程

  • 逻辑层修改视图层元素属性值的方式有两种,一是命令式,先通过getElementById等方法获取元素对象,然后再修改对象的属性;二是声明式,先将视图层元素的属性值和逻辑层数据绑定,通过修改逻辑层数据,实现视图层元素属性值的自动更新。
  • 现代前端开发框架,都采用声明式。

2、响应式数据

  • 使用声明式编程的开发框架,需要通过特定的机制通知视图层更新。
  • Vue通过Proxy代理机制,劫持读取或修改数据的行为,进而通知使用到数据的UI节点进行更新,被Proxy代理的数据,就称之为响应式数据,在组合式API中,Vue提供了ref和reactive两个API来创建响应式数据。
  • 而Blazor中的字段或属性,不需要特殊处理,天然具有响应式特性,其内在机制,暂不清楚。.NET的另一个响应机制MVVM,则是通过事件机制,来通知UI层更新。


二、Vue定义响应式数据的方法


Vue提供reactive和ref两个API来创建响应式数据,只有响应式数据才具有通知更新功能。实际应用中,有几个点需要特别注意:

1、reactive只能用来创建对象类型(如对象、数组、Map、Set),不能创建原始类型(如string、number、boolean等)。而ref可以创建任何类型。

const a = reactive(name:\'MC\',age:18) //正确
const b = reactive(18) //错误
const a = ref(name:\'MC\',age:18) //正确
const b = ref(18) //正确

2、reactive创建的响应式对象,默认是深层次的,里面嵌套的数据都具有响应式。

const a = reactive()
a.people = name:\'MC\',age:18 //增加的people属性也是响应式

3、当使用ref时,值保存在ref对象的value属性上。如果是在逻辑层代码里读取或修改,需要通过访问value属性,如b.value+=2;如果在视图层模板中读取或修改,会自动解包,不需要.value

//视图层中,自动解包,不需要.value
//逻辑层中,需要通过.value来访问
<template>
  <h1>a.name</h1>
</template>

<script setup>
import ref from \'vue\'
const a = ref(name:”MC”,age:18)
a.value.name 
</script>

4、当使用ref创建对象类型时,会调用reactive来创建value属性,类似于这种感觉ref(reactive(value))。当整体替换value值时,新值仍然是响应式的,而reactive如果整体替换新值,则会失去响应性。

  • 在实际应用中,创建对象数组类型时,推荐使用ref,因为ref创建的对象,使用数组的map、filter、reduce等返回新数组的方法时,新数组仍然可以保持响应性。
  • 使用模块化开发时,export出来的数据,也应该使用ref,这样在引用这个API时,解构出来的数据仍然具有响应性。
  • 官方文档有一句话“为了解决reactive带来的限制,Vue 也提供了一个ref方法来允许我们创建可以使用任何值类型的响应式ref”。创建响应式数据时,除了对象类型,其它类型都请尽量使用ref,虽然.value麻烦点。
 //整体替换,a失去响应性
const a = reactive(name:”MC”,age:18)
a = reactivename:”Fun”,age:16

//ref可以实现响应式替换,b仍具有响应性
const b = ref(name:”MC”,age:18)
b.value = name:”Fun”,age:16 
 
//ref实现响应式解构
const obj1 = foo: ref(1),bar: ref(2)
const foo,bar = obj1 //响应式解构

//使用ref,即使使用filter等方法,b仍然还是响应式的
const b = ref([
  name:”MC1”,age:18,
  name:”MC2”,age:19,
  name:”MC3”,age:20])
b.value = b.value.filter((e)=>return e.age >18)

//上例换成reactive,b失去了响应性
const b = reactive([
  name:”MC1”,age:18,
  name:”MC2”,age:19,
  name:”MC3”,age:20])
b = b.filter((e)=>return e.age >18)

5、Vue的响应式原理

无论是选项式API的date()方法,还是组合式API的ref和reactive,都会将数据包装为Proxy对象。如果熟悉C#的属性,代理机制其实很简单。

//需要被代理的数据
const obj = 
  name:"functionMC",
  age:18


//当读取或修改数据时,指定代理的行为
//当读取数据时,调用get方法; 当修改数据时,调用set方法
//参数说明:target-被代理的对象、prop-读取的属性、receiver-代理对象、value-新值
const handler = 
  get(target,prop,receiver)
    
    //通过代理读取属性时,在返回值之前,它会做一个跟踪的操作,标记哪些地方用到了这个数据
    //track(),追踪谁用了这个属性......

    return target[prop]
  ,

  set(target,prop,value,receiver)
    target[prop] = value

    //通过代理修改值之后,做一些其它操作
    //trigger(),触发所有使用了该值的位置进行更新
  
;

//为数据obj,创建一个代理对象proxy
//之后对数据obj的读取和修改,都通过代理proxy来完成
const proxy = new Proxy(obj,handler)


三、Blazor中的响应式数据


Blazor中,字段和属性天然具有响应性,对象也是深层次绑定。利用属性的getter和setter方法,可以对响应式数据进行更复杂的控制。

@page "/"

<p>@Num</p>
<MButton @onclick="AddNum">增加</MButton>

<p>@employee.Name</p>
<MButton @onclick="ChangeName">更改名称</MButton>

<p>@employee.Address.City</p>
<MButton @onclick="ChangeCity">更改城市</MButton>

@foreach (var sport in sports)

    <p>@sport</p>

<MButton @onclick="AddSport">增加运动</MButton>

@code
    //值类型的属性绑定
    public int Num  get; set; 

    //对象类型的字段绑定(深层次响应)
    private Employee employee = new Employee  
        Id = 1, 
        Name = "functionMC", 
        Address = new Address  Province = "广东", City = "广州"  ;

    //集合类型对象的字段绑定
    private List<string> sports = new List<string>  "Running", "Swiming", "BasketBall" ;

    private void AddNum()
    
        Num++;
    

    private void ChangeName()
    
        employee.Name = "MC";
    

    private void ChangeCity()
    
        employee.Address.City = "深圳";
    

    private void AddSport()
    
        sports.Add("FootBall");
    


以上是关于一次学俩Vue&Blazor:1.4基础-响应式数据的主要内容,如果未能解决你的问题,请参考以下文章

6 大完整开源项目,一次学个够

一次学透C指针C进阶

研梦记一次学姐考研经验分享总结

Blazor VS React / Angular / Vue.js

Blazor VS Vue

Blazor 是不是有一些机制像 vue 中的 $attrs 一样工作?