# vue-cli-0822 **Repository Path**: huanghe01/vue-cli-0822 ## Basic Information - **Project Name**: vue-cli-0822 - **Description**: vue-cli-0822vue-cli-0822vue-cli-0822vue-cli-0822vue-cli-0822 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2022-12-26 - **Last Updated**: 2023-01-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Vue2 课堂笔记 ## 每日彩蛋 1. 说明 `a = b = c = d = 1;`的执行过程 - 查阅MDN的运算符优先级文档,找到赋值(=)运算符,发现多个=在一个表达式中是从右向左执行的 - `c=d=1`是先执行`d=1`,然后把`d=1`的返回值赋值给c - 赋值(=)操作符的返回值:返回=右侧的值,所以`d=1`返回1,然后把1再赋值给c - 后边依次类推 2. `for(var i = 0,j = 0; i < 5, j < 10; i++,j++){语句}` 请问当前for循环的循环次数??为什么 - 首先直到for循环是否能够向下继续循环,只要看for中的判断式 - 判断式是多个,由逗号运算符间隔开,我们就要考虑逗号运算符的返回值 - 逗号运算符如果出现多个,则从左向右执行,并返回逗号右侧的值 - 所以当前的循环主要看j的次数来决定整个循环的次数 3. 代码题:请得到7天以后的现在的时间 - 方式1 ```js //1. 获取当前的时间 new Date(); //2. 获取当前时间的日期 new Date().getDate(); //3. 获取目标时间的日期 new Date().getDate() + 7; //4. 获取当前的时间,把日期修改为目标日期 new Date().setDate(new Date().getDate() + 7); ``` - 方式2 ```js //1. 得到7天以后的时间戳 Date.now() + 1000 * 60 * 60 * 24 * 7; //2.创建一个时间,把7天以后的时间戳交给参数 new Date(Date.now() + 1000 * 60 * 60 * 24 * 7); ``` 4. 代码题:'abaabgfdebbafefgefsrsbabesseeeeaa' 请计算每一个字母出现的次数,及出现最多次数的字母 ```js const str = "abaabgfdebbaefefgfsrsbabesseeeeaa"; //1.创建一个对象,用来保存每一个字符出现的次数 const obj = {}; //2. 遍历字符串的每一个字符,然后去对象中判断,如果对象中不存在,则给对象新增一个属性默认值为1,如果对象存在,则把对象的值+1 for (let key of str) { obj[key] ? obj[key]++ : (obj[key] = 1); } console.log(obj); //3. 先初始化一个值用来保存出现最多的key,再初始化一个值用来保存出现最多key的次数 let bigStr = ""; let bigStrNum = 0; //4. 遍历对象,一个的判断 for (let key in obj) { //如果当前遍历出的新值的次数 大于目前保存的次数,那你牛逼,我们跟你 if (obj[key] > bigStrNum) { bigStr = key; bigStrNum = obj[key]; } } console.log(bigStr, bigStrNum); ``` 5. 让一个字符串的首字母大写,比如 "hello every one"--->"Hello every one" 6. 让一个字符串所有单词的首字母大写,比如"hello every one"--->"Hello Every One" 7. 数组去重的方法(3种) 8. 封装一个myNew函数实现new操作符,如下,让p1和p2有一样的效果 ```js function Person(name,age){ this.name = name; this.age = age; } Person.prototype.do = function(){} //原始new const p1 = new Person("xiaowang",18); //手动封装new const p2 = myNew(Person,"xiaowang",18); ``` 9. 让一个不定宽高的元素在容器中水平垂直居中的方式(3种方式) 10. 给按钮绑定点击事件,频繁点击按钮时让事件最少间隔1s才能触发一次(节流),并且封装通用函数 11. 什么是事件流(事件机制) - 事件冒泡:事件从最精确的元素(target)开始向最不精确的元素(document)依次传播 - 事件捕获:事件从最不精确的元素(document)开始向最精确的元素(target)依次传播 - W3C事件流: 当事件触发,先执行捕获过程 再执行目标元素的事件(target) 在执行冒泡过程 12. 在输入框输入内容后,等待1s后发送请求,如果1s内输入框内容改变了,则重新等待1s(防抖) 13. 我们要拷贝一个对象(深拷贝和浅拷贝)的做法 14. 整理HTML5新特性有哪些 * 语义性标签,header\footer\nav\aticle\section * 增强表单,input的多种type类型(tel\month\email\number\color.....) * 音频视频 * WebWorker:开启多线程 * WebStorage:本地存储 * WebSocket:是一种通信协议 * Canvas:画布 15. 整理CSS3新特性有哪些 * 选择器 * 边框,阴影,背景,渐变 * 变形 * 过渡动画 * 关键帧动画 * flex * @media媒体查询 16. 整理ES6新特性有哪些 * let和const * 解构赋值 * 新增数据类型(symbol,bigint) * 新增的数据结构(map,set) * iterator接口(for..of..,解构,扩展运算符原理) * promise/async/await * class类 * es6模块化 * 新增的对象字符串等方法 17. 用css画一个三角形 18. 描述undefined和null的区别????? * null代表空,undefined代表的是找不到 * undefined出现的场景 - 声明一个变量没有赋值,则变量值是undefined - 获取一个对象没有的属性时,则值是undefined - 函数没有return值,则函数的返回值就是undefined - 函数的形参没有被赋值,则这个形参的值是undefined * null出现的场景 - 原型链的终点是null(防止原型链死循环) - 声明变量此时不想赋值,可以先赋值为null - 调用函数传参占位 - 把一个对象的引用移除,把这个对象变成垃圾对象 19. 已知一个网页地址`http://www.baidu.com?a=1&b=2&c=3`,请封装一个方法提炼出这个地址中的参数,并以对象形式返回{a:1,b:2,c:3} 20. 封装一个扁平化数组的函数(flat),[1,[2,[3,4],5],6]====>[1,2,3,4,5,6] 21. 封装一个函数,求数组的交集,[1,2,3,4],[2,3,5,6]===>[2,3] 22. 封装一个函数,接收一个数字作为参数,检查它是不是4的次方数,如果是则返回true,否则返回false(进阶:不使用递归) 23. 后台给了一组数据,但是这组数据不是我们想要的 ```js const obj = [ {id:3,parent:2}, {id:1,parent:null}, {id:2,parent:1} {id:4,parent:1} ] ``` 把这个数据转为我们需要的格式 ```js const result = { id:1, parent:null, children:[ { id:2, parent:1, children:[ { id:3, parent:2 } ] }, { id:4, parent:1 } ] } ``` 24. 浏览器的事件轮询机制 * js代码分为了同步代码和异步代码 * 其中异步代码又分为了宏任务和微任务 - 宏任务:整体的script,定时器,ajax,事件 - 微任务:Promise.then/catch/finally async/await * js执行代码的顺序:先执行异步(整体的script)-->再执行同步--->再执行异步 * 事件轮询机制的过程 - js执行主线程同步代码 - js遇到宏任务会把宏任务交给浏览器的对应的管理模块(其实就是浏览器开启的多线程) - js遇到微任务,会把微任务的回调函数直接放在微任务的回调队列中 - 当浏览器的管理模块中的异步需要被执行的时候,就会把回调函数放在宏任务回调队列中 - 当js主线程的同步代码执行完毕的以后,会先清空微任务队列,然后再去执行宏任务队列中的回调 - 当每次执行完一个宏任务的时候,都会去再次清空微任务队列 - 轮询检测宏任务队列中是否有代码需要执行 25. 执行上下文 * JS引擎并不是一行行的解析和执行代码,而是一段段的去分析和执行,当执行一段代码时,先开始做一些准备工作(1:开辟一块内存空间 2:创建变量对象(VO) 3:确定作用域链 4:确定this指向),这个准备工作被称作为执行上下文 * js可执行的代码段分为2种类型: 全局代码 、 函数代码 * 每执行一段代码,都会创建相对应的执行上下文,在脚本中可能存在多个执行上下文,因为有太多的执行上下文, JS创建了一个执行上下文栈(stack) 用来管理执行上下文 * 当js开始解析程序的时候,最先遇到的全局代码,此时向执行上下文栈中 压入一个全局执行上下文,全局的一定是在整体运行结束以后(页面关闭)才被清空 * 当执行一个函数的时候 会创建一个函数的执行上下文,并压入到执行上下文栈中,只要函数执行完成,会将函数从栈里弹出 26. 变量对象(声明提升的原理): * 变量对象是 ECMAScript规范术语。在一个执行上下文中,变量对象才被激活 * 变量对象是储存了在上下文中定义的形参,实参,变量和函数声明 * 全局执行上下文的变量对象其实就是全局对象window,因为全局的变量和函数都是window对象的属性和方法 * 每次进入一个函数的的时候会创建对应的执行上下文,执行上下文的第一步就是创建变量对象(VO),收集所有形参,实参,变量声明和函数声明 - 先收集所有的形参和实参 - 再检查所有声明的函数,如果变量对象已经有相同名字的属性,则完全替换 - 检查所有的声明的变量,变成变量对象的属性,值是undefined,如果变量名和已经声明的形参或函数相同,则变量声明不会干扰已经存在的这类属性 27. 作用域链 * 作用域链的用途,是保证对 执行环境有权访问的所有变量和函数 的有序访问 * 作用域链是在当前函数被声明的时候,就已经产生了,但是没有最前端当前函数的变量对象 * 函数执行的时候会创建自己的变量对象,并把自己的变量对象推入该作用域链的前端形成完整的作用域链 * 作用域链的前端,始终都是当前执行的代码所在环境的变量对象。全局执行环境的变量对象window始终都是作用域链中的最后一个对象。 * 标识符解析是沿着作用域链一级一级地搜索标识符的过程。搜索过程始终从作用域链的前端开始,然后逐级地向后回溯,直至找到标识符为止(如果到window还找不到标识符,如果是查询值通常会导致错误发生) 28. this指向 * 先判断当前函数是否是call/apply/bind调用,如果是,则指向强制绑定的那个值 * 判断当前函数是否是被new实例化调用,如果是,则可能指向实例化对象,也可能指向构造函数的返回的对象类型 * 判断当前函数是否是被一个上下文对象调用,如果是则指向上下文对象(注意隐式丢失的情况 var fn = o.fn; o.fn = o1.fn) * 函数默认调用,this指向window * 严格模式下,如果某个函数没有调用者,则内部的this指向undefined * 箭头函数没有自己的this,需要沿着作用域链去上一级函数查询this ## 复习--git - 01.git 操作复习 1. 初始化本地仓库(`git init`) 2. 本地仓库提交(`git add . `, `git commit -m 'init/add/fixed/docs:xxxxxx'`) 3. 新建远程仓库,拿到远程仓库的ssh地址 4. 把本地仓库和远程仓库关联(`git remote add origin xxxxxxxxx`) 5. 把本地仓库向远程仓库提交(第一次:`git push -u origin master`,第二次:`git push`) 6. 去到当前仓库中的管理页面,把当前项目设置为开源 7. 拉取其他人代码(`git clone xxxx`||`git pull`) 8. 撤销工作区的改动(`git restore .`) 9. 取消远程仓库的关联(`git remote remove origin`) - 02.免密登录的配置 1. 配置本地git用户名和gitee的用户名一致:`git config --global user.name "username"` 2. 配置本地git邮箱和gitee的邮箱一致:`git config --global user.email "email"` 3. 在任意命令行位置书写`ssh-keygen`,生成秘钥,拿到公钥的地址 4. 用记事本打开公钥文件,复制里边内容 5. 去gitee的公钥配置中,添加公钥,即可使用ssh免密操作 ## Vue学习需要使用的插件 - vscode的vue2插件: * Vetur -- Pine Wu * Vue 3 Snippets----hollowtree * vue-helper --- shenjiaolong - 其他插件: * vscode-icons 文件列表图标插件 * Prettier - Code formatter 格式化插件 ## Vue基础概念 1. MVVM模型 * MVVM(Model-View-ViewModel)是一种软件架构设计模式 * MVVM分为三个部分:分别是M(Model,模型层 ),V(View,视图层),VM(ViewModel,视图数据层,V与M连接的桥梁,也可以看作为控制器) + M:模型层,值得是数据模型,主要负责业务数据相关; + V:视图层,顾名思义,负责视图相关,细分下来就是html+css层,为了更方便的展示Model层的数据; + VM:V与M沟通的桥梁,负责监听M或者V的修改,是实现MVVM双向绑定的要点 * ViewModel是Vue.js的核心,它是一个Vue实例,MVVM支持双向绑定,意思就是当M层数据进行修改时,VM层会监测到变化,并且通知V层进行相应的修改,反之修改V层则会通知M层数据进行修改 2. new Vue(options)中基础配置项 * el:配置项,代表当前vue实例要挂载的容器,可以是一个选择器的字符串,也可以是已经获取的DOM元素 * template:配置项,一个字符串模板。模板将会替换容器 * data:Vue 实例的数据对象 3. $mount挂载 * 如果 Vue 实例在实例化时没有收到 el 选项,则它处于“未挂载”状态,没有关联的 DOM 元素。 * 可以使用 vm.$mount() 手动地挂载一个未挂载的实例。 * 接受的参数可以是选择器string,也可以是一个获取的DOM元素,作为容器 * 我们可以使用$mount进行异步挂载 4. 模板的语法糖写法 * 容器内部也可以进行书写模板,切记不是DOM,而是模板 * 在vue实例化过程中,如果选项中存在template选项,则把template选项的内容作为模板替换容器 * 如果选项中不存在template,则把容器的outerHTML作为模板 5. data配置项详解 * data可以是一个对象,是Vue实例的数据对象 * data的数据会在实例对象vm上作为属性存放起来 * data也可以是一个函数,返回一个对象,对象中存放当前实例需要的数据,并且建议是一个函数 * 为什么组件内的data要书写为一个函数???? 01. 当一个组件被定义,data 必须声明为返回一个初始数据对象的函数 02. 因为组件可能被用来创建多个实例(组件可能被复用)。 03. 如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!则数据就会互相影响 04. 通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象。 6. 插值语法注意事项: * 插值语法中的变量都是从当前的vm对象上去寻找的 * 插值语法中可以书写任意表达式(由一个或者多个变量或值 配合0个或多个运算符组成的 被称作为表达式,表达式都会有返回值),不能书写语句 * 插值的变量可以是任意类型的,按照一定的规则转为字符串展示(Symbol除外) ## 指令系统 ### 01. 什么是指令 * 指令 (Directives) 是带有 v- 前缀的特殊 attribute。指令 attribute 的值预期是单个 JavaScript 表达式 (插值语法区域)。 * 指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM ### v-bind 1. v-bind的基础使用 * 模板中的属性值默认都是字符串格式的!!! * 如果希望属性值的区域是一个插值语法区域,我们就可以使用v-bind指令 * v-bind:强制绑定(动态绑定):把一个模板中属性的值区域变成插值语法区域,在插值语法区域中可以执行表达式,也可以去实例上拿值 * v-bind可以直接简写为 `:` * 在v-bind中我们经常的去拼接一些值,方法如下 01. `` 02. `` 2. v-bind动态类的设置 * 什么时候使用动态类?当类名是通过数据来控制是否添加的时候,才会使用动态类 * 情况1-字符串:当动态类只有一个类的时候,我们可以直接使用三元等表达式,返回一个字符串即可 * 情况2-对象:当动态类的类有一个或者多个的时候(固定个数),我们可以给动态类设置一个对象,每一个类名都是对象的key,值是一个布尔值代表是否开启当前的类 * 情况3-数组:当动态类的类有一个或多个,不确定数量的时候,可以使用数组,只要在数组中的类都会添加到DOM上,不能开启和关闭,但是可以操作数组来控制类 3. v-bind动态style的设置 * v-bind可以使用动态的style控制元素的样式 * 动态的style可以接受一个对象,对象的key就是style的属性,对象的值就是style的值,对象的值可以使用插值来进行实现 * 动态类style可以接受一个数组,数组中可以包含多个动态类对象 4. 批量强制绑定 * 很多时候我们需要把对象中的属性一个个的绑定在元素或者组件上,我们可以使用批量绑定 * v-bind批量绑定 直接使用 v-bind="需要展开的对象名即可",此种写法不能简写 ### v-on 事件绑定 1. 事件的书写和methods选项 * 使用v-on执行给模板绑定原生事件 `` * 事件函数写在哪里? - 原则上来说,在data中书写函数,并且是箭头函数,函数内的this是指向当前的vue实例对象,但是一旦写成了普通函数,则this指向全局window,严格模式下会指向null,都不是我们想要的,但是我们不会把函数书写在data中,1.必须书写箭头函数 2.函数和数据混杂在一起不容易维护(data就是为了写数据的) - methods选项中用来书写方法,比如事件回调函数,也有我们自己封装的函数等。methods中的方法已经被vue统一处理过了,vue控制methods中所有的方法的this指向当前的vue实例,为什么要把methods方法的this指向vm实例呢?因为方法一般都是用来操作数据的,而数据都在vm实例上放 * methods中的方法也会全部的放在vm实例上,供我们使用 2. event事件对象的获取 * 默认事件函数接收的第一个参数就是event事件对象(js的event对象),我们可以直接接收使用 * e.target就能获取当前事件所在的元素(真实DOM) * 当事件函数传递参数的时候,则事件函数的第一个参数不再默认是event事件对象了,在事件指令的插值语法区域,默认存在着一个变量$event代表的就是当前事件的event事件对象,如果传参的事件函数需要event事件对象,我们可以直接把$event显性的传递进事件函数中 3. 事件函数的传参 * 如果想要给事件函数传递参数,则在绑定事件函数的时候,直接书写参数即可 * 在代码运行的时候,只要我们不触发事件,事件属性值的内容是不会有任何执行的 * 当事件触发以后,事件属性值内部的代码才会触发执行,并直接传入的参数 4. 事件逻辑的简单写法 * 如果事件的逻辑很简单,只是简单的一句操作数据,则可以不用书写函数,直接把逻辑写在事件的插值中即可 5. 事件修饰符 * 修饰符是对某条指令的补充 * .stop:阻止事件传播 * .capture:让当前的事件在捕获的阶段执行 * .prevent:阻止默认事件 * .self:只有事件真正发生在自己身上的时候才会触发 * .once:一次性事件 * .enter:按键修饰符-回车键 * ... 其他按钮修饰符 ### v-model数据双向绑定 1. v-model的基础使用 * v-model 指令在表单