昨天看快手面经有这样一道题目,今天就试着来实现了一下
vue组件封装,写逻辑部分,css忽略。大概是:全选单选,就像购物车的全选按钮,五个商品五个按钮,一个全选按钮,点击全选,商品都选中,反之,商品都选中则全选按钮亮。
- html部分
<template id="check">
<div>
// 表示全选框,定义全选点击事件
<input type="checkbox" class="all_check" value="全选" @click='allCheck' ref="all">
// 利用v-for渲染五个单选框,定义单选点击事件
<input type="checkbox" class="one_check" @click='click1' v-for='value in times' ref="one" :key='value'>
</div>
</template>
- css部分(随意布局了一下…)
input {
display: block;
margin-top: 10px;
}
- js逻辑部分代码
详细见注释
data() {
return {
times: 5,
isAll: false,
num: 0,
ischeck: false
}
},
methods: {
allCheck(e) {
// isAll代表是否为全选
this.isAll = !this.isAll
let list = this.$refs.one
if (this.isAll) {
// 如果是全选的话,给每一个子元素的checked属性设置为true
for (let i = 0; i < list.length; i++) {
list[i].checked = true
}
// num用来计数,表示当前子元素有几个被选中
this.num = this.times
} else {
// 如果不是全选的话,给每一个子元素的checked属性设置为false
for (let i = 0; i < list.length; i++) {
list[i].checked = false
}
this.num = 0
}
},
click1(e) {
if (e.target.checked) {
// 如果当前元素被选中,那么num++
this.num++
} else {
// 有一个没有被选中的话,那么就说明不是全选,就设置this.isAll为false
this.num--
this.isAll = false
}
if (this.num == this.times) {
this.isAll = true
}
}
},
watch: {
isAll(newValue) {
if (newValue) {
this.$refs.all.checked = true
} else {
this.$refs.all.checked = false
}
}
}
4. 自我总结
本来觉得只是一个简简单单的小组件功能,结果自己写的时候真的出现了各种问题,这里记录一下:
(1) mdn引入vue的时候,创建组件的问题
平时基本上都用vue-cli来创建组件,只需在xx.vue里面定义好组件直接暴露出去导入使用就可以了,但是现在,需要利用vue的template模板创建组件,然后注册组件,引用组件,我基本上都忘光了
- 创建全局组件
//1. 创建组件的模板
<template id='info'>
<div>
<img src='./images/fm.jpg'>
<p>我是描述信息</p>
</div>
</template>
// 2. 注册组件
Vue.component('abc', {
template: "#info"
});
// 3. 使用组件
<abc></abc>
- 创建局部组件
//1. 创建组件的模板(和上面一样)
//2. 在vue实例的components属性里面注册组件
et vue = new Vue({
el: '#app1',
data: {
name: '王雨欣'
},
components: {
'abc': {
template: '#info'
}
}
});
// 3. 使用组件
(2)组件的命名问题
刚开始的时候我给全选框组件命名的是checkBox驼峰命名,但是使用的时候也是用来驼峰命名,结果报了这样的错: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the “name” option
vue的命名规范如下(组件名,数据,方法名):
1.1 注册组件的时候使用了"驼峰命名", 那么在使用时需要转换成"短横线分隔命名",官方推荐的组件名是每个单词首字母大写(PascalCase) 或者 全小写用 - 连接(kebab-case) 。 在DOM中使用的时候, 改为全小写, 单词之间用 - 连接。
例如: 注册时: myFather -> 使用时: my-father
1.2 在传递参数的时候如果想使用"驼峰名称", 那么就必须写"短横线分隔命名"
例如: 传递时: parent-name=“name” -> 接收时: props: [“parentName”]
1.3 在传递方法的时候不能使用"驼峰命名", 只能用"短横线分隔命名"
@parent-say=“say” -> this.$emit(“parent-say”);
(3)v-for的渲染问题:
v-for可以可以遍历 数组, 字符, 数字, 对象,用以渲染界面
可以通过ref取得v-for渲染的所有dom对象,会返回一个数组
(4)对<input type=checkbox>的复习
- radio是单选框(一个主题的选项必须指定一样的name属性),checkbox是复选框,同一个主题的复选框选项不会互斥,name也可以不同
// 还有value属性:指定input的值。如果省略,获取该元素的值的结果为字符串"on"。
<form action="http://vip.biancheng.net/register.php" method="post" name="formName">
爱好:<input type="checkbox" name="running" checked>跑步
<input type="checkbox" name="reading" checked>阅读
<input type="checkbox" name="shopping" checked>购物
</form>
(5) e.target.check
如何设置复选框元素是否被选中,只需要设置e.target.check=true/false
获取一个元素的属性可以直接把元素看成一个对象,元素的属性看做是对象的属性
eg:
let input = document.getElementById('read')
console.log(input.name); //reading
console.log(input.checkd); //false