vue 前期知识点
day1
MVC 概念
MVC 是一种分层开发模式, 让业务更加清晰, 并不会减少业代码量, 可能会更多, 减少模块的耦合度
MVC 是站在整个项目的角度对项目进行分层
1.M(数据连接层 --- 数据库)
2.V(视图层)-- 前端页面
3.C(业务层 ---- 路由那一块)
cookie 和 session
cookie 存在客户端, 安全性很低
session 存在服务端, 里面也使用了 cookie, 安全性较高, 数据也不容易丢失.
框架和库的区别
+ 框架: 是一套完整的解决方案, 对项目的侵入性较大, 项目如果需要更换框架, 那就需要重新架构整个项目.
+ 库: 提供某一个功能, 对项目侵入较小, 在项目中也容易切换库进行开发.
MVVM 的理解
相当于 MVC 模式中的 V 层, 把 V 层分层了 MVVM 三层, 在请求 - 处理 - 响应中, 也就是 V 层 - C 层 - M 层(大致).
MVVM 是前端视图层的分层开发思想, 主要把每个页面分层 M/V/VM, 其中 VM 是 MVVM 思想的核心, 它是 M 和 V 之间的调度者. VM 提供了数据的双向绑定.
M --- 保持的是每个页面中单独的数据
V --- 视图, 也就是页面的 html 结构.
VM -- M 渲染到 V 层 需要 VM 的调度, V 到 M 也需要 VM 的调度.
注意点
+ 在函数内要注意 this 的指向, 比如定时器之类的, 有时可以使用箭头函数.
什么是 vue.js
16 年底火了起来
是一套构建用户界面的框架, 只关注视图层, 可以和其他类库整合.
vue 语法可以进行手机 App 开发, 需要借助 weex.
用户不在操作 DOM 元素, 双向数据的绑定, 程序员只需要关心数据的业务逻辑, 以及组件系统.
目前最火的前端框架
引入 MVVM 设计模式
简单, 轻量, 快捷的快捷
单页面应用(spa)
单页面应用(SinglePage web Application,SPA)--- 多页面应用(MultiPage Application,MPA)
组成 ---- 一个外壳页面和多个页面片段组成 ------------------- 多个完整页面构成
资源共用(CSS,JS)----- 共用, 只需在外壳部分加载 ------------------- 不共用, 每个页面都需要加载
刷新方式 ---- 页面局部刷新或更改 ------------------- 整页刷新
url 模式 ---- http://a.com/#/pageone http://a.com/#/pagetwo ------------------- http://a.com/pageone.html http://a.com/pagetwo.html
用户体验 ---- 页面片段间的切换快, 用户体验良好 ------------------- 页面切换加载缓慢, 流畅度不够, 用户体验比较差
转场动画 ---- 容易实现 ------------------- 无法实现
数据传递 ---- 容易 ------------------- 依赖 url 传参, 或者 cookie ,localStorage 等
搜索引擎优化 (SEO)---- 需要单独方案, 实现较为困难, 不利于 SEO 检索 可利用服务器端渲染(SSR) 优化 ------------------- 实现方法简易
试用范围 ---- 高要求的体验度, 追求界面流畅的应用 ------------------- 适用于追求高度支持搜索引擎的应用
开发成本 ---- 较高, 常需借助专业的框架 ------------------- 较低 , 但页面重复代码多
维护成本 ---- 相对容易 ------------------- 相对复杂
vue 的指令
v-cloak 和{{}} 插值表达式
在插值表达式里 网速比较慢的时候, vue 包还没有加载完成的时候会在页面显示{{msg}}, 加载完了后才渲染出数据, 就会产生闪烁问题. 此时需要在 CSS 中写 [v-cloak] {display:none}, 切插值的元素写 v-cloak 属性.
实现原理 1: 通过[v-cloak] 给指定的元素执行添加 隐藏样式 2: 当 vue 引入完毕, 则把此属性删除掉
v-text 和 v-HTML
v-text: 解析成字符串, 没有闪烁问题但会覆盖原来的文本内容
v-HTML: 可以解析 HTML 标签, 没有闪烁问题但会覆盖原来的文本内容
v-bind,v-on
v-bind: 可以直接简写成 : , 且 v-bind 可以写合法的 JS 代码及表达式
只能实现数据的单向绑定, 从 M 到 V 层.
v-model 数据的双向绑定
针对表单元素 Input,select,checkbox 以及还有组件上 component 等等, 可以和用户进行交互.
vue 中唯一一个双向数据绑定的指令.
v-for 的使用
循环数组 v-for="item in arr" --- "(val,i) in arr"
循环对象
迭代数字 v-for="count in 10" -----count 从 1 开始
要保证循环每一项的唯一性, M 和 V 层的一一对应, 需要添加 :key 属性.
key 且必须是一个 string/number 的类型数据, 数据也要保证唯一性. index 的值不建议作为 key 值.
- v-if,v-show,v-else
- v-if
直接删除, 为 true 则需要重绘, DOM 操作
v-show
类似于 display: none; 切换比较频繁的可以使用 v-show
事件的修饰符
.stop ------- 阻止事件冒泡
.prevent ---- 阻止默认行为.<a href="http://baidu.com" @click.prevent="add">
.capture(捕获机制)----- .once(只执行一次)------.self(只执行自己) - 事件修饰符可以连用
vue 中设置 class 类, 使用 v-bind 进行属性绑定
数组的形式
属性绑定的形式
数组中添加三元表达式
数组中对象来代替三元表达式
属性绑定的形式, 在 data 中定义 flag 布尔值
对象的形式
day2
在 Vue 中只需要关注数据的改变, 而无需关心 DOM 操作. 在 Vue 中已经实现了数据的双休绑定, 每当我们修改 data 的数据时, 就会自动监听数据的变化, 应用到页面上.
过滤器
用作常见的文本格式化
用在差值表达式 {{}} 和 v-bind 属性里
语法: 1.
定义全局的过滤器
{{ name | 过滤器名称}}
Vue.filter('过滤器的名称',function(data){ })
可以多次调用过滤器, 一直 | (管道符)下去
定义 vue 实例的私有过滤器
在 Vue 实例里, 写 filters: {}
使用的时候以查找私有过滤器为先, 没有则查找全局过滤器.
填充字符串
- padStart(length,str)
- padEnd(length,str)
按键修饰符
vue 自带的修饰符
enter -- 键盘码相当于 13
- table
- up
- down
- ....
键盘码
用法: @keyup.enter = "function" 或者 @keyup.13 = "add" -------
自定义键盘修饰符
- Vue.config.keyCodes.enter = 13; // 两者一一对应
- @keyup.enter = "function"
指令的自定义 ---- 类似于 v-focus(系统没有这个指令)
注: 在 Vue2.0 中, 代码复用和抽象的主要形式是组件. 然而, 有的情况下, 你仍然需要对普通 DOM 元素进行底层操作, 这时候就会用到自定义指令. 1. 定义全局的指令 // 定义的时候, 指令的名称前面, 不需要加 v- 前缀. 在调用的时候, 必须在名称前添加 v- 前缀来进行调用. // 其中: 参数 1 是指令的名称. // 参数 2 是一个对象包裹的钩子函数.
- Vue.directive('focus',{
- // 注意: 在每一个函数中, 第一个参数只能是 el , 表示被绑定的元素的原生的 JS 对象, 可以进行 DOM 操作.
- bind: function(el){
- },// 表示指令绑定到元素上的时候, 会立即执行 bind 函数, 只执行一次. bind 表示还没有挂载到 DOM 树上去. 故有些方法建议在 inserted 函数上调用. // 样式操作, 在这里进行.
- inserted: function(){
- }, // 表示元素插入到 DOM 中的时候, 会执行此函数, 只执行一次. // JS 操作在这里
- updated: function(){
- },
- })
生命周期函数
从 Vue 实例创建, 运行, 到销毁期间, 总是伴随各种各样的事件, 这些事件(函数), 统称为生命周期
创建期间的生命周期函数:
beforeCreate: 实例刚在内存中被创建出来, 此时, 还没有初始化好 data 和 methods 属性
created: 实例已经在内存中创建 OK, 此时 data 和 methods 已经创建 OK, 此时还没有开始 编译模板.
可以在这里获取 Ajax 数据.
beforeMount: 此时已经完成了模板的编译, 但是还没有挂载到页面中
mounted: 此时, 已经将编译好的模板, 挂载到了页面指定的容器中显示. 是 Vue 实例创建的最后一个函数, 实例也即将进入运行阶段.
最早此处可以进行 DOM 操作
运行期间的生命周期函数:
beforeUpdate: 状态更新之前执行此函数, 此时 data 中的状态值是最新的, 但是界面上显示的 数据还是旧的, 因为此时还没有开始重新渲染 DOM 节点
updated: 实例更新完毕之后调用此函数, 此时 data 中的状态值 和 界面上显示的数据, 都已经完成了更新, 界面已经被重新渲染好了!
销毁期间的生命周期函数:
beforeDestroy: 实例销毁之前调用. 在这一步, 实例仍然完全可用.
destroyed:Vue 实例销毁后调用. 调用后, Vue 实例指示的所有东西都会解绑定, 所有的事件监听器会被移除, 所有的子实例也会被销毁.
vue-resource vue 里面的请求数据
.then()------- 后面第一个参数为成功的回调函数, 第二个为失败的回调函数(失败的可以省略).
通过 result.body 拿到请求的数据.
手动发起的 POST 请求, 默认没有表单格式, 即没有设置 application/x-www-form-urlencoded, 有的服务器处理不了. 需要重新设置 {emulateJSON: true}
day3
vue 动画
使用 transition 设置动画, 把需要动画的元素包裹起来. // //
{{ 这是需要动画的元素, 需要被 transition 包裹起来 }}
//
v-enter 表示一个时间点, 是进入之前元素的起始状态
v-leave-to 表示终止状态.
且包含的 元素(h3) 支持显示隐藏.
在 transition 标签里面添加 name 属性可以把 V- 前缀换成自己定义的. v-enter 变成 my-enter
vue 动画可以和 animate.CSS 合用. --- 参见 vue day3-8 节
transition-group 组合列表动画标签
.v-move 和. v-leave-active 要一起使用
初始化动画需要加 appear
设置渲染成的标签 tag=""
半场动画的实现
- @before-enter
- @enter
手动刷新 offsetWidth --offset 系列
done() ------ 触发 after-enter 函数
@after-enter
组件的出现
组件的出现就是为了拆分 Vue 实例的代码量, 防止一个 vue 实例代码量过多.
组件化: 从 UI 界面的角度进行划分的, 方便组件复用
模块化: 从代码逻辑的角度的划分的, 方便代码分层开发, 让每个功能模块职能单一.
组件也有自己的生命周期函数
组件上的 data 数据
data 是一个函数, 且返回一个 对象. 这样可以使得每个组件都有一个私有的 data 数据域.
多个组件的切换
使用
组件渲染的几种方式
直接以组件的名称作为标签渲染
用 component 标签渲染 但是需要添加 :is 属性来添加组件名称.
在组件中操作 DOM, 如 ref,
在一个组件中可以操作页面上所有的元素.
即在子组件中也可以获取父组件的 DOM 元素
配合 getBoundingClientRect() 获取偏移距离.
关于 watch
使用这个属性, 可以监听 data 中指定数据的变化, 然后触发函数. 此函数有两个参数. 参 1 新数据 ; 参 2 旧数据.
watch 最主要是用来监听路由的变化.
关于 computed
在 computed 中, 可以定义一些 属性, 这些属性, 叫做 [计算属性] , 计算属性的, 本质, 就是 一个方法, 只不过, 我们在使用 这些计算属性的时候, 是把 它们的 名称, 直接当作 属性来使用的; 并不会把 计算属性, 当作方法去调用;
计算属性的求值结果, 会被缓存起来, 方便下次直接使用;
需要 return 一个值.
父组件向子组件传值
原理: 父组件通过属性绑定 (v-bind/v-on)的形式, 把数据 (data/methods) 绑定到子组件标签上, 子组件就可以通过属性名获取父组件的数据, 并且子组件需要添加 props 属性接收 绑定的属性名 获取数据.
props 中的数据 是只读的, 和 template 模板写在一起;
子组件的数据和父组件的区别 :
子组件传值给父组件
类似一个 回调函数.
1, 在渲染的子组件上使用 v-on 绑定要传递的函数
2, 在渲染的子组件中使用 this.$emit('函数名', 参数)
ref 获取 DOM 和组件
Vue 不建议操作 DOM, 故提供了 ref 操作 DOM
1. 在需要操作的元素或组件上添加 ref=""
2. 可以在函数调用 this.$refs.str.
调用子组件的 data 和 methods.
路由
什么是路由: 路由是一种对应关系.
后端路由: 是前端请求的 URL 和后端的处理函数的对应关系.
前端路由: 是对于单页面, 主要通过 hash (#)来实现不同页面之间的切换. 在 HTTP 请求中, 不会包含 hash 后面的内容
路由引入的两种方式
script 引入
webpack 模块化
路由对象
每当创建一个路由对象, 在全局中, 就有了一个 路由的构造函数 VueRouter, 传递一个配置对象.
routes 表示[路由匹配规则] -- 是一个数组, 每一项是对象
每一项匹配规则就是一个对象, 必须带有两个属性:
path ------ 路径
component------ 路由跳转的组件
如果有路由的嵌套, 则添加第三个属性 children:[], 在里面写路由的匹配规则.
将路由对象注册到 vm 实例上
在 HTML 上 放一个路由容器 router-view 标签
关于 vue-router
router-link 默认是 a 标签, 可以通过 tag='' 改为相应的标签.
router-link 有一个选中样式属性 .router-link-active
linkActiveClass: 'myactive' // 和激活相关的类, 在路由实例里添加修改上面的类名.
路由的重定向
{path:'/', redirect:'/login(重定向的路径)'}
路由传参
在路由中以 序列化 形式传递.
在路由规则中以 ** this.$route.query 对象拿取.**/ 模板中提取
在路由中以 / 的方式传递
在 path 匹配路径中添加 /:id
在组件中可以用 http://this.$route.params.id 提取
vue 目前提供的标签
- template transition transition-group component
- data
在 Vue 中一般是自己组件中的私有数据.
在网页中有两种跳转形式
使用 a 标签的形式 叫做标签跳转
使用 Windows.location.href 的形式 叫做 编程式导航.
区分 this.route
this.$route 是路由参数对象, 所有路由中的参数, params,query 等等都属于他
this.$route 是一个路由导航对象 VueRouter, 用它可以方便的 使用 JS 代码, 实现路由的前进和后退, 跳转到新的 URL 地址.
webpack 的主要内容
打包时候问题:
+ 1 只有添加了插件 webpack-dev-server 的时候 bundle.JS 文件才会在虚拟内存中挂载.
+ 2 使用 var htmlWebpackPlugin = require('html-webpack-plugin')
+ 2 先看一下文档.
WEBPACK 是基于 node 构建的.
NPM run dev NPM run build
webpack-dev-server 1. 把项目开启在服务器上, 类似于一个 node 服务 2. 把指定的 index.JS 打包成 main.JS , 并把 main.JS 放入到内存中
HTML-webpack-plugin 1. 把 index.HTML 文件打包到内存中 2. 把 main.JS 自动添加到 index.HTML 中
loader 1.webpack 默认只能打包 JS 类型的文件. 此时打包 CSS 等需要 loader 2. Less Less-loader 先这两个包装包 (vue 脚手架不提供 Less 和 Sass, 只提供 CSS 的)---- 装完包后 在页面上引入 即可使用 Less 格式的 CSS 样式! +
render 方法(重点)
render 渲染组件会覆盖之前 #App 里面的内容.
render: function (createElements) { // createElements 是一个 方法, 调用它, 能够把 指 定的 组件模板, 渲染为 HTML 结构 return createElements(login) // 注意: 这里 return 的结果, 会 替换页面中 el 指定的那个 容器 }
包的查找规则 import 和 require 导入规则都一样.
1. 在项目目录中查找 node_modules 的文件夹
2. 在 node_modules 的文件夹根据包名, 查找对应的 Vue 文件夹(以 vue 为例子)
3. 在 vue 文件中查找 package.JSON 的配置文件
4. 在配置文件中 查找 mian 属性, 此 mian 属性指定了包被加载的时候的入口文件.
如何在 webpack 中使用 vue 项目
-D 表示一般安装项目所需的工具, 放在 package.JSON 中的 devDependencies 如 CSS-loader ,Less
-S 表示项目所需的依赖文件 dependencies 如 vue jQuery
-g 表示全局文件
vue 学习的几个点以及其他
JS 东西就是变量的声明方式
数组的扩展, 对象的扩展, 函数的扩展
代理, 反射, promise,class, 模块化
promise
就是单纯的解决 回调地狱 的问题, 也就是多层嵌套, 比如 Ajax 里面还有 Ajax.
代码量不一定减少.
重要概念
Promise 是一个构造函数, 那么就可以 new Promise() 得到一个 Promise 实例.
Promise 上有两个函数, 分别是 resolve(成功之后的回调) 和 reject(失败回调).
在 Promise 的 prototype 属性上, 有一个 .then() 方法, 只要是 Promise 构造出来的实例都可以访问 .then() 方法.
Promise 表示一个 异步的操作, 每 new Promise 的实例就表示一个具体的异步操作.
既然 Promise 创建的实例是一个异步操作. 那么, 操作的结果只能是两种状态:
异步执行成功 ---resolve(成功之后的回调)和异步执行失败 ---reject().
由于 Promise 的实例, 是一个异步, 所以, 内部拿到操作的结果侯, 无法使用 return 把操作的结果返回给调用者; 这个时候, 只能使用回调函数的形式, 来把成功或失败的结果, 返回给调用者. // function(data,callback){ return data;--- 这是错的, 而是下面这种. return callback(data); }
我们可以在 new 出来的 Promise 实例上, 调用. then() 方法[预先] 为这个 Promise 异步操作, 指定成功 resolve 和失败 reject 的回调函数.
- // 注意: 这里 new 出来的 promise, 只是代表 [形式上] 的一个异步操作;
- // 什么是形式上的异步操作: 就是说, 我们只知道它是一个异步操作, 但是做什么具体的异步事 情, 目前还不清楚 // var promise = new Promise()
- // 这是一个具体的异步操作, 其中, 使用 function 指定一个具体的异步操作
- var promise = new Promise(function(){ // 这个 function 内部写的就是具体的异步操作!!! })
- const fs = require('fs')
- // 每当 new 一个 Promise 实例的时候, 就会立即 执行这个 异步操作中的代码 // 也就是说, new 的时候, 除了能够得到 一个 promise 实例之外, 还会立即调用 我们为 Promise 构造函数传递的那个 function, 执行这个 function 中的 异步操作代码; var promise = new Promise(function () { fs.readFile('./files/2.txt', 'utf-8', (err, dataStr) => { if (err) throw err console.log(dataStr) }) })
- // 初衷: 给路径, 返回读取到的内容. 且为了规避一 new promise 就触发括号里面的 function(){} 需要用一个函数把实例包裹起来. function getFileByPath(fpath) { return new Promise(function (resolve, reject) { fs.readFile(fpath, 'utf-8', (err, dataStr) => {
- if (err) return reject(err)
- resolve(dataStr)
- })
}) }
promise 的需求
在一连串的 .then 中, 哪怕前面的 Promise 执行失败了, 但是, 也不要影响后续 .then 的执行, 此时, 我们可以单独为每个 Promise 通过失败的回调里 指定下一次的内容.---- 参照 Vue 课程 day8-8 节.
catch 的作用 : 但是又有相反的需求, 后续的 Promise 执行, 和前面有关, 一旦前面的报错, 后续的不能执行.
catch 的作用就是前面的 Promise 执行失败, 则立即终止所有 Promise 的执行, 并马上进入 catch 去处理 Promise 中抛出的异常 catch(fn).
axios 的请求拦截和响应拦截有什么用, 能做什么
关系 vue
父子组件生命钩子加载的顺序
父子组件的通讯方案, 兄弟组件的通讯方案
为什么不建议在子组件改变父组件传过来的值
vue 中的 extend,extends,mixin 的区别
vue-router 中的 history 模式和 hash 模式的区别, 为什么 history 模式更好, 怎么配置 history 模式
vue-router 的路由钩子可以用它做什么;
设置路由跳转的取消和成功
怎么利用 vue-router 进行公共页面的布局.
来源: https://juejin.im/post/5c4c0d5e6fb9a049d4422fb4