# code-210322
**Repository Path**: zxfjd3g/code-210322
## Basic Information
- **Project Name**: code-210322
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 6
- **Forks**: 0
- **Created**: 2021-07-05
- **Last Updated**: 2021-12-10
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# day01
## 1. 变量相关问题
```
- 变量到底是什么?
- 可以变化的量, 由变量名和变量值组成, 名称是标识, 值是可以变化的
- 一个变量对应一块小内存, 变量名是这块内存的标识名称, 用于查找这块内存, 变量的值就是内存中保存的数据
- 基本类型变量与引用类型变量的区别是什么?
- 根据变量内存中保存的数据来区分
- 基本类型变量: 内存中保存的基本类型的数据
- 引用类型变量: 内存中保存的是地址值
- 给变量赋值到底做了什么?
- 将基本类型数据赋给变量: 将数据保存在变量内存中
- 将对象赋给变量: 将对象在内存中的地址值保存在变量内存中
- 将另一个变量赋给变量: 将右侧变量内存中的数据(基本数据/地址值数据)拷贝保存到左侧变量内存
- 函数传参, 到底是值传递还是引用传递?
- 函数调用时, 是将实参变量的数据拷贝一份赋值给形参变量
- 只是实参变量数据可能是基本类型, 也可能是引用类型的(地址值)
- 有哪些改变变量值的方式?
- 只能通过赋值改变
- c.m = 2: 改的是c变量指向的对象内部的属性数据, c本身没有变化的(对象内存的位置没变)
- 如何理解下面2句重要的话(编码演示说明)?
- 2个引用变量指向同一个对象, 如果通过一个变量修改对象内部的数据 => 另一个变量也能看到原对象(新数据)
- 2个引用变量指向同一个对象, 让其中一个变量指向一个新的对象 => 另一个引用变量看到的是老的对象
```
## 2. 函数与对象相关重要问题
```
1. 如何理解/证明函数也对象?
- 证明: instanceof 为 true
- 函数有对象的所有特性: 属性与方法
- 可以调用/执行
- 有特有的属性: prototype
- 有特有的方法: call()/apply()/bind()
2. 区别实例对象与函数对象?
- 实例对象: new构造函数产生对象 ==> 简称 对象
- 函数对象: 将函数作为对象使用时称为函数对象
3. 区别方法与属性?
- 方法是一种特别的属性, 特别之处是属性值是函数
- 什么属性才称为方法: 当属性值为函数时我们称之为方法
4. 区别方法与函数?
- 定义在对象中的或通过对象调用的 ==> 方法
- 不是在对象中定义 / 不通过对象调用 ==> 函数
5. 判断是回调函数的3个条件?
- 我们定义的
- 我们没有直接调用
- 在某个时刻或条件下会执行
6. 回调函数需要确定的3个问题?
- 什么时候调用?
- 用来做什么的?
- this是谁?
7. 区别函数的定义和函数的执行
执行函数定义: 创建函数对象/原型对象/函数名变量
执行函数: 执行函数体中的语句
执行函数定义是执行函数的前提
```
## 3. 表达式a.b的内部解析流程
```
1. 查找a变量
沿着作用域链查找, 如果没有找到, 报错: ReferenceError,否则得到变量的值
准备找b属性, 但手里必须要有对象, 得到看a的值
如果是null/undefined ==> TypeError
如果是number/string/boolean ==> 创建对应包装类型对象
引用地址值 ==> 找到对应的对象
2. 查找b属性
先在对象自身上查找, 如果找到了返回它, 如果没有找到, 沿着原型链查找
没有: 返回 undefined
有: 返回它
```
## 4. 原型链内存分析
```js
function Fn () {}
const fn1 = new Fn()
const fn2 = new Fn()
const o1 = new Object()
const o2 = {}
console.log(Fn instanceOf Object)
console.log(Fn instanceof Function)
console.log(Object instanceof Function)
console.log(Object instanceof Object)
console.log(Function instanceof Object)
console.log(Function instanceof Function)
console.log(fn1 instanceof Function)
console.log(Object instanceof Fn)
```

## 5. Git的基本使用
1. 创建本地仓库
1. 配置忽略
2. git init
3. git add .
4. git commit -m "xxxx"
2. 创建远程仓库
1. 指定名称
2. 指定是公开的
3. 将本他仓库的代码推送到远程仓库
1. 关联: git remote add origin gitee上的url
2. 推送: git push origin master
4. 如果本地代码有变化
1. git add .
2. git commit -m "xxxx"
3. git push origin master
5. 如果远程有变化
1. git pull origin master
6. 新来的
1. git clone url
## 6. ES6常用新语法
```
1. let / const / 块作用域
2. 解构赋值: 解构对象或数组
3. 数值扩展: bigint
4. 字符串扩展: 模板字符串 / includes
5. 函数扩展: 箭头函数 / 形参默认值 / rest(剩余)参数
6. 对象扩展: 属性和方法简写, 扩展对象
7. 数组扩展: 扩展数组 / find() / findIndex() / Array.from()
9. 新容器: Map和Set
10. 类语法: class / static / constructor / super / extends
11. 新的异步语法: Promise / aysnc与await
12. 模块化: export / default / import
```
## 7. Promise的基本使用
```
Promise是异步编程的新方案
可以通过其.then的链式调用来解决回调地狱问题
Promise(执行器函数)
Promise的三个状态
pending
fulfilled
rejected
状态只能改变一次
要么是pending ==> fulfilled, 要么是pending ==> rejected
then返回的promise的结果状态如何判断?
简洁表达: 由then指定回调函数的执行结果
详细表达: 4种情况
情况1: 抛出错误 ==> 失败, reason为抛出的错误
情况2: 返回一个失败的promise ==> 失败, reason为就失败的promise的reason
情况3: 返回一个成功的promise ==> 成功, vlaue为就成功的promise的value
情况4: 返回非promise对象值
Promise.all(promises): 只有所有的都成功了才成功, 成功的value为所有成功promise的value组成的数组
只要有一个失败的, 直接失败, reason为失败promise的reason
```
## 8. axios的基本使用
- 测试接口:
- [https://api.github.com/search/users?q=a](https://api.github.com/search/users?q=${value})a
- http://39.98.123.211:8170/admin/acl/index/login
```
请求携带参数的形式? (3种)
1. query参数: url问号的参数
2. params参数: 与路由中的带冒号的路径对应的
3. body参数: 请求体参数(post请求)
http://localhost:8080/user/1?name=tom&age=12
http://localhost:8080/user/3?name=jack&age=13
axios使用XMLHttpRequest和Promise封装的ajax请求库
有一系列发请求的语法:
axios(url)
axios({
url: '', // 路径中可以拼params参数数据, 也可以拼query参数
method: 'POST/GET/PUT/DELETE',
params: {}, // query参数
data: {}, // 请求体参数
})
axios.get(url, {params: {name: 'tom', age: 12}})
axios.post(url, data)
// 添加请求拦截器: 发送请求前执行
axios.interceptors.request.use((config) => {
console.log('请求拦截器执行...', config)
config.headers.token = 'xxxxa123213'
return config
})
// 添加响应拦截器
axios.interceptors.response.use(
response => {
console.log('响应拦截器的成功的回调', response.data)
// return response
return response.data
// return undefined
},
error => {
console.log('响应拦截器失败的回调')
// throw error
return Promise.reject(error)
}
)
```
# day02
## 双向数据绑定与MVVM
- 双向数据绑定 ==> 通过v-model来展现双向数据绑定
- 模板显示能根据data中的数据动态显示 ==> 数据绑定
- 当改变页面输入, 数据会自动更新data中
- MVVM模式
- M: Model 模型, 在vue就是包含可变数据的data对象
- V: View 视图, 在vue就是动态的模板页面
- VM: ViewModel 视图模型, 在vue就是Vue的实例
## 模板
- html + js 动态/模板页面
- 插值: {{expression}} 向标签体中动态插入数据显示
- 指令(directive): vue自定义的以v-开头的一些标签属性
- v-model: 双向数据绑定
- v-bind: 指定动态的属性值
- v-on: 绑定事件监听
## 计算属性与监视
- Object.defineProperty(): 给对象定义属性
- 可以动态计算属性值: getter
- 可以监视属性值的变化: setter
- 计算属性
- 当要显示的值是由已有数据动态计算确定
- getter: fullName () {return 动态值}
- getter/setter: fullName: {get () {}, set() {}}
- 有缓存, 多次读取, 只计算一次, 效率高
- 监视
- 当某个数据变化时, 我们就需要做一些什么操作 ==> 就得用监视
- 基本写法
```
watch: {
// 只有数据发生改变时才调用
firstName (value) {},
firstName: {
handler (value) {},
immediate: true // 在初始时就会调用第一次
}
}
```
- 监视的回调中可以进行异步操作, 但计算属性getter中是不可以
## class与style绑定
- :class="类名字符串": 类名不确定
- :class="{类名1: true/false, 类名2: true/false}": 确定类名, 但不确定有没有
- :style="{样式名: 值, 样式名2: 值}"
## 条件渲染
- v-if / v-else与v-show: 标签结构的显示与隐藏效果
- 实现的本质不同
- v-if直接删除标签来隐藏, 重新显示时需要再创建
- v-show通过样式来隐藏, 重新显示时不需要重新创建, 只需要修改样式
- v-show: 以空间换时间: 占用的空间更大, 但速度会快
- 如果有有频繁的切换, 用v-show相对好些
## 列表渲染
- 使用 v-for 遍历数组
```
{{item.name}}
```
- vue内部如何监视数据变化从而更新页面(数据绑定)
- 对象中的属性
- 通过defineProerty给属性添加getter/setter来实现对属性数据的监视的
- 问题:
- 添加新属性, 界面不会显示
- 直接删除已有属性, 界面不会更新
- 数组中的元素
- 对数组中用于更新元素的一系列方法进行重写
- 调用数组原生的对应方法去更新元素
- 更新界面
- push/pop/shift/unshift/splice/sort/reverse
- 有限制: 只能通过重写的几个数组方法来更新元素, 如果直接通过下标更新元素界面不会更新
- 直接更新length属性, 界面不会变化
# day03
## 事件处理
```
1. 绑定监听:
v-on:xxx="fun"
@xxx="fun"
@xxx="fun(参数)"
默认事件形参: event
隐含属性对象: $event
2. 事件修饰符:
.prevent: 阻止事件的默认行为 event.preventDefault()
.stop: 停止事件冒泡 event.stopPropagation()
.once: 事件只响应一次
3. 按键修饰符
.keycode: 操作的是某个keycode值的健
.enter: 操作的是enter键
```
## 表单数据收集
```
1. 使用v-model自动收集表单项输入数据
2. @submit.prevent 来监听表单提交并阻止表单自动提交
```
## vm/组件对象的生命周期
```
1. vue对象的生命周期
1). 初始化显示
* beforeCreate(): 不能通过this访问data中的数据和methods中的方法
* created(): 可以通过this访问data中的数据和methods中的方法
* beforeMount(): 不能通过ref得到标签对象
* mounted(): 可以通过ref得到标签对象
2). 更新状态: this.xxx = value
* beforeUpdate(): 通过ref得到是老的界面标签
* updated(): 通过ref得到的是新的界面标签
3). 销毁vue实例: vm.$destory()
* beforeDestory()
* destoryed()
2. 常用的生命周期方法
created()/mounted(): 发送ajax请求, 启动定时器等异步任务
beforeDestory(): 做收尾工作, 如: 清除定时器
```
## 过渡&动画
```
1. vue动画的理解
操作css的trasition或animation
vue会给目标元素添加/移除特定的class
2. 基本过渡动画的编码
1). 在目标元素外包裹
2). 定义class样式
1>. 指定过渡样式: transition
2>. 指定隐藏时的样式: opacity/其它
3. 过渡的类名
xxx-enter-active: 指定显示的transition
xxx-leave-active: 指定隐藏的transition
xxx-enter: 指定隐藏时的样式
xxx-leave-to: 指定隐藏时的样式
```
## 自定义过滤器
```
1. 理解过滤器
功能: 对要显示的数据进行特定格式化后再显示
注意: 并没有改变原本的数据, 可是产生新的对应的数据
2. 编码
1). 定义过滤器
Vue.filter(filterName, function(value[,arg1,arg2,...]){
// 进行一定的数据处理
return newValue
})
2). 使用过滤器
{{myData | filterName}}
{{myData | filterName(arg)}}
3. 日期处理工具库
moment
dayjs: 更小
moment/daysj(time).format(格式字符串)
```
## 指令
```
1. 内置指令
v-text : 更新元素的 textContent
v-html : 更新元素的 innerHTML
v-if : 如果为true, 当前标签才会输出到页面
v-else: 如果为false, 当前标签才会输出到页面
v-show : 通过控制display样式来控制显示/隐藏
v-for : 遍历数组/对象
v-on : 绑定事件监听, 一般简写为@
v-bind : 强制绑定解析表达式, 可以省略v-bind
v-model : 双向数据绑定
2. 自定义指令
1. 注册全局指令
Vue.directive('my-directive', function(el, binding){
el.innerHTML = binding.value.toupperCase()
})
2. 注册局部指令
directives : {
'my-directive': function(el, binding) {
el.innerHTML = binding.value.toupperCase()
}
}
3. 使用指令
v-my-directive='xxx'
```
## 插件的定义的使用
```
1. 自定义vue插件
1) 如果插件是对象, 对象必须要有一个install
2) 如果插件是函数, 将这个函数当作install方法对待
2. 使用插件
引入插件包
声明使用插件: Vue.use(插件)
```
## 列表key问题
```
面试题:
1). react/vue中的key的作用/内部原理
2). 为什么列表的key尽量不要用index
1. 虚拟DOM的key的作用?
1). 简单的说: key是虚拟DOM对象的标识, 在更新显示时key起着极其重要的作用
2). 详细的说: 当列表数组中的数据发生变化生成新的虚拟DOM后, React进行新旧虚拟DOM的diff比较
a. 能找到对应的key
item数据没变, 直接使用原来的真实DOM
item数据变了, 对原来的真实DOM进行数据更新
b. 没有对应的key
根据item数据创建新的真实DOM显示
2. key为index的问题
1). 添加/删除/排序 => 产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低
2). 如果item界面还有输入框 => 产生错误的真实DOM更新 ==> 界面有问题
注意: 如果不存在添加/删除/排序操作, 用index没有问题
3. 解决:
使用item数据的标识数据作为key, 比如id属性值
```
## 组件的定义和使用
```
1. 定义组件
Vue.component('组件标签名', {
data () { // 指定内部可变数据
return {
count: 0
}
},
props: ['title'] // 指定外部传入的可变数据
template: '{{title}}--{{count}}
'
})
2. 使用组件
<组件标签名 :title="xxx">组件标签名>
3. 组件的data只能是函数, 不能对象
原则: 一个组件的多个标签实例不能共用一个data对象
如果data配置的是对象, 那就会导致多个标签共用一个data对象 ==> 有问题
如果data配置是函数, 函数调用每次都返回一个新的data对象, 每个标签都是自己的data对象 ==> 可以
```
# day04
## 使用vue脚手架创建项目
```
npm i -g @vue/cli yarn: 全局下载脚手架包和yarn (后面创建项目内部要使用)
vue create vue-component: 以纯命令的方式创建项目
vue ui: 以图形界面的方式创建项目
yarn serve: 启动
npm install -g @vue/cli-init: 下载2.x的脚手架包
vue init webpack my-project: 创建项目
3/4脚手架与2脚手架的最大区别:
2的项目的webpack配置是暴露 ==> 可以直接修改, 但也容易改得不好
3/4项目的webpack配置是隐藏 ==> 如果需要修改webpack配置, 在vue.config.js中编写(由脚手架来定)
```
## 打包运行项目的2种方式
```
1. 开发环境运行
命令: yarn serve
本质:
1. 在内存中打包(编译)生成打包文件
2. 启动服务器运行项目
2. 生产环境打包运行
命令:
打包: yarn build
下载服务器包: npm i -g serve
运行: serve dist
本质:
1. 在内存中打包(编译)生成打包文件
2. 将内存中的打包文件保存到本地
3. 将本地打包加载中内存中
4. 启动服务器运行项目
```
## 单文件组件的定义与使用
```
1. 定义组件: xxx.vue
2. 使用组件
引入
注册
组件标签
3. 创建vm
new Vue(
render: h => h(App) // 根据指定的App组件创建组件实例对象, 并渲染到页面
).$mount('#app')
```
# day05
## 组件化编码的基本流程
```
1. 静态页面
2. 拆分界面组件
App
Header
List
Item
Footer
3. 实现静态组件页面
4. 实现动态组件
初始化数据动态显示
设计初始化数据
将数据在当前组件或通过props传递后代组件显示
交互:
Header: 添加
Item: 移入移出 / 删除 / 勾选
Footer: 显示 / 全选 / 删除所有勾选的
设计初始化数据
数据结构: [{id, title, completed}]
名称(根据数据意义来取名): todos
位置( 保存在哪个组件):
看是哪个组件使用?: 交给它
还是哪些组件使用?: 交给它们共同的父组件 ==> App
```
## props使用深入
```
1. 在父组件中可以通过标签属性向子组件传入数据
2. 在子组件中需要通过props配置声明接收属性数据
写法1: 只指定属性名
props: ['name', 'myAge']
写法2: 指定属性名和类型
props: {
name: String,
myAge: Number
}
写法3: 指定属性名, 类型, 必要性, 默认值, 校验
props: {
name: {
type: String,
required: true
},
myAge: {
type: Number,
default: 0,
validator (value) {
return value >=0
}
}
}
3. 标签名与属性名写法
完全一样
大写变小写, 中间用-连接
标签名不要与原生标签名重名
```
## 通过props实现父子间相互通信
```
1. 父向子
父组件: 向子组件标签传入标签属性 ==> 属性值必须是非函数
子组件: 通过props声明揽收, 读取属性数据显示
2. 子向父
父组件: 向子组件标签传入标签属性 ==> 属性值是函数 (函数在父组件中)
子组件: 通过props声明揽收, 调用传入的函数, 可以传入参数数据, 数据就从子组件传到了父组件中
3. 问题:
祖孙组件间通信比较麻烦: 必须逐层传递
兄弟组件间通信比较麻烦: 借助父组件传递
```
## 相关问题
```
移入移出的事件监听
mouseenter与mouseleave: 进入子元素不会触发leave
mouseover与mouseout: 进入子元素会触发out
查看问题的基本流程
看有没有报错 ===> 控制台
看数据 ==> vue调试工具
看元素及样式 ==> 检查元素及对应的样式
查看代码
组件化编码的基本原则
数据在哪个组件, 修改/更新数据的函数就应该定义在哪个组件, 其它组件如果要更新这个数据, 只能是想办法调用更新函数来更新这个数据
组件不要直接去修改props中的数据
```
## 功能: 关闭浏览再打开访问还能看到最后的样子
```
存储数据:
存储哪个数据? todos
什么时候保存? 总是保存最新的数据 ==> 对todos进行深度监视, 在监视的回调中保存
保存在哪里? localStorage
读取数据
什么时候读取: 初始化时就读
```
# day06
## 组件间通信1: props
```
props: 实现父子组件间通信
父向子通信: 非函数props
子向父通信: 函数props
不足:
1. 祖孙组件: 必须逐层传递 ==> 麻烦
2. 兄弟组件: 必须借助父组件 ==> 麻烦
```
## 组件间通信2: Vue自定义事件
```
Vue自定义事件实现: 子向父通信 ==> 用来替代函数props
1. 原生DOM事件
1) 绑定事件监听