编写轮子的过程中遇到的问题与总结,
轮子项目地址:https://github.com/o0Chivas0o/my-wheel
—2019-04-09—
- Vue组件中Props的变量接受类型可以是指定单个或多个类型.props具体属性可查看vue官方文档:https://cn.vuejs.org/v2/guide/components-props.html
1
2
3
4
5
6
7
8
9// props有2种写法:
1.
props:{
xxx:{
type:[String,Number]
}
}
2.
props:['xxx'] - 组件中name属性建议规范命名,便于调试
1
//通过 this.$option.name 可以获取到当前组件的名字
—2019-06-17—
- props中的default的值如果是对象或者数组,需要用函数return一个对象或数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19props:{
object:{
type:Object,
default:() => {
return {
a:'1',
b:'2'
}
}
},
array:{
type:Array,
default:() => {
return [
'a','b','c
]
}
}
}
### ---2019-07-02---
vue 默认合并 :style 和 class里的东西
1
2<w-tabs class='lee'></w-tabs>
// html 中 class 为 class='tabs lee'.sync的用法
1
2
3<w-tabs :selected.sync="selectedTab">
<w-tabs selected="selectedTab" @update:selected="selectedTab = $event">
// 两种写法是等价的vue 的事件不会冒泡
css中
margin-left:auto
可将元素放置在最右porps 与 data的区别
1
2
3
4
5
6
7prop:需要用户传值
data:不需要用户传值
function fn(prop1,prop2){
var data1 = prop1
data1 = 2
}通过
provide
和inject
API完成eventBus
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29//top-level
import Vue from 'vue'
export default{
...
data(){
return {
eventBus:new Vue(),
yyy:false
}
},
provide:{
eventBus:this.eventBus
},
mounted(){
this.eventBus.$emit('update:xxx',this.yyy)
}
}
//rest of level
export default{
...
inject:['eventBus'],
created(){
this.eventBus.$on('update:xxx',()=>{
// 通过回调来改变值或进行其他操作
})
}
}组件生成过程中使用
mounted
钩子函数进行后续操作,因为created
并不能确定组件是否完全生成
### ---2019-07-03---this.$children
的操作,只能获取到组件内的 子组件 ,并不能获取到组件内的 子元素
### ---2019-07-04---编写
popover
组件的思路,- 点击
button
使其展示或关闭,此方法仅能通过按钮来展示或关闭,满足不了更多的需求且有bug.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24<template>
<div class="popover" @click="xxx">
<div class='content-wrapper' v-if="visible">
<slot name='content'></slot> // 等价展示内容
</div>
<slot><slot> // 等价按钮
</div>
</template>
// 靠变量visible使其关闭或显示
<script>
...
data(){
return {
visible:false
}
},
methods:{
xxx(){
this.visible = !this.visible
}
}
...
</script> - 使其点击 body元素 就能关闭popove
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34// 接上段代码,更改methods中的xxx函数
xxx(){
this.visible = !this.visible
if(this.visible){
document.addEventListener('click',()=>{
this.visible = false
})
}
}
// 然而以上代码会产生几个bug
// 1. 监听器并没有删除,点击一次监听器在增加一个
// 2. 监听是同时进行的,当visible变为ture的瞬间,监听器便将其值更改为false,所以页面中看不到visible
// 3. 需要使用this.$nextTick或者setTimeout 来使其是异步操作
// 完善以上代码
xxx(){
this.visible = !this.visible
if(this.visible){
// 这个操作是因为
// 1. 箭头函数不具名
// 2. 如果修改为function x(){}.bind(this) 会新生成另一个函数,与x函数不同,所以提出来这样写
let x = () => {
this.visible = false
document.removeEventListener('click',x)
}
this.$nextTick(()=>{
document.addEventListener('click',x)
})
}
}
// 此时点击外层的document元素也能使其关闭内容展示 - 但是用户如果需要复制popover弹出层的内容,而这段代码不能满足该需求,所以修改如下结构.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32<template>
// vue中给@click事件添加修饰符.stop便阻止冒泡,仅添加这一项便能满足如下需求
<div class="popover" @click.stop="xxx">
<div class='content-wrapper' v-if="visible" @click.stop>
<slot name='content'></slot> // 等价展示内容
</div>
<slot><slot> // 等价按钮
</div>
</template>
// 靠变量visible使其关闭或显示
<script>
...
data(){
return {
visible:false
}
},
methods:{
xxx(){
this.visible = !this.visible
let x = () => {
this.visible = false
document.removeEventListener('click',x)
}
this.$nextTick(()=>{
document.addEventListener('click',x)
})
}
}
...
</script>
- 点击
—2019-07-08—
popover
组件,还需要注意几点.- 点击按钮开启,点击其他位置只关闭一次.(事件监听)
- popover显示内容,不能被具有
overflow:hidden
属性的元素遮挡,解决办法很简单,通过$refs.popoverContent
找到popover显示内容,并通过document.body.appendChild(popoverContent)
插入到body中. - 在寻找popover的位置时,如果页面出现滚动条,还会出现位置不正确的bug,需要在定位的同时,加上scroll的距离,例如:
this.$refs.contentWrapper.style.left = left + window.scrollX + 'px'
,该情况下是x方向出现滚动条的定位.
### ---2019-07-09--- - 在编写某些标签上的自定义属性,如果用到拼接字符串,需用双引号包起来,如:
1 | <use :xlink:href="`#i-${name}`"></use> |
—2019-07-15—
- 递归组件的几种写法.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42//以cascader组件为例子
// 1. 以组件中name为标识,通过组件name递归引用自身
<template>
<div class="cascader-item">
{{sourceItem.name}}
<w-cascader-item
v-if="sourceItem.children"
v-for="item in sourceItem.children"
:sourceItem="item"></w-cascader-item>
</div>
</template>
export default {
name: 'WCascaderItem',
props: {
sourceItem: {type: Object}
}
}
// 2. 以下形式
<template>
<div class="cascader-item">
{{sourceItem.name}}
<w-cascader-item
v-if="sourceItem.children"
v-for="item in sourceItem.children"
:sourceItem="item"></w-cascader-item>
</div>
</template>
const WCascadearItem = {
name: 'WCascaderItem',
components:{WCascadearItem},
props: {sourceItem: {type: Object}},
}
export default WCascadearItem
// 上述两种形式都需要在父组件中 import 该组件, 并添加components属性使用该组件. - scss
@mixin
和placeholder
的区别@mixin
会将属性重复写在被选择器选中的元素内(重复写属性)placeholder
会将选择器提取出来写在属性前(不会重复)
—2019-07-17—
- 编写组件需要用到数组记录的过程当中需注意:
- vue是不允许直接修改数组的,需要使用
this.$set(target,index,value)
这样的api来动态修改数组内的值 - 或者使用
this.target.push()
或者this.target.splice()
等数组方法来间接修改数组内的值. - 切记勿使用
this.array = value
来修改值 - 参考-深入响应式原理
- vue是不允许直接修改数组的,需要使用
- vue编写组件,不允许 子组件 直接 修改props的值
- 组件的编写尽量单项数据流的思路去做,省去很多麻烦
—2019-07-19—
- Vue自定义指令
- 组件如果需要操作dom,尽量封装到Vue指令中,
v-xxx
这种 - 具体编写查看vue文档,下面是cascader轮子中用到的自定义指令:
- 组件如果需要操作dom,尽量封装到Vue指令中,
1 | // click-outside.js |
—2019-07-22—
- vue动画
- transition 动画
- CSS animation 动画 (可搭配animate.css使用)
- JS 操作动画 (volocity.js 库使用 2.0.0版本以上可能存在问题)
- 条件渲染时,在渲染元素需要加上
key
,transition标签加mode
—2019-08-08—
- vue中 $children 如果是通过 slot 这种方式渲染的 不会马上拿到
—2019-08-10—
- 移动端 获取用户手指坐标(touchstart事件),通过e.touches[0]来获取第一个手指的坐标
—2019-08-12—
- vue.config.js 文件中 如若有修改路径目录的东西,需按以下写
1 | const path = require('path') |
—2019-08-20—
v-if 和 v-show的区别
- v-if让元素不出现在页面,而v-show则元素一直在页面.
- v-if 为 true 时 元素 create 当 v-if 为false 时 元素 destory,而v-show 只改变style,并没有生命周期
—2019-08-22—
浏览器会合并css属性,例如:
1 | el.style.height = 0 |
—2019-08-26—
表单验证有两种,及时验证,异步验证,参考
validate.js
- 及时验证
- 邮箱正则
/^.+@.+$/
- 手机
/\d{10}
或/\d{11}
- 邮箱正则
- 异步验证
- 需要用到查询数据的
一个关于引用类型的知识点 具体参考:https://segmentfault.com/a/1190000006769676
1 | let a = {} |
—2019-09-17—
uploader 组件 涉及到简单的node.js构建的静态服务器,其中有一些需要注意的地方
—2020-07-20—
发现table组件 并不能在 column 中 添加标签 如 a 标签进行其他操作,于是修改结构,将table自身column 属性,更改为 table-column 组件 , 通过 slot 来构建table 的 column , 其中发现需要声明一个组件来完成该操作.
- 需要构建一个组件来渲染子组件中的html标签
- 外层引用 需要用到 slot-scope 的属性
1 | <template> |
__END__