Comecei a série https://laracasts.com/series/learning-vue-step-by-step . Parei na lição Vue, Laravel e AJAX com este erro:
vue.js: 2574 [Vue warn]: Evite alterar um objeto diretamente, pois o valor será substituído sempre que o componente pai for renderizado novamente. Em vez disso, use dados ou propriedades calculadas com base no valor do suporte. Suporte sendo mutado: "lista" (encontrada no componente)
Eu tenho esse código no main.js
Vue.component('task', {
template: '#task-template',
props: ['list'],
created() {
this.list = JSON.parse(this.list);
}
});
new Vue({
el: '.container'
})
Sei que o problema está em created () quando sobrescrevo o suporte da lista, mas sou novato no Vue, portanto, não sei como corrigi-lo. Alguém tem uma idéia de como (e por favor explique o porquê) para corrigi-lo?
javascript
vue.js
vuejs2
Dariusz Chowański
fonte
fonte
Respostas:
Isso tem a ver com o fato de que a mutação de um suporte local é considerada um anti-padrão no Vue 2
O que você deve fazer agora, caso queira alterar um suporte localmente , é declarar um campo no seu
data
que use oprops
valor como seu valor inicial e depois modifique a cópia:Você pode ler mais sobre isso no guia oficial do Vue.js.
Nota 1: Observe que você não deve usar o mesmo nome para seu
prop
edata
, por exemplo:Nota 2: Uma vez que eu sinto que há alguma confusão a respeito
props
e reatividade , eu sugiro que você ter um olhar sobre este tópicofonte
O padrão Vue está
props
baixo eevents
ativo. Parece simples, mas é fácil esquecer ao escrever um componente personalizado.A partir do Vue 2.2.0, você pode usar o modelo v (com propriedades calculadas ). Eu descobri que essa combinação cria uma interface simples, limpa e consistente entre os componentes:
props
passagem para seu componente permanece reativa (ou seja, não é clonada nem requer umawatch
função para atualizar uma cópia local quando são detectadas alterações).Uma propriedade computada permite que o setter e o getter sejam definidos separadamente. Isso permite que o
Task
componente seja reescrito da seguinte maneira:A propriedade model define a qual
prop
está associadov-model
e qual evento será emitido nas alterações. Você pode chamar esse componente do pai da seguinte maneira:A
listLocal
propriedade computada fornece uma interface simples de getter e setter dentro do componente (pense nisso como uma variável privada). Dentro de#task-template
você pode renderizarlistLocal
e permanecerá reativo (ou seja, se houverparentList
alterações, ele atualizará oTask
componente). Você também pode fazer uma mutaçãolistLocal
chamando o setter (por exemplo,this.listLocal = newList
) e ele emitirá a alteração para o pai.O melhor desse padrão é que você pode passar
listLocal
para um componente filho deTask
(usingv-model
), e as alterações do componente filho serão propagadas para o componente de nível superior.Por exemplo, digamos que temos um
EditTask
componente separado para fazer algum tipo de modificação nos dados da tarefa. Usando o mesmov-model
padrão de propriedades e computado, podemos passarlistLocal
para o componente (usingv-model
):Se
EditTask
emite um mudança que vai chamar apropriadamenteset()
emlistLocal
e, assim, propagar o evento para o nível superior. Da mesma forma, oEditTask
componente também pode chamar outros componentes filhos (como elementos de formulário) usandov-model
.fonte
O Vue apenas avisa: você altera o suporte no componente, mas quando o componente pai é renderizado novamente, a "lista" será substituída e você perde todas as alterações. Portanto, é perigoso fazê-lo.
Use a propriedade computada como esta:
fonte
Se você estiver usando o Lodash, poderá clonar o suporte antes de devolvê-lo. Esse padrão é útil se você modificar esse suporte no pai e no filho.
Digamos que tenhamos uma lista de props na grade de componentes .
No componente pai
No componente filho
fonte
Props para baixo, eventos para cima. Esse é o padrão de Vue. O ponto é que, se você tentar alterar os adereços que passam de um pai ou mãe. Não funcionará e apenas será sobrescrito repetidamente pelo componente pai. O componente filho pode emitir apenas um evento para notificar o componente pai a executar sth. Se você não gostar dessas restrições, poderá usar o VUEX (na verdade, esse padrão será uma sucção na estrutura de componentes complexos, você deve usar o VUEX!)
fonte
Você não deve alterar o valor dos objetos no componente filho. Se você realmente precisar mudar, pode usar
.sync
. Bem assim<your-component :list.sync="list"></your-component>
fonte
De acordo com o VueJs 2.0, você não deve alterar um suporte dentro do componente. Eles são apenas mutados pelos pais. Portanto, você deve definir variáveis nos dados com nomes diferentes e mantê-las atualizadas, observando os objetos reais. Caso o objeto da lista seja alterado por um pai, você pode analisá-lo e atribuí-lo a mutableList. Aqui está uma solução completa.
Ele usa mutableList para renderizar seu modelo, assim você mantém a sua lista segura no componente.
fonte
não altere os adereços diretamente em components.if você precisa alterá-lo, defina uma nova propriedade como esta:
E altere o valor de listClone.
fonte
A resposta é simples: você deve interromper a mutação direta do suporte atribuindo o valor a algumas variáveis locais do componente (pode ser uma propriedade de dados, calculada com getters, setters ou observadores).
Aqui está uma solução simples usando o observador.
É o que eu uso para criar qualquer componente de entrada de dados e funciona muito bem. Quaisquer novos dados enviados (modelo-v) do pai serão observados pelo observador de valores e serão atribuídos à variável de entrada e, uma vez que a entrada seja recebida, podemos capturar essa ação e emitir entrada para o pai, sugerindo que os dados sejam inseridos. do elemento do formulário.
fonte
Eu também enfrentei esse problema. O aviso foi depois que eu uso
$on
e$emit
. É algo como usar$on
e$emit
recomendado para enviar dados do componente filho para o componente pai.fonte
Se você deseja alterar os adereços - use object.
componente:
fonte
Você precisa adicionar um método computado como este
component.vue
fonte
fluxo de dados unidirecional, de acordo com https://vuejs.org/v2/guide/components.html , o componente segue o fluxo de dados unidirecional . Todos os adereços formam uma ligação unidirecional entre a propriedade filho e o pai primeiro, quando a propriedade pai é atualizada, ela flui para o filho, mas não o contrário, isso impede que os componentes filhos modifiquem acidentalmente os pais, o que pode dificultar a compreensão dos dados do aplicativo.
Além disso, sempre que o componente pai for atualizado, todos os objetos nos componentes filhos serão atualizados com o valor mais recente. Isso significa que você não deve tentar alterar um suporte dentro de um componente filho. Se você fizer .vue, você será avisado no console.
Geralmente, existem dois casos em que é tentador alterar um suporte: o suporte é usado para transmitir um valor inicial; o componente filho deseja usá-lo como uma propriedade de dados local posteriormente. O suporte é passado como um valor bruto que precisa ser transformado. A resposta apropriada para esses casos de uso são: Defina uma propriedade de dados local que use o valor inicial do objeto como seu valor inicial:
Defina uma propriedade calculada que é calculada a partir do valor do suporte:
fonte
Os adereços do Vue.js não devem ser alterados, pois isso é considerado um antipadrão no Vue.
A abordagem que você precisará adotar é criar uma propriedade de dados em seu componente que faça referência à propriedade prop original da lista
Agora sua estrutura de lista que é passada para o componente é referenciada e alterada através da
data
propriedade do seu componente :-)Se você deseja fazer mais do que apenas analisar a propriedade da lista, use a
computed
propriedade do componente Vue . Isso permite que você faça mutações mais profundas em seus objetos.O exemplo acima analisa o suporte da sua lista e o filtra para apenas os sistemas de lista ativos , faz o logout de schnitts e risadinhas e o retorna.
nota : ambas as propriedades
data
ecomputed
são referenciadas no modelo da mesma forma, por exemploPode ser fácil pensar que uma
computed
propriedade (sendo um método) precisa ser chamada ... nãofonte
Talvez isso atenda às suas necessidades.
fonte
Adicionando a melhor resposta,
A configuração de props por uma matriz é destinada à dev / prototipagem. Na produção, defina os tipos de prop ( https://vuejs.org/v2/guide/components-props.html ) e defina um valor padrão caso a prop não tenha foi preenchido pelo pai, como tal.
Dessa forma, você obtém pelo menos um objeto vazio em
mutableList
vez de um erro JSON.parse, se não estiver definido.fonte
O Vue.js considera isso um antipadrão. Por exemplo, declarar e definir alguns adereços como
Portanto, para resolver esse problema, é necessário levar um valor dos adereços para os dados ou a propriedade calculada de uma instância do Vue, assim:
Isso definitivamente vai funcionar.
fonte
Além do acima, para outras pessoas com o seguinte problema:
"Se o valor de props não for necessário e, portanto, nem sempre retornado, os dados passados retornarão
undefined
(em vez de vazios)". O que poderia atrapalhar<select>
o valor padrão, resolvi-o verificando se o valor está definidobeforeMount()
(e, se não estiver), da seguinte forma:JS:
Html:
fonte
Quero dar essa resposta que ajuda a evitar o uso de muito código, observadores e propriedades computadas. Em alguns casos, isso pode ser uma boa solução:
Os acessórios são projetados para fornecer comunicação unidirecional.
Quando você tem um
show/hide
botão modal com um suporte, a melhor solução para mim é emitir um evento:Em seguida, adicione listener ao elemento modal:
(Nesse caso, o suporte
show
provavelmente não é necessário porque você pode usar um easyv-if="show"
diretamente no modal base)fonte
Pessoalmente, sempre sugiro que você precise alterar os adereços, primeiro passe-os para a propriedade computada e retorne a partir daí; depois, é possível alterar os adereços facilmente, mesmo que você possa rastrear a mutação dos adereços, se estes estiverem sendo alterados por outro componente também ou podemos assistir também.
fonte
Como os adereços do Vue são um caminho de fluxo de dados, isso evita que os componentes filhos modifiquem acidentalmente o estado dos pais.
No documento oficial do Vue, encontraremos 2 maneiras de resolver esses problemas
se o componente filho quiser usar adereços como dados locais, é melhor definir uma propriedade de dados local.
O suporte é passado como um valor bruto que precisa ser transformado. Nesse caso, é melhor definir uma propriedade computada usando o valor do prop:
fonte
SIM !, os atributos mutantes no vue2 são antipadrão. MAS ... Apenas quebre as regras usando outras regras e siga em frente! O que você precisa é adicionar o modificador .sync ao atributo do componente no escopo do paret.
<your-awesome-components :custom-attribute-as-prob.sync="value" />
🤡 É simples matar o batman 😁
fonte
Para quando o TypeScript é o seu idioma preferido. de desenvolvimento
e não
fonte
Abaixo está um componente da lanchonete, quando eu fornecer a variável snackbar diretamente no modelo v como este, se funcionar, mas no console, ocorrerá um erro como
Evite alterar um suporte diretamente, pois o valor será substituído sempre que o componente pai for renderizado novamente. Em vez disso, use dados ou propriedades calculadas com base no valor do suporte.
A maneira correta de se livrar desse erro de mutação é usar o watcher
Portanto, no componente principal onde você carregará essa lanchonete, basta fazer esse código
Isso funcionou para mim
fonte