Vue.config.productionTip=false //阳止 vue在启动时生成生产提示。
BootCDN
MOMENT.JS 日期处理库 dayjs
解构赋值连续写法
{query:{id,title}}
debugger调试
debugger
debugger 语句用于停止执行 JavaScript,并调用 (如果可用) 调试函数。
使用 debugger 语句类似于在代码中设置断点。
通常,你可以通过按下 F12 开启调试工具, 并在调试菜单中选择 "Console" 。
注意: 如果调试工具不可用,则调试语句将无法工作。
MVC
MVVM
M : 模型(Model) : 对应data中的数据
V : 视图 (View) : 模板
VM : 视图模型(ViewModel) :vue实例对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4vJxQlEj-1651137472216)(C:\Users\mht\AppData\Roaming\Typora\typora-user-images\image-20211212181705266.png)]
回顾 Object.defineproperty方法 reduce
Object.defineproperty(‘'给哪个对象添加属性','添加的属性叫什么名字',{
配置项
value:18,
enumerable:true,//控制属性是否可以枚举,默认false
writable:true,//控制属性是否可以修改,默认false
configurable:true,//控制属性是否可以被删除,默认值是false
//当有人读取obj的age属性时,get函数就会被调用,据返回值就是age的值
get:function({
return: number
}),
//当有人修改了obj的age属性时,set函数(setter)就会被调用,且会收到修改的具体值。
set(value){
console.log('有人修改了age属性,且值是',value)
number=value;
}
})
添加的属性不可以被枚举(遍历)
Object.keys(object)
delete obj.name
https://www.jianshu.com/p/e375ba1cfc47
reduce()方法可以搞定的东西,for循环,或者forEach方法有时候也可以搞定,那为啥要用reduce()?这个问题,之前我也想过,要说原因还真找不到,唯一能找到的是:通往成功的道路有很多,但是总有一条路是最捷径的,亦或许reduce()逼格更高...
array.reduce(()=>{},0)
callback (执行数组中每个值的函数,包含四个参数)
1、previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
2、currentValue (数组中当前被处理的元素)
3、index (当前元素在数组中的索引)
4、array (调用 reduce 的数组)
initialValue (作为第一次调用 callback 的第一个参数。)
例子
var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
console.log(prev, cur, index);
return prev + cur;
})
console.log(arr, sum);
打印结果:
0 1 0
1 2 1
3 3 2
6 4 3
[1, 2, 3, 4] 10
这个例子index是从0开始的,第一次的prev的值是我们设置的初始值0,数组长度是4,reduce函数循环4次。
结论:如果没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供initialValue,从索引0开始。
数据代理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qIb2seYZ-1651137472217)(C:\Users\mht\AppData\Roaming\Typora\typora-user-images\image-20211212192220990.png)]
数据代理:通过一个对象代理对另一个对象中属性的操作 读/写
1.Vue中的数据代理:
通过vm对象来代理data对象中属性的操作(读/写)
2.Vue中数据代理的好处:
更加方便的操作data中的数据
3.基本原理:
通过object.defineProperty()把data对象中所有属性添加到vm 上.为每一个添加到vm上的属性,都指定一个getter/setter.
在getter/setter内部去操作(读/写)data中对应的属性。
let obj1={x:100}
let obj2={y:200}
Object.defineProperty(obj2,'x',{
get(){
return obj1.x
},
set(value){
obj1.x=value
}
})
vue 中的data的数据都是代理的
vm._data===data
vm._data= 里面作了数据劫持
vue原型对象
Vue.prototype
Vue.extend()返回值是VueComponents
图像界面创建
vue ui 图像界面创建
选vue3.x
1.安装插件
axios
2.安装依赖
echarts
echarts-gl 3d的库
template 标签包裹dom元素但不生成dom元素
v-model
v-model.number
事件
v-on 简写@ 绑定
@click 点击
@wheel 鼠标滚轮滚动事件
@scroll 滚动条滚动事件
1.onmouseenter和onmouseleave是一组:当鼠标进入指定区域的时候触发,但是不支持冒泡,进入或者离开子组件都不触发
onmouseenter和onmouseleave相当于绑定的区域为A+B
2.onmouseover和onmouseout是一组:当鼠标进入指定区域的时候触发,进入或者离开子组件也都触发
onmouseover和onmouseout相当于绑定的区域为A(不包含B)
事件修饰符
e.preventDefault()阻止默认行为
e.stopPropagation()阻止冒泡
e.target 获取点击的元素
@click.prevent=""阻止默认行为
Vue中的事件修饰符:
1.prevent:止默认事件(常用);
2.stop:阻止事件冒泡(常用);
3.once:事件只触发一次(常用);
4.capture:使用事件的捕获模式; 一般是先捕获在冒泡 冒泡才开始触发事件 加完后就是 捕获的时候就触发事件
5.self:只有event.target是当前操作的元素是才触发事件;
6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
键盘事件
keydown按下去
keyup抬起来
keyCOde 键盘编码
@keyup.enter
常用的按键别名:
回车=>enter
删除=>delete(捕获“删除”和“退格”键)
退出=>esc
空格=>space
换行=>tab(切换焦点必须配置keydown使用)
上=>up
下=>down
左=>left
右=>right
@keyup.caps-lock 切换大小写
2.Vue未提供别名的按健,可以使用按健原始的key值去绑定,但注意要转为kebab-case(短横线命名)
3.系统修饰键(用法特殊):ctrl、alt、 shift、meta
(1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他健,事件才被触发。
(2).配合keydown使用:正常触发事件。
4.也可以使用keyCode去指定具体的按键(不推荐)
5.Vue.config.keyCodes.自定义健名=键码,可以去定制按键别名
计算属性与监听,过滤
vue所管理的函数都要写普通函数
计算属性
//计算属性
不能开启异步任务的
export default {
data() {
return {
hasWeixinAuth: '您好',
}
},
computed:{
hash:{
//get有什么作用?当有人读取hash时,get就会被调用,且返回值就作为hash的值 重复调用走缓存
//get什么时候调用? 1.初次读取hash的时候调用。2.所有依赖的数据发生变化时
get(){
console.log('被调用了');
return '帅哥'+this.hasWeixinAuth
},
//set什么时候调用? 当hash被修改的时候
set(value){
console.log('set',value);
const arr=value.split('-');
console.log(arr);
}
}
},
onShow() {
this.hash='李-四';
},
methods: {
demo(){
}
}
}
简写(只读取不改)
computed:{
hsah(){
console.log('被调用了');
return '帅哥'+this.hasWeixinAuth
}
}
监视属性watch
可以做异步任务的
监视属性watch:
1.当被监视的属性变化时,回调函数自动调用,进行相关操作
2.监视的属性必须存在,才能进行监视!!
3.监视的两种写法:
(1).new Vue时传入watch配置
(2).通过vm.$watch监视
watch:{
isHot:{
//handler什么时候被调用?当isHot发生改变的时候
immediate:true,//初始化时让handler调用一下
deep:true,//深度监听
handler(newValue,oldValue){
新值和旧值对比
console.log('isHot被修改了',newValue,oldValue)
}
}
}
vm.$watch('isHot',{
//handler什么时候被调用?当isHot发生改变的时候
immediate:true,//初始化时让handler调用一下
handler(newValue,oldValue){
新值和旧值对比
console.log('isHot被修改了',newValue,oldValue)
}
})
还可以监听计算属性里面的值
export default {
data() {
return {
hasWeixinAuth: '您好',
isShow:true,
}
},
computed:{
info(){
return this.isShow?'炎热':'寒冷'
}
},
watch:{
info:{
immediate:true,
handler(newValue,oldValue){
console.log('info被修改了',newValue,oldValue)
}
},
},
methods: {
demo(){
this.isShow=!this.isShow
}
}
}
//深度监听
/**
(1).Vue中的watch默认不监测对象内部值的改变(一层)
(2).N置deep:true可以监测对象内部值改变(多层)
-备注:
(1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
(2).使用watch时根据数据的具体结构,决定是否采用深度监视-
*/
data() {
return {
numbers:{
a:1,
b:2
}
}
},
watch:{
'numbers.a':{
//监视多级结构中某个属性的变化
immediate:true,
handler(newValue,oldValue){
console.log('a被修改了',newValue,oldValue)
}
},
numbers:{
//监视多级结构中所有属性的变化
deep:true,
immediate:true,
handler(value){
console.log('a被修改了',value)
}
}
},
// 简写(简写了就不能配置了)
info(newValue,oldValue){
console.log('info被修改了',newValue,oldValue)
}
vm.$watch('isShow',function(newValue,oldValue){
console.log('info被修改了',newValue,oldValue)
})
vue监测数据的原理
vue 怎么检测对象中数据改变的
defineProperty
加工data 就可以实现对对象进行监视
vue监测数组的原理
数组里面值得变化不是靠set和get来监测的
用这写可以改变原数组的来写 可以相应
包装数组修改数组身上的方法实现的
push push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度。
pop pop() 方法用于删除数组的最后一个元素并返回删除的元素。
shift shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。
unshift unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。
splice
sort
reverse(颠倒数组中元素的顺序:)
Vue数据监听总结
过滤器
<h3>{{ time | timeFormater('YY年MM月DD日') | mySlice}}</h3>
过滤器本质是个函数
局部过滤器
首先读取time 将time作为参数给timeFormater函数 最好返回值会把他{{ time | timeFormater}}全部替换掉
第一个参数 就是time 阶梯模式往下传
filters:{
timeFormater(value,str="YY年MM月DD日 HH:mm:ss"){
}
}
全局的叫filter
Vue.filter('mySlice',function(value){
return value.slice(0,4)
})
用于插值语法
绑定值的时候也可以用
有时候电商 1999 => 过滤成1,900
<h3 :x="msg | mySlice ">撒大大</h3>
过滤
filter不改变原数组 返回新数组
应用场景
平时开发中,需要用到过滤器的地方有很多,比如单位转换、数字打点、文本格式化、时间格式化之类的等
比如我们要实现将30000 => 30,000,这时候我们就需要使用过滤器
Vue.filter('过滤器名称',function(){
})
//搜索 watch 实现
<body>
<div id="app">
<h1>人员列表</h1>
<button @click.once="add">添加</button>
<input type="text" placeholder="请输入名字" v-model="keyWord">
<ul>
<li v-for="(p,index) in filterPersons" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
<script>
new Vue({
el: '#app',
data:{
keyWord:'',
persons: [
{ id: '001', name: '马东梅', age: 18,sex:'女' },
{ id: '002', name: '周冬雨', age: 19,sex:'女' },
{ id: '003', name: '夏洛', age: 20,sex:'男' },
{ id: '004', name: '金毛狮王', age: 21,sex:'男' },
],
filterPersons:[]
},
filter:{
},
watch: {
keyWord:{
immediate:true,
handler(newValue){
this.filterPersons = this.persons.filter((p)=>{
return p.name.indexOf(newValue)!== -1;
})
}
}
},
methods: {
}
})
</script>
</body>
//计算属性的过滤
new Vue({
el: '#app',
data:{
keyWord:'',
persons: [
{ id: '001', name: '马冬梅', age: 18,sex:'女' },
{ id: '002', name: '周冬雨', age: 19,sex:'女' },
{ id: '003', name: '夏洛', age: 20,sex:'男' },
{ id: '004', name: '金毛狮王', age: 21,sex:'男' },
],
},
computed:{
filterPersons(){
return this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord)!== -1;
console.log(p);
})
}
}
})
1.定义:要用的属性不存在,要通过已有的计算属性得来
2.原理:底层借助了objcet.defineproperty方法提供的getter和setter.
3.get函数什么时候执行?
(1).初次读取时会执行一次。
(2).当依赖的数据发生改变时会被再次调用。
4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
5.备注:
1.计算属性最终会出现在vm 上。直接读取使用即可。
2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
//可以读性高
computed:{
//方法:函数
}
计算属性与方法的区别
计算属性是基于他们的依赖进行缓存的(依赖指data 中的数据) 比较耗时的计算可以节省性能
方法不存在缓存的
//监听 处理异步 用于登录
watch:{
isHot:{
//handler什么时候被调用?当isHot发生改变的时候
immediate:true,//初始化时让handler调用一下
handler(newValue,oldValue){
新值和旧值对比
console.log('isHot被修改了',newValue,oldValue)
}
}
}
这两个都可以实现相同效果但过程有点不一样
Computed特点:
需要主动调用,具有缓存能力只有数据再次改变才会重新渲染,
否则就会直接拿取缓存中的数据。
Watch特点:
无论在哪只要被绑定数据发生变化Watch就会响应,
这个特点很适合在异步操作时用上。
//过滤器
应用场景
平时开发中,需要用到过滤器的地方有很多,比如单位转换、数字打点、文本格式化、时间格式化之类的等
比如我们要实现将30000 => 30,000,这时候我们就需要使用过滤器
Vue.filter('过滤器名称',function(){
})
key作用与原理
用inputd时最好用id 区分
面试题: react. vue中的key有什么作用?(key的内部原理)
1.虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当状态中的数据发生变化时,Vue会根据【新数据】生成【新的虚拟DON》,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
2.对比规则:
(1).旧虚拟DOw中找到了与新虚拟DOM相同的key:
1.若虚拟DOM中内容没变,直按使用之前的真实DOW!
2.若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
(2).旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到到页面。
3.用index作为key可能会引发的问题:
1.若对数据进行:逆序添加、逆序删除等破环顺序操作:
会产生没有必要的真实DOM更新==>界面效果没问题,但效率低。
2.如果结构中还包含输入类的DOM:
会产生错误DOM更新==>界面有问题。
4.开发中如何选择key?
1.最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,
使用index作为key是没有问题的。
收集表单信息
单选框
要配置value值
多选
初始化数据是数组
@submit.prevent 表单提交事件
type="number" v-model.number 输入的字符串转成有效数字
v-model.lazy 失去焦点后在收集数据
v-model.trim 输入首位空格过滤
vue.set()
//改数组里面的值
this.$set('哪个对象','对象的哪个属性','值是什么');
只能给data中某个响应式对象添加属性
//改数组里面的值
this.$set('哪个数组','数组的下标','值是什么');
内置指令
v-text
向其所在的标签插文本
name='牛比'
拿到name的值替换掉整个内容的值
<div v-text=name> </div> => <div>牛比</div>
v-html
v-cloak
主要解决当你网速过慢的时候他不会让你未经过解析的东西跑到页面上去
1.本质是一个特殊属性 Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
2.使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。
<style>
[v-cloak]{
display: noen;
}
</style>
<h1 v-cloak>人员列表</h1>
v-once
1.v-once所在节点在初次动态渲染后,就视为静态内容了。
2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
<h1 v-once>初始化的n值:{{n}}</h1>
<h1>当前的n值:{{n}}</h1>
<button @click="n++">n++</button>
v-pre
1.跳过其所在节点的编译过程。
2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。
加了之后vue就不去解析他了
自定义指令
directives:{
对象和函数的写法
big:{
},
big(){
}
}
生命周期
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eOuR8ee1-1651137472218)(C:\Users\mht\AppData\Roaming\Typora\typora-user-images\image-20211223205619303.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BTd8NRXP-1651137472219)(C:\Users\mht\AppData\Roaming\Typora\typora-user-images\image-20211223205713030.png)]
mounted(挂载完毕)
//Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
-
什么是生命周期
- 一个组件从创建到销毁的过程,就是组件的一生
-
作用
- 在不同的阶段做不同的事
-
分四个阶段
-
a.挂载阶段,只执行一次
-
beforeCreate
- 实例初始化后调用,做一些初始化的事件,但组件的data、methods、computed、props、watch…等等选项对象还未创建,数据观察与事件机制尚未形成,也就不能使用data中的状态和methods方法
-
created
- 实例已经创建完成之后被调用,可以通过this访问
inject
,props
,data
,methods
,computed
,watch
等大部分属性和方法了 - 可以在此发网络请求
- 实例已经创建完成之后被调用,可以通过this访问
-
beforeMount
- 挂载前调用,在内存中对模板与数据进行编译结合,但此时还没有挂载到页面上,页面还是旧的,可以在此 对数据进行最后一步修改
-
mounted
- 挂载完成,内存中编译好的vnode渲染到了网页上,此时才可以获取dom,但不建议直接操作dom,要用框架的思想通过状态去实现需求
-
-
b.更新阶段,状态更新了就会触发
- beforeUpdate
- 响应式数据更新时调用,当状态发生改变的时候就会触发此钩子函数,页面还没有和最新的数据保持同步,这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器
- updated
- 数据与模板相互结合 ,会将新数据挂载到页面上,可以在此获取最新的dom结构,避免在此期间更改状态,因为这可能会导致更新无限循环
- beforeUpdate
-
c.销毁阶段
- beforeDestroy
- 在实例销毁之前调用,实例仍然完全可用
- 一般在这一步做一些重置的操作,比如清除掉组件中的定时器 和 解绑监听的dom事件
- destroyed
- 在实例销毁之后调用,所有的事件监听器会被移出,所有的子组件实例也会被销毁,所有的 data 和 methods , 指令, 过滤器 ……都是处于不可用状态。组件销毁后会将vue与当前网页之间的关系进行断开解绑
- beforeDestroy
-
d.错误捕获
- errorCaptured
- 当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回
false
以阻止该错误继续向上传播。
- 当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回
- errorCaptured
-
-
keep-alive专属
- activited
- 组件被激活时调用
- deactivated
- 组件被销毁时调用
- activited
组件化编程
非单文件组件
Vue中使用组件的三大步骤:
一、定义组件(创建组件)
二、注册组件
三、使用组件(写组件标签)
一、如何定义一个组件?
使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options儿乎一样,但也有点区别;
区别如下:
1.el不要写,为什么?—最终所有的组件都要经过一个vm的管理,tvm中的el决定服务哪个容器。
2.data必须写成函数,为什么?——避免组件被复用时,数据存在引用关系。
备注:使用template可以配置组件结构。
二、如何注册组件?
1.局部注册:靠new Vue的时候传入components选项
2.全局注册:菲vue.component('组件名",组件)
三、编写组件标签:
<school></ school>
const schoo = Vue.extend({
name:'atghg',
template:``,
data(){
return{
}
},
methods: {
}
})
//全局注册组件
Vue.components('schoo',schoo)
components:{
schoo,
}
单文件组件
组件注意事项
1.关于组件名:
一个单词组成:
第一种写法(首字母小写):school
第二种写法(首字母大写):School
多个单词组成:
第一种写法(kebab-case命名):my-school
第二种写法(Camelcase命名):MySchoo1(需要Vue脚手架支持)
备注:
(1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。
(2).可以使用name配置项指定组件在开发者工具中呈现的名字。
2.关于组件标签:
第一种写法: <school></ school>
第二种写法:<school/>
备注:不用使用脚手架时,<school/>会导致后续组件不能渲染。
3.一个简写方式:
const school = Vue.extend(options)可简写为: const school = options
底层写了判断他会直接帮你解决
VueComponent构造函数
关于VueComponent:
1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
2.我们只需要写<school/>或<school></school>,Vue解析时会帮我们创建school组件的实例对象,
即Vue帮我们执行的:new VueComponent(options).
3.特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!
4.关于this指向:
(1).组件配置中;
data函数、methods中的函数、watch中的函数、computed中的函数它们的this均是【Vue】
(2).new Vue()配置中:
data函数、methods中的函数、watch中的函数、computed中的函数它们的this均是【Vue】
5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。
Vue的实例对象,以后简称vm。I
原型
1.一个重要的内置关系:VueComponent.prototype._proto_ === Vue.prototype
2.为什么要有这个关系:让组件实例对象_(vc)可以访问到Vue原型上的属性、方法。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5U1ZzdHo-1651137472219)(C:\Users\mht\AppData\Roaming\Typora\typora-user-images\image-20220105202936951.png)]
vue脚手架
npm install -g @vue/cli
vue inspecrt > output.js 把vue脚手架默认配置整理成为.js文件
public 里面的index.html 不支持ie8以下版本
指public目录<%= BASE_URL %>
src
-assets 放静态资源
-components 组件
-main.js 项目入口文件
Vue.config.productionTip = false 关闭vue生产提示
new Vue({
//将App组件放入容器中
render
- 文章目录
- 繁