Vue 通过它的反应机制触发组件重新渲染,因此开发人员可以直接改变状态。Vue 会检测状态变化并触发组件重新渲染。
React 手动触发组件重新渲染setState,React 将区分 VDOM 以检查它是否应该重新渲染。建议开发人员不要直接改变状态,而是创建新的状态来替换原始状态,这样可以shallowEqual有效地处理原始状态和新状态。(不可变方法)。
例如,有一个状态如下:
state = { a: 1, b: 2 }
// mutate state in Vue
state.a = 3
// mutate state in React
this.setState({...state, a: 3 })
Run Code Online (Sandbox Code Playgroud)
似乎反应机制更直观,可以编写更少的代码。我想知道这两种方法之间的优缺点是什么?我应该选择哪种场景?
我试图在 vuejs 中拥有一个与 es6 类关联的计算属性。我的 Vue 实例如下所示:
...
props: ['customClass'],
computed: {
localClass: {
get() {
return this.customClass
},
set (value) {
console.log("changed")
}
}
}
...
Run Code Online (Sandbox Code Playgroud)
我的班级看起来像这样
class CustomClass {
constructor () {
this.selected = false
}
}
Run Code Online (Sandbox Code Playgroud)
如果我尝试做这样的事情:
this.localClass.selected = true
Run Code Online (Sandbox Code Playgroud)
但是从来没有调用过二传手,就像反应性已经丢失一样,我不明白为什么。
我也尝试:
Vue.set(this.localClass, 'selected', true)
Run Code Online (Sandbox Code Playgroud)
我将 customClass 作为 prop 传递,但即使直接在组件中创建新实例也不会改变结果。
在 vuejs 文档中,我不记得有一节讨论过 es6 类中的反应性问题,所以我想知道是否有人知道为什么以及如何使我的类具有反应性。
提前致谢
我试图将对象添加到我在Vue实例数据对象中声明的数组中.我可以在州的购买对象中设置值,但是当我将数据推送到订单队列数组时,不会填充空数组.该函数正在被触发,但该数组不会更新.
这是我的表格:
<form
v-on:submit.prevent="queuePurchase"
class="form-inline row"
id="order-creation-form"
method="POST"
>
@csrf
<autocomplete-field
sizing="col-xs-12 col-sm-3 col-md-3"
name="customer"
label="Customer"
:data="{{ json_encode($customers) }}"
v-on:setcustomer="setCustomer($event)"
></autocomplete-field>
<div class="col-xs-12 col-sm-3 col-md3 form-group d-flex flex-column align-items-start">
<label for="phone">Product</label>
<select
v-model="purchase.product"
class="form-control w-100"
name="product"
aria-describedby="productHelpBlock"
required
>
@foreach ($products as $product)
<option :value="{{ json_encode($product) }}">
{{ $product->name }}
</option>
@endforeach
</select>
<small id="productHelpBlock" class="form-text text-muted">
Select a product
</small>
</div>
<div class="col-xs-12 col-sm-3 col-md-3 form-group d-flex flex-column align-items-start">
<label for="phone">Quantity</label>
<input
v-model="purchase.quantity"
type="number"
min="1"
name="product"
class="form-control w-100"
aria-describedby="productHelpBlock" …Run Code Online (Sandbox Code Playgroud) 当传递的 prop 对象中的嵌套属性发生更改时,我无法更新计算属性。
this.favourite通过 props 传递,但当this.favourite.selectedChoices.second.id和this.favourite.selectedChoices.first.id更改时,计算属性不会更新。
关于如何使其具有反应性的任何想法?
这是计算的属性:
isDisabled() {
const hasMultipleChoices = this.favourite.choices.length
? this.favourite.choices[0].value.some(value => value.choices.length) :
false;
if (hasMultipleChoices && !this.favourite.selectedChoices.second.id) {
return true;
} else if (this.favourite.choices.length && !this.favourite.selectedChoices.first.id) {
return true;
}
return false;
}
Run Code Online (Sandbox Code Playgroud) 我正在使用mapGettersVueX的帮助程序,但我只在页面的第一次加载时遇到了一些问题,它不是反应性的......让我告诉你:
我的 html 模板触发更改:
<input type="number" value="this.inputValue" @change="this.$store.dispatch('setInputValue', $event.target.value)">
Run Code Online (Sandbox Code Playgroud)
我的商店收到价值
{
state: {
appValues: {
inputValue: null
},
},
getters: {
getInputValue: (state) => {
return state.appValues.inputValue;
},
},
mutations: {
setInputValue(state, value) {
state.appValues.inputValue = value;
},
},
actions: {
setInputValue(context, payload) {
return new Promise((resolve, reject) => {
context.commit('setInputValue', payload);
resolve();
});
},
}
}
Run Code Online (Sandbox Code Playgroud)
然后我的组件监听商店:
import {mapGetters} from 'vuex';
computed: {
...mapGetters({
inputValue: 'getInputValue',
}),
}
watch: {
inputValue: {
deep: true,
immediate: true,
handler(nVal, …Run Code Online (Sandbox Code Playgroud) Villager我有一个组件,它prop从父组件接收一个数组。父组件从 中提取该数组this.$store.state。
return this.$store.state.villages.find(value => value.id === 0).villagers
Run Code Online (Sandbox Code Playgroud)
之后我执行this.$store.mutation提交来更改给定的数组。正如您在下面的屏幕截图中看到的那样,突变确实有效。然而,我所在的组件没有重新渲染,并且仍然显示 3 个而不是 2 个项目。
反应链似乎在某个地方被破坏了,但我无法确定到底是哪个恶魔。我认为props价值是一种反应机制。正如您在屏幕截图中看到的,它的值已更改,但 DOM 并未相应更新。
我尝试提取问题的相关部分
商店/index.ts
[...]
export default new Vuex.Store({
state: {
villages: [
{
id: 0,
name: 'Peniuli',
foundingDate: 20,
villagers: [
{
id: '33b07765-0ec6-4600-aeb1-43187c362c5a1',
name: 'Baltasar',
bloodline: 'Gent',
occupation: 'Farmer'
},
[...]
mutations: {
disbandVillager (state, payload) {
const villagerId = payload.id
const village = state.villages.find(value => value.id === 0)
console.debug('disbanding villager:', villagerId)
if (!_.isNil(village)) …Run Code Online (Sandbox Code Playgroud) 如何创建对象属性reactive?
当我运行下面的代码时,导入的内容visible不会更改为true.
导入对象的组件:
<template>
<div class="context">
<span v-if="visible"> test </span>
</div>
</template>
Run Code Online (Sandbox Code Playgroud)
<script>
import { ContextManager } from "./utils.js";
import { ref } from "vue";
export default {
name: "context",
setup() {
const visible = ref(ContextManager.visible);
return { visible };
}
};
</script>
Run Code Online (Sandbox Code Playgroud)
向对象添加数据的其他组件:
const openContext = (e) => {
e.preventDefault();
ContextManager.add({
el: e.target,
items: contextItems
},e );
};
Run Code Online (Sandbox Code Playgroud)
上下文管理器对象:
import { reactive } from "vue";
export const ContextManager = reactive({
context: null,
visible: …Run Code Online (Sandbox Code Playgroud) 在 Vue3(组合 API)中,我有一个表单组件需要填充来自数据列表组件的数据。在表单组件中执行以下操作:
<input
v-model="formdata.formfields.FirstName"
type="text"
/>
<input
v-model="formdata.formfields.LastName"
type="text"
/>
...
props: {
fields: {
type: Object,
default: () => ({}),
},
},
setup(props, context) {
const formdata = reactive({
formfields: props.fields,
});
watch(
() => props.fields,
(current, previous) => {
formdata.formfields= current;
},
{ deep: true, immediate: true }
);
Run Code Online (Sandbox Code Playgroud)
由于不允许将 props 直接放入 v-model 中,所以我引入了该formdata变量。
然后在数据列表组件中,我将字段传递给此表单组件,如下所示,其中字段来自数据列表中的条目:
<dataform :fields="listitemfields" />
Run Code Online (Sandbox Code Playgroud)
这可行,但我觉得有点难看。而不是这样做,formdata.formfields.FirstName我宁愿formfields.FirstName只这样做。formfields但那时我似乎无法做出那样的反应。
以下不起作用:
const formfields = reactive({});
watch(
() => props.fields,
(current, …Run Code Online (Sandbox Code Playgroud) 当我从空对象创建 aref并随后添加对象属性时,没有反应性:
<template>
<p>{{hello}}</p>
<button @click="add()">Click me</button>
</template>
<script>
import {ref} from 'vue';
export default {
name: "Test",
setup(){
const myData = ref({});
return {myData}
},
methods: {
add(){
this.myData["text"] = "Hello";
console.log(this.myData);
}
},
computed: {
hello(){
return this.myData.hasOwnProperty("text")) ? this.myData["text"] : "no text";
}
}
}
</script>
Run Code Online (Sandbox Code Playgroud)
单击按钮显示myData 已更改,但计算的属性hello未更新。
也尝试过reactive({})而不是ref({})没有成功。
当我们使用诸如 之类的属性初始化 ref 时,它会起作用const myData = ref({"text": "no text"});。
但为什么空对象不起作用呢?
编辑:
终于找到了问题到底是什么以及如何解决:Vue3 的反应性核心不警惕属性的Object.keys()值,而仅警惕属性的值,而空对象没有任何属性值。但是,如果计算属性定义如下,则可以使 Vue3 发出警报 …
我正在开发一个使用 vue 和 firebase 的网站。在身份验证部分之后,用户进入仪表板,其中有他的项目列表,这些项目是 firestore 中用户文档的子集合。
我创建了一个 pinia 存储来管理这些数据,每次使用表单创建项目或删除项目时,都会state.projects使用新的项目数组进行更新,这些项目会循环显示视图中的列表。
在视图中,我可以访问store.projects应该是反应性的吸气剂,但当我添加或删除项目时,视图中没有任何反应,但仍然会state.projects更新。
这是DashboardView.vue的代码:
<template>
<MainHeader mode="dashboard" />
<main class="main">
<div class="main__container">
<section class="main__section">
<div class="section__header">
<h1 class="header__title">Projects</h1>
<!-- <TextInput type="text" placeholder="Search" v-model="filter" /> -->
</div>
<div class="section__content">
<ul class="content__list">
<li
v-for="project in projects"
:key="project.id"
class="content__item"
>
{{ project.id }}
<!-- <router-link
:to="{ name: 'ProjectView', params: { id: project.id} }">
</router-link> -->
<SimpleButton @click="deleteProject(project.id)" type="button" text="delete" />
</li>
</ul>
</div>
<div class="section__footer">
<form @submit.prevent="createProject">
<TextInput …Run Code Online (Sandbox Code Playgroud) vue-reactivity ×10
vue.js ×10
javascript ×6
vuejs3 ×3
vuejs2 ×2
vuex ×2
ecmascript-6 ×1
es6-class ×1
immutability ×1
laravel-5 ×1
pinia ×1
reactjs ×1
store ×1