Vue2 - 使用:选中复选框输入会破坏默认行为

时间:2017-07-26 17:17:46

标签: javascript vue.js vuejs2

我正在进行"状态更新"在我的实际组件中,我将第一个自定义复选框(顶部的圆圈等)标记为checked ...但是对于下面的CodePen,我只是将它们全部标记为{{ 1}}迭代我的问题。

" twitter"复选框无法检查和取消选中。 Facebook的人会。

我确定这与我在twitter复选框上启用/禁用字符计数器这一事实有关。如果你点击其中一个推特复选框,你会注意到字符计数器打开,但是从不检查复选框(或者更确切地说,检查然后立即取消选中)...

例如,在方法:checked='false'中,如果我注释掉toggleMaxCharLength(),则复选框可以正常工作。

如果我从输入self.enableMaxCharLength = true;中移除:checked='false',则按原样运行...

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

1 个答案:

答案 0 :(得分:3)

检查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片段。

&#13;
&#13;
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;
		}    
  }
})
&#13;
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;
}
&#13;
<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>
&#13;
&#13;
&#13;