学习vue,顺手记录下的基础点笔记。
一定要有随手保存代码的习惯,除非你的开发工具设置了自动保存。
1. 组件使用
-
组件定义时名称为驼峰,例如HelloWorld,但在html里使用时用小写字母横杆连接,hello-world
-
自定义的组件在single-file components(.vue文件)/string template/jsx中使用时采用自闭合单标签形式,但是在html中使用时,要采用双标签,自闭合的单标签在默认情况下根本不管用。例如:
<app/><hello-world/>
这种写法浏览器只会渲染<app>
组件,而会把<hello-world/>
认为是<app></app>
内容以至于被<app>
的template覆盖了
2. 关于scoped
<style scoped></style>
style标签加上scoped属性,是指这里包含的css样式只会应用在包含它的组件的元素上- 同一个组件里,既可以有加scoped属性的style标签,也可以有不加scoped属性的style标签,它们作用域不同,前者是组件内,后者是全局范围生效(一般不这么用,全局的还是写在全局的css文件里)
- 加了scoped的样式不会影响子组件里的元素,只会影响子组件的根节点
- 如果想要父组件的加了scoped的样式影响到子组件,可以用
>>>
combinator,但有些预处理器可能不认>>>
combinator,这种情况下可以用/deep/
或者::v-deep
代替,这俩是>>>
的别名,效果完全一样。例如.a >>> .b { }
,可以影响子组件中的class名是b的元素的样式 - 当加了scoped的样式里有属性选择器时,浏览器渲染样式会几倍的慢,建议使用类选择器或id选择器,就跟不加scoped的性能差不多了
3. ref属性
-
用于快速定位到dom结构。
html使用
<div ref='test'></div>
js使用this.$refs.test => div这个元素对象
4. @import ‘./*.css’
5. ‘./a.css’和’…/a.css’区别
6. assets文件夹和static文件夹
- assets文件夹,主要放项目里用到的图片等静态资源
- static文件夹,主要放第三方的静态资源,比如字体
7. v-if例子和v-show例子
<!-- flag变量值为1时显示aa,2时显示bb,其他情况显示cc -->
<p v-if="flag === 1">aa</p>
<p v-else-if="flag === 2">bb</p>
<p v-else>cc</p>
<!-- flag为1时显示aa -->
<span v-show="flag === 1">aa</span>
8. v-show和v-if区别
v-if条件不符合时不会渲染对应元素
v-show条件不符合时会渲染对应元素,但样式设为display:none;
所以在选择使用哪个时,看使用场景,如果值不会频繁变化,就用v-if,但如果值会频繁变化时,使用v-show性能更好一些,因为v-if的元素切换时要渲染DOM元素这个过程是需要大量计算的,所以出于性能考虑我们一般是不赞成频繁进行DOM元素渲染的。
9. v-for遍历数组和遍历对象例子
<!-- 循环arr数组,每条数据显示顺序号和name属性 -->
<ul>
<li v-for="(item, index) in arr" :key="item.id"> <span>{{index + 1}}-{{item.name}}</span>
</li>
</ul>
<!-- 循环obj对象,每条数据显示顺序号-key-value -->
<ul>
<li v-for="(value, key, idx) in obj" :key="key">
{{idx + 1}}-{{key}}-{{value}}
</li>
</ul>
10. v-for跟v-if不建议一起用,有需要这样用的场景,可以使用computed属性,v-for绑定对原始数组进行filter之后返回的数组
11. 动态属性,比如<span v-bind:id='myId'>ss</span>
myId是data里定义的变量,简写就是<span :id="myId">ss</span>
。
动态class的两种写法,对象和数组,当然也可以是单个变量
<span :class="{class1: hasClass1, class2: hasClass2}">ss</span>
其中hasClass1和hasClass2是布尔型变量
<span :class=[class1, class2]>ss</span>
其中class1和class2是字符串型变量,class名
动态style绑定的是对象,其中样式名称用驼峰写法例如font-size写成fontSize
12. v-html有xss风险,会覆盖标签内容和子组件
13. vue事件中不用传参数时可以直接获取到event,有参数时需要把event参数传到事件处理函数中;vue的event参数是原生的,event.target是引起触发事件的元素,event.currentTarget是事件处理函数挂载的元素
14. `带格式的字符串`,这个符号包起来的字符串可以有格式,不需要写\n之类的换行
15. computed有缓存,data不变就不会重新计算;watch默认是浅度监听,就是只监听表层变化,除非设置deep:true(配合handler)才会递归遍历监听对象各属性进行watch;watch如果监听引用类型是拿不到oldVal的
16. computed使用
export default {
data () {
return {
num: 1, // 值类型
obj: { // 引用类型
pro: '哈哈'
}
}
},
computed: {
com1() { // 跟get方式一样
return this.num + 1
},
com2: { // get set方式
get() {
return this.num + 1
},
set(val) {
this.num = val - 1
}
}
},
watch: {
num(oldVal, val) {
console.log('watch', oldVal, val);
},
obj: {
handler(oldVal, val) {
console.log('deep watch', oldVal, val)
},
deep: true // 深度监听
}
}
}
// 使用时
<span>{{num}}</span>
<span>{{com1}}</span>
<span>{{com2}}</span>
<input v-model="com2" />
17. 事件修饰符
<!-- stop阻止事件继续传播 -->
<div v-on:click.stop="func"></div>
<!-- prevent阻止事件默认行为,例如submit事件的重载页面,a标签点击跳转等 -->
<form v-on:submit.prevent="func"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="func"></a>
<!-- 可以只有修饰符不加事件处理 -->
<form v-on:submit.prevent></form>
<!-- capture事件捕获期的事件处理函数 -->
<div v-on:click.capture="func">...</div>
<!-- self只有event.target是当前元素时触发的处理函数 -->
<div v-on:click.self="func">...</div>
18. 按键修饰符
.ctrl .alt .shift .meta
.enter .tab .delete .esc .space .up .down .left .right
<!-- 只要按下指定键,就算有其他按键一起按下也会触发 -->
<button v-on:keyup.ctrl="func">xx</button>
<!-- exact,只按下指定键时触发 -->
<button v-on:keyup.ctrl.exact="func">xx</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:keyup.exact="func">xx</button>
19. 表单修饰符
<!-- trim去掉首尾的空格 -->
<input v-model.trim="myInput" />
<!-- lazy防抖,从input触发变成change触发,离开输入框才进行输入的内容跟数据绑定的内容进行同步,因为v-model默认是每次值变化都会同步数据,所以可能造成画面抖动 -->
<input v-model.lazy="myInput" />
<!-- number把输入的内容转换成数字,因为默认输入的都会变成字符串,加上number修饰符就可以把输入的数字转化成数值型,对非数字内容不起作用 -->
<input v-model.number="myInput" />
20. 页面回到顶部
<div id="headDiv"></div>
// 调用headDiv.scrollIntoView()使顶部div可见达到目的
21. slot 插槽
父组件往子组件里插入内容
<!-- 常规使用 -->
<!-- 子组件 -->
<template>
<p>
<slot>
默认显示,当父组件没有往子组件插入内容
</slot>
</p>
</template>
<!-- 父组件 -->
<myComponent>
{{parentData.title}}
</myComponent>
<!-- 如果父组件想插入子组件的值 -->
<!-- 子组件 -->
<template>
<p>
<slot :childData="childDa">
默认显示,当父组件没有往子组件插入内容
</slot>
</p>
</template>
<!-- 父组件 -->
<myComponent>
<template v-slot="props">
{{props.childData.property}}
</template>
</myComponent>
<!-- 具名插槽:子组件好几个slot设置name -->
<!-- 子组件 -->
<template>
<p>
<slot name="slot1"></slot>
</p>
<p>
<slot></slot>
</p>
<p>
<slot name="slot2"></slot>
</p>
</template>
<!-- 父组件 -->
<myComponent>
<template v-slot:slot1></template>
<template></template>
<template #slot2></template>
</myComponent>
22. 动态组件
<component :is="namename" />
23. $nextTick
页面数据更改后立刻获取DOM元素,不会获取到最新的,因为还没有渲染,这时想要得到最新的DOM,可以把访问DOM的代码放到 n e x t T i c k 里 。 nextTick里。 nextTick里。nextTick是基于Promise.resolve().then()执行的回调,所以会比setTimeout的回调执行的早一些,效率高。
export default {
data() {
return {
list: ['1', '2']
}
}
methods: {
test() {
this.list.push('3')
this.list.push('4')
// 访问DOM元素放到$nextTick里
this.$nextTick(() => {
console.log(this.$refs.listDom.childNodes.length)
})
}
}
}
// 不管list里push几个,会将data修改做整合,都只会渲染一次,异步渲染,$nextTick会在DOM渲染完之后回调。
// 上面代码如果不把访问DOM放到$nextTick里,它会打印出来2也就是push前的长度而不是我们需要的4.
24. 异步组件
// 如果直接在这import就不是异步的,加载这个页面时就会加载组件
// import asyncComponent from './asyncComponent'
export default {
components: {
asyncComponent: () => import('../asyncComponent')
}
}
25. keep-alive
场景:缓存组件,tab频繁切换不需要重复渲染的情况,性能优化方式之一
当然,如果组件比较简单,也可以用v-show通过原生css来控制
使用方式:
<keep-alive>
<myComponent1 v-if="flag==1"></myComponent1>
<myComponent2 v-if="flag==2"></myComponent2>
<myComponent3 v-if="flag==3"></myComponent3>
</keep-alive>
26. 自定义v-model
27. vue生命周期
单个组件:
beforeCreate->created(实例初始化完毕)->beforeMount(生成虚拟DOM)->mounted(DOM渲染完毕)->beforeUpdate->updated->beforeDestroy(要解除自定义事件以及clearTimeout等)->destroyed
实例初始化各项目顺序:props -> methods ->data -> computed -> watch
父子组件:
父组件beforeCreate->父组件created->父组件beforeMount->子组件beforeCreate->子组件created->子组件beforeMount->子组件mounted->父组件mounted->父组件beforeUpdate->子组件beforeUpdate->子组件updated->父组件updated->父组件beforeDestroy->子组件beforedestroy->子组件destroyed->父组件destroyed
总结:初始化实例是父组件先初始化完毕,渲染是子组件先渲染完毕,更新是父先开始,子先更新完毕,销毁是父先开始销毁,子组件先销毁完毕。
28. 组件间通讯
父传子:props
子传父:this.$emit(‘事件名’,参数)
其他级别组件:event.$on(‘自定义事件名’,处理函数)
触发时使用event.$emit(‘自定义事件名’,参数)
组件销毁时移除自定义事件防止内存溢出 event.$off(‘自定义事件名’,处理函数)
29. mixin
mixin慎用,可能造成代码混乱,不易理解维护。