Использование и различие ref, reactive, toRef и toRefs в vue3, взрыв идей, различия в использовании, существенные различия, отзывчивость, pit, elementPlus, select


ссылка

обзор

Генерация чувствительных данных типа значения Лучше
использовать .valueизменение значения
для создания реагирующих объектов типа объекта и массива.reactive


HTML

<template>
	<div>
		<div>countRef: {
   
   { countRef }}</div>
		<div>objCountRef: {
   
   { objCountRef.count }}</div>
		<div>爱好: {
   
   { hobbyRef.join('---') }}</div>
	</div>
</template>

JavaScript

import {
    
     ref } from 'vue';

export default {
    
    
	name: 'refDemo',
	setup () {
    
    
		// 值类型
		const countRef = ref(1);
		console.log(countRef);
		
		// 对象
		const objCountRef = ref({
    
     count: 1 });
		
		// 数组
		const hobbyRef = ref(['爬山', '游泳']);
		
		setTimeout(() => {
    
    
			// 通过value改变值
			countRef.value = 2;
			objCountRef.value.count = 3;
			hobbyRef.value.push('吃饭');
		}, 3000);
		
		return {
    
    
			countRef,
			objCountRef,
			hobbyRef
		};
	}
}

реактивный

обзор

reactiveМетод создает и возвращает глубоко реагирующий объект на основе входящего объекта. Реактивные объекты выглядят так же, как переданные объекты. Однако изменение значения свойства адаптивного объекта, независимо от того, насколько глубока иерархия, активирует адаптивный стиль, а добавление и удаление свойств также активирует адаптивный стиль.
1. Изменить nameатрибуты
2. Глубоко изменить addressатрибуты
3. Добавить schoolатрибуты
4. Удалить ageатрибуты


HTML

<template>
	<div class="demo">
		<div>姓名: {
   
   { state.name }}</div>
		<div v-if="state.age > 0">年龄: {
   
   { state.age }}</div>
		<div>地址: {
   
   { state.address.provoince }} - {
   
   { state.address.city }} - {
   
   { state.address.street }}</div>
	</div>
	
	<div class="demo">
		<div>学校: {
   
   { state.school || '自学成才' }}</div>
	</div>
</template>

JavaScript

import {
    
     reactive } from 'vue';

export default {
    
    
	name: 'reactiveDemo',
	setup () {
    
    
		// 响应式对象
		const state = reactive({
    
    
			name: '太凉',
			age: 18,
			hobby: ['游泳', '爬山'],
			address: {
    
    
				provoince: '北京',
				city: '北京',
				street: '东城区长安街'
			}
		});
		
		// 过3秒后改变
		setTimeout(() => {
    
    
			// update1: 改变name属性
			state.name = '冰箱太凉';
			state.age = 25;
			// update2: 深度改变
			state.address.provoince = '山东省';
			// address属性
			state.address.city = '临沂市';
			// update3: 新增school属性
			state.school = '清华北大';
			// update4: 删除年龄属性
			delete state.age;
			// update5: 数组添加一项
			state.hobby.push('打豆豆');
		}, 3000);
		
		return {
    
    
			// 注意这里不能通过...state方式结构,
			// 这样会丢失响应式
			state  
		};
	}
}

стиль

.demo {
    
    
	text-align: left;
	width: 600px;
	margin: 20px auto;
}

toRef

обзор

1. Создайте один для (свойства) reactiveотзывчивого объекта (инкапсуляция) и сохраните отзывчивый 2. Эти два поддерживают ссылочное отношениеpropref


HTML

<template>
	<div class="demo">
		<div>姓名--state.name: {
   
   { state.name }}</div>
		<div>姓名2--nameRef: {
   
   { nameRef }}</div>
		<div>年龄: {
   
   { state.age }}</div>
	</div>
</template>

JavaScript

import {
    
     reactive, toRef } from 'vue';

export default {
    
    
	name: 'toRefDemo',
	setup () {
    
    
		// 响应式对象
		const state = reactive({
    
    
			name: '太凉',
			age: 18
		});
		
		// 通过toRef创建一个Ref响应式
		const nameRef = toRef(state, 'name');
		
		// 过3秒后改变 两者 保持引用关系 
		setTimeout(() => {
    
    
			// update1: 改变name属性
			state.name = '冰箱太凉';
		}, 3000);
			
		// 过6秒后改变两者保持引用关系 
		setTimeout(() => {
    
    
			// update1: 改变name属性
			nameRef.value = '我就是冰箱太凉';
		}, 6000);
		
		return {
    
    
			nameRef,
			state
		};
	}
}

toRefs

обзор

toRefsrefЭто практический метод уничтожения реагирующих объектов и преобразования всех их свойств в
1. Преобразование реагирующих объектов ( reactiveинкапсуляция) в обычные объекты
2. Каждое свойство объекта ( prop) соответствует ref
3. Оба сохраняют отношение ссылки


HTML

<template>
	<div class="demo">
		<h3>state方式不推荐的方式绑定</h3>
		<div>姓名--state.name: {
   
   { state.name }}</div>
		<div>年龄--state.age: {
   
   { state.age }}</div>
	</div>
	
	<div class="demo">
		<h3>toRefs之后的方式推荐这种方式,return需要{ ...toRefs(state) }</h3>
		<div>姓名--name: {
   
   { name }}</div>
		<div>年龄--age: {
   
   { age }}</div>
	</div>
</template>

JavaScript

import {
    
     reactive, toRefs } from 'vue';

export default {
    
    
	name: 'toRefsDemo',
	setup () {
    
    
		// 响应式对象
		const state = reactive({
    
    
			name: '太凉',
			age: 18
		});
		
		// 通过toRefs创建一个响应式对象属性的Ref
		const toRefsValue = toRefs(state);
		
		// 过3秒后改变  两者保持引用关系
		setTimeout(() => {
    
    
			state.name = '冰箱太凉';
			state.age = '30';
		}, 3000);
		
		// 过6秒后改变 两者保持引用关系
		setTimeout(() => {
    
    
			toRefsValue.name.value = '我就是宇宙小超人';
			toRefsValue.age.value = '101';
		}, 6000);
		
		return {
    
    
			// 不建议使用这种方式,可以用下面的方式直接替换
			state,
			// 最佳方式:这里是结构将name的ref,
			// age的ref结构到对象根下面
			...toRefsValue
		};
	}
}

Используйте toRefs(state) для возврата

<template>
	<div>
		<div>姓名:{
   
   { name }}</div>
		<div>年龄:{
   
   { age }}</div>
	</div>
</template>
import {
    
     reactive, toRefs } from 'vue';

export default {
    
    
	setup () {
    
    
		const state = reactive({
    
    
			age: 20,
			name: '太凉'
		});
		
		const stateAsRefs = toRefs(state);
		
		return {
    
    
			...stateAsRefs
		};
	}
}

Разница между ref и реактивным использованием

reactiveОпределите ссылочный тип данных, определите переменные, определенные refбазовым типом, которые будут использоваться напрямую, и определенные переменные должны использоваться непосредственно в шаблоне, что помогает нам судить, определен ли он ( через атрибуты), поэтому он добавляется автоматически .
reactiveref.value
vuereactiveref__v_isRef.value


Существенная разница между ref и reactive

Фрагмент кода один

Есть много деталей исходного кода, эта часть только анализирует основной код refи сначала находит функцию, вызывает функцию и возвращает класс.reactive
refcreateRefcreateRefRefImpl

export function ref(value?: unknown) {
     
     
	// 创建ref
	return createRef(value, false);
}

function createRef(rawValue: unknown, shallow: boolean) {
     
     
	if (isRef(rawValue)) return rawValue;
	
	// 返回一个RefImpl对象
	return new RefImpl(rawValue, shallow);
}

Фрагмент кода 2

RefImplЧувствуется ли класс знакомым, да Object.defineProperty, то, что здесь делается, это сбор зависимостей и запуск зависимостей, просто измените способ написания.

class RefImpl<T> {
     
     
	// 用来保存加工后实现响应化的值
	private _value: T
	// 用来保存当前未经加工过的值
	private _rawValue: T
	// 用来收集依赖,这是一个Set类型
	public dep?: Dep = undefined;
	// 用来标识该值是否经过ref加工
	public readonly __v_isRef = true;
	
	constructor(value: T, public readonly __v_isShallow: boolean) {
     
     
		// __v_isShallow默认没有传,
		// 故默认为undefined,这里分别调用toRaw和toReactive
		this._rawValue = __v_isShallow ? value : toRaw(value);
		this._value = __v_isShallow ? value : toReactive(value);
	}
	
	get value() {
     
     
		trackRefValue(this);
		
		return this._value;
	}
	
	set value(newVal) {
     
     
		const useDirectValue = this.__v_isShallow || isShallow(newVal) || isReadonly(newVal);
		newVal = useDirectValue ? newVal : toRaw(newVal);
		if (hasChanged(newVal, this._rawValue)) {
     
     
			this._rawValue = newVal;
			this._value = useDirectValue ? newVal : toReactive(newVal);
			triggerRefValue(this, newVal);
		}
	}
}

Фрагмент кода третий

toReactiveЕсли параметр, переданный функцией, является объектом, возвращаемое значение будет reactiveзаключено в оболочку путем вызова метода, и, reactiveнаконец, Proxyответ будет реализован через метод.

export const toReactive = <T extends unknown>(value: T): T => isObject(value) ? reactive(value) : value;

Подведем итог

один

1. Используются значения базового типа ( String, Number, Booleanили Symbol) или объекты с одним значением (например, { count: 1 }объекты только с одним значением атрибута) ref
2. Используются значения ссылочного типа ( Object, Array)reactive


два

reactiveИзмените значение ссылочного типа на адаптивный тип и используйте Proxyреализацию
ref, чтобы изменить как базовый тип, так и ссылочный тип на адаптивный тип, отслеживая сумму свойств класса , valueно когда переданное значение является ссылочным типом. , метод фактически используется внутренне Производительность обработки повышается после модифицированного метода реализации Рекомендуется использовать шаттлgetsetreactive
refref


три

1. При создании refбазового типа данных .серединеvue2что в,томуаналогичныйObject.definePropertyметод,черезреализуется
ответrefreactive
vue3refreactivereactiverefref


Кровавое озарение

1. refИнкапсулируйте данные в единое целое, перенаправьте данные на новый адрес памяти и дайте им возможность реагировать.
2. reactiveРазбейте все данные эталонных данных на отдельные независимые оперативные данные, чтобы добавлять, удалять, изменять и проверять данные, что означает углубленный мониторинг.
3. Если вы хотите сбросить массив во время разработки ref, рекомендуется использовать его, потому что refадрес памяти сбрасывается; если это фиксированный объект данных, и вы просто хотите изменить значение определенного атрибута в данных, то это reactiveболее уместно его использовать.


яма

Когда я мало разбираюсь в этом ref, reactiveнеправильно использую и определяю reactiveпустой массив для хранения данных, возвращаемых бэкендом, в результате запрошенные данные не отображаются нормально на странице.
При использовании vue3+ typeScript+ elementPlus+ selectдля реализации выбора раскрывающегося списка данные раскрывающегося списка всегда находились в состоянии «нет данных» и позже использовались для refрешения этой проблемы.

Guess you like

Origin blog.csdn.net/weixin_51157081/article/details/132287166