【问题标题】:Vue2 - Using :checked on checkbox input breaks default behaviourVue2 - 在复选框输入上使用 :checked 会破坏默认行为
【发布时间】:2018-01-02 03:58:43
【问题描述】:

我正在执行各种“状态更新”组件,在我的实际组件中,我将第一个自定义复选框(顶部的圆圈等)标记为 checked...但对于下面的 CodePen,我只是将它们全部标记为:checked='false' 以重复我的问题。

“twitter”复选框不会选中和取消选中。 Facebook 的会。

我确定这与我在 twitter 复选框上启用/禁用字符计数器有关。如果您单击其中一个 twitter 复选框,您会注意到字符计数器打开,但该复选框从未被选中(或者更确切地说,被选中然后立即取消选中)...

例如,在方法@​​987654324@ 中,如果我注释掉self.enableMaxCharLength = true;,复选框就会正常工作。

如果我从输入 v-for 中删除 :checked='false',则可以正常工作...

更新 - 工作笔和解决方案: https://codepen.io/mikebarwick/pen/qXdqBO

【问题讨论】:

  • 我没有投反对票,但您能否将相关代码粘贴到问题中,以防 codepen 链接出现问题。这将使这个问题对未来的读者有所帮助
  • 你看过 CodePen 了吗?这是很多代码 - 为什么要泛滥这个问题,这肯定会让用户无法阅读和/或提供答案。我解释了一个用例并提供了相关代码的链接。
  • @MikeBarwick 我在我的答案中将笔转换为 sn-p 只是作为一个例子。链接的主要问题是链接中断。
  • 谢谢,是的。我明白了。

标签: javascript vue.js vuejs2


【解决方案1】:

检查 twitter 帐户会导致重新渲染,这当然会将您的 checked 值设置为 false。

您需要记住选中的值。我做了一些小的修改可以做到这一点,但还有其他方法。

<input type="checkbox"
       :ref="key"
       :name="scheduleUsingBuffer ? 'buffer_profiles[]' : key + '[]'" 
       :value="scheduleUsingBuffer ? account.profile_id : account.page_id"                              
       :checked="account.checked"   
       @change="handleAccountInputChange(key, account)">

还有

handleAccountInputChange(type, account) {
  this.$set(account, 'checked', !account.checked)
  if (type == 'twitter') {                  
    this.toggleMaxCharLength();
  }
},

Updated pen.

另一种避免这种情况的方法是将复选框抽象为它们自己的组件,这些组件会记住它们的状态,这样当父级重新渲染时,复选框的状态就不会被覆盖。

另外,笔也变成了 SO sn-p。

var accounts = {
  facebook: {
    testing1: {
      page_id: '23derf56hg',
      img_url: null
    }
  },
  twitter: {
    testing2: {
      page_id: 'fr2wlfrhoi',
      img_url: null
    },
    testing3: {
      page_id: '92frgl5639',
      img_url: null
    }
  }
}

var app = new Vue({
  el: '#app',
  mounted(){
    setTimeout(() => {
      Object.keys(accounts).forEach((site, siteIndex) => {
        Object.keys(accounts[site]).forEach((account, actIndex) =>{
          accounts[site][account]["checked"] = (siteIndex === 0 && actIndex === 0)
        })
      })
      console.log(accounts)
      this.connectedAccounts = accounts
    }, 100)
  },
  data: {
    message: 'Hello Vue!',
    connectedAccounts: [],
    scheduleUsingBuffer: false,
    formData: {},
    enableMaxCharLength: false,
    maxCharCount: 140,
    remainingCharCount: 140,
    isAboveMaxCharCount: false,
    statusMessage: ''
  },
  
  methods: {
    onSubmit(event) {
		  this.formData = serialize(event.target, { hash: true });
		},
    
    toggleMaxCharLength() {
			this.enableMaxCharLength = false;

			Vue.nextTick(() => {
				var self = this;

				this.$refs.twitter.forEach(twitterInput => {
				   	if (twitterInput.checked) {
				   		self.enableMaxCharLength = true;
				   	}
				});
			});		
    },
    
    handleAccountInputChange(type, account) {
      this.$set(account, 'checked', !account.checked)
			if (type == 'twitter') {					
				this.toggleMaxCharLength();
			}
		},

		countdown() {
		 	this.remainingCharCount = this.maxCharCount - this.statusMessage.length;
		  this.isAboveMaxCharCount = this.remainingCharCount < 0;
		}    
  }
})
section.create-story {
  margin: 30px auto;
  width: 425px;
}
section.create-story h4 {
  margin-bottom: 15px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: normal;
  font-size: 14px;
}
section.create-story .switch {
  display: block;
  margin-bottom: 20px;
}
section.create-story #connected-accounts {
  margin-bottom: 15px;
}
section.create-story #connected-accounts label.account-checkbox {
  position: relative;
  display: inline-block;
  margin: 0 5px 0px 0;
  cursor: pointer;
}
section.create-story #connected-accounts label.account-checkbox .avatar {
  position: relative;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background-size: cover !important;
  background-position: center !important;
  background-color: #CCC !important;
  border: 2px solid #CCC;
  transition: all 0.1s ease-in-out;
}
section.create-story #connected-accounts label.account-checkbox .avatar,
section.create-story #connected-accounts label.account-checkbox .account-icon {
  filter: grayscale(100%);
  opacity: 0.3;
}
section.create-story #connected-accounts label.account-checkbox .avatar:hover,
section.create-story #connected-accounts label.account-checkbox .account-icon:hover {
  opacity: 1;
}
section.create-story #connected-accounts label.account-checkbox input[type="checkbox"] {
  display: none;
}
section.create-story #connected-accounts label.account-checkbox input[type="checkbox"]:checked + .avatar {
  border: 2px solid green;
}
section.create-story #connected-accounts label.account-checkbox input[type="checkbox"]:checked + .avatar + .account-icon {
  color: green;
}
section.create-story #connected-accounts label.account-checkbox input[type="checkbox"]:checked + .avatar, section.create-story #connected-accounts label.account-checkbox input[type="checkbox"]:checked + .avatar + .account-icon {
  filter: grayscale(0);
  opacity: 1;
}
section.create-story #connected-accounts label.account-checkbox .account-icon {
  position: absolute;
  font-size: 13px;
  width: 24px;
  height: 24px;
  line-height: 24px;
  right: -4px;
  bottom: -4px;
  background: white;
  color: #4d4d4d;
  border-radius: 50%;
  pointer-events: none;
  box-shadow: 0 1px 0 0px rgba(49, 49, 93, 0.05), 0 2px 3px 0 rgba(49, 49, 93, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.1);
}
section.create-story #status {
  margin-bottom: 20px;
  padding: 15px;
  border-radius: 5px;
  border: 1px solid #4d4d4d;
}
section.create-story #status textarea {
  display: block;
  margin-bottom: 15px;
  padding: 0;
  font-style: italic;
  font-size: 14px;
  min-height: 60px;
  border: none;
  box-shadow: none;
}
section.create-story #status .remaining-chars.has-text-danger {
  font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app">
  <section class="create-story box content">
	  <h4>New Story</h4>

		<form id="new-story" v-on:submit.prevent="onSubmit">
		  <div id="status">
			  <div id="connected-accounts">
							<span v-for="(accounts, key, index) in connectedAccounts">
								<label v-for="(account, i) in accounts" class="account-checkbox">
                  <input type="checkbox"
                         :key="key"
                    :ref="key"
                    :name="scheduleUsingBuffer ? 'buffer_profiles[]' : key + '[]'" 
                    :value="scheduleUsingBuffer ? account.profile_id : account.page_id"				                
                    :checked="account.checked" 	
                    @change="handleAccountInputChange(key, account)"> <!-- mark first account as "checked" :checked="index == 0 && i == 0" -->
                  
                    <div 
                      class="avatar"
                      :style="'background: url(' + account.img_url + ')'">
                    </div>

                      <i :class="'account-icon fa fa-' + key"></i>
                  </label>
              </span>					
						</div>

				<div class="control">
							<textarea @keyup="countdown" v-model="statusMessage" name="status-message" class="textarea" placeholder="What story do you have to tell?"></textarea>
						</div>	

				<div class="level">
							<div class="level-right">
								<div v-if="enableMaxCharLength" class="level-item">
									<span :class="{'has-text-danger': isAboveMaxCharCount}" class="remaining-chars" v-text="remainingCharCount"></span>
								</div>
								<div class="level-item">
									<input type="submit" value="Schedule" class="button  is-primary">	
								</div>
							</div>
						</div>
			</div>
		</form>
	</section>
</div>

【讨论】:

  • 太棒了。吃完午饭回来试试这个。不过乍一看,:checked="account.checked",json 不会(也不会有)checked 键/值。在我的实际代码中,我仅在第一项上将 :checked 值设置为真(即:checked="index == 0 && i == 0")
  • @MikeBarwick 我在handleAccountInputChange 方法中对此进行了补偿。如果该值不存在,它将添加它。吃顿好午餐!
  • 确实如此,但我认为这行不通。 :checked="account.checked" 将变为 :checked="index == 0 &amp;&amp; i == 0",导致 $set 无法按计划运行。对吗?
  • @MikeBarwick 我明白你的意思。 only 是第一个值吗?真的是您想要默认 为要检查的第一个值吗?
  • 没错,第一个复选框应始终为checked。也许有更好的方法来解决这个问题......注意:index == 0 &amp;&amp; i == 0 不适用于伪造的 codepen 数据。
猜你喜欢
  • 2015-10-05
  • 2021-09-22
  • 2018-11-22
  • 2012-03-19
  • 2014-03-16
  • 1970-01-01
  • 2023-01-30
  • 2020-03-29
  • 1970-01-01
相关资源
最近更新 更多