Vue.js 2:重用元素逻辑如何在'v-if''v-else-if''中工作(为什么它不能在嵌套元素上工作)

ca1c2owp  于 2023-01-09  发布在  Vue.js
关注(0)|答案(3)|浏览(171)

我有这个代码:(注意input s和label s以及v-if s和v-else s的结构)

new window.Vue({
  el: "#app",

  template: `
    <div>
      This will reset:
      <div v-if="loginType === 'username'">
        <label>Username: <input/></label>
      </div>
      <div v-else>
        <label>Email: <input/></label>
      </div>

      <br />

      This will not:
      <div v-if="loginType === 'username'">
        <label>Username: </label>
        <input/>
      </div>
      <div v-else>
        <label>Email: </label>
        <input/>
      </div>

      <br />

      This will reset too:
      <div v-if="loginType === 'username'">
        <label>Username: </label>
        <input key="input-for-username"/>
      </div>
      <div v-else>
        <label>Email: </label>
        <input key="input-for-email"/>
      </div>

      <br />

      <button @click=changeLoginType>Change Username</button>
    </div>`,

  data: () => {
    return { loginType: "email" };
  },

  methods: {
    changeLoginType() {
      if (this.loginType === "email") this.loginType = "username";
      else this.loginType = "email";
    }
  }
});

可执行代码沙箱:https://codesandbox.io/s/jovial-elion-cntkin?file=/src/index.js
This code renders a switchable input (switches between "email" input and "username" input). I got this code from Vue.js 2 documentation: https://v2.vuejs.org/v2/guide/conditional.html#Controlling-Reusable-Elements-with-key
文档中说VUe.js重用了v-if块和v-else块中的input元素,因此用户输入的值保持不变。当您在用户名和电子邮件之间切换时,它不会重置。但在我的代码中,第一个示例的输入在切换时重置。这是因为Vue.js只保留第一级直接子元素相同的元素(在这个例子中是label)?我的意思是它改变了每个属性和所有的HTML内容,而只是 * 没有 * 元素本身?
我试着用它做了一些尝试,我试图找到一种方法来告诉Vue.js重用下面代码摘录中的输入:

<div v-if="loginType === 'username'">
  <label>Username: <input/></label>
</div>
<div v-else>
  <label>Email: <input/></label>
</div>

(by重用我的意思是,如果我切换loginType,除了input的值保持与用户输入的相同。

bwleehnv

bwleehnv1#

在MVVM的世界里,更好的选择不是依赖于框架,因为它重用了我们所看到的东西,而是使用“VM”并显式地绑定组件模板中的数据。这个想法不是尽可能多地重用DOM(实际上,我从不依赖于DOM),而是将输入值“连接”到彼此,这样无论它们是否被重用,视觉上它们总是显示相同的数据
您需要做的是在组件中定义state属性,并使用“v-model”指令将其附加到两个输入:

<template>
    <div v-if="loginType === 'username'">
        <label>Username: </label>
        <input v-model="userLogin" />
    </div>
    <div v-else>
        <label>Email: </label>
        <input v-model="userLogin" />
    </div>

    <button @click="changeLoginType()">Change Username</button>
</template>

<script>
export default {
    name: 'App',
    data: () => {
        return { loginType: 'email', userLogin: '' };
    },
    methods: {
        changeLoginType() {
            if (this.loginType === 'email') this.loginType = 'username';
            else this.loginType = 'email';
        },
    },
};
</script>

在这种情况下,无论您选择哪个选项,您的输入值总是从组件状态中取值,并且输入的更改将反映在状态中(所谓的双向数据绑定)
另外,有趣的是,当我使用Vue 3在新创建的应用程序中使用初始代码示例时--当单击按钮和更改登录类型时,输入值总是重置。因此,无论它在Vue 2中的行为如何,在新版本的Vue中,事情可能会发生变化,以前工作的代码可能会失败,因此,从长期项目支持的Angular 明确定义事情肯定更好

nnt7mjpx

nnt7mjpx2#

当使用v-for时,key属性是key,但它也有助于v-if/v-else。它防止Vue重用相同的DOM节点。
你应该试试这样的方法:

<template>
  <div>
    <label for="account">{{ loginType === 'username' ? 'Username' : 'E-mail' }}</label>
    <input id="account" v-model.trim="usernameOrEmail" :type="loginType === 'username' ? 'text' : 'email'">
  </div>
</template>
kmb7vmvb

kmb7vmvb3#

在Vue中,您必须将输入值从视图传递到模型,反之亦然(双向数据绑定),为此,您需要Vue的v-model指令。
现在,要达到这个要求,您只需将输入值绑定到一个变量,然后在changeLoginType()方法上重置/清除它。
现场演示**:**

new Vue({
  el: '#app',
  data: {
    loginType: "email",
    inputVal: ''
  },
  methods: {
    changeLoginType() {
      this.inputVal = '';
      this.loginType = this.loginType === 'email' ? 'username' : 'email';
    }
  }
})
<div id="app">
  <div v-if="loginType === 'username'">
    <label>Username: </label>
    <input v-model="inputVal"/>
  </div>
  <div v-else>
    <label>Email: </label>
    <input v-model="inputVal"/>
  </div>
  <button @click=changeLoginType>Change Username</button>
</div>

相关问题