model 数据
view 页面
viewModel Vue实例
说明: 文本数据渲染
用法: v-text = "Vue实例中的数据" => 简写 {{Vue实例中的数据}}
相当于JavaScript中的innerText
v-text指令 和 {{ }}插值表达式 的区别
说明: HTML渲染数据
用法:v-html = "Vue实例中的数据"
会解析html结构 渲染至页面
相当于JavaScript中的innerHTML
️1.2.1 v-html指令 和 v-text指令的区别
注意: 在网站上动态渲染任意的 HTML 是非常危险的!!! 因为容易导致 XSS 攻击 只在可信内容上使用 v-html 绝对不要用在用户通过(提交)的内容上使用
说明: 事件绑定(绑定事件监听器)
用法: v-on:事件名 = "事件处理函数" => 简写 @事件名 = "事件处理函数"
️1.3.1 详细用法
methods
中 注意: 操作Vue实例上的数据要跟上 this
- $event.target 获取当前事件触发的DOM元素
- $event.path[0](el.path[0]) 也可以获取当前事件触发的DOM元素 path数组中有从触发事件源的元素的所有上一级元素 直到window
- 实参不传递(没有任何参数) 默认在形参中第一个就是事件参数
实参传递 就必须传递$event 来获取获取事件参数
1.3.2 事件修饰符
很重要!有些第三方组件可能内部并没有设置原生的事件 就可以通过.native来触发事件
面试问及
之前在使用饿了么UI的时候给一个组件添加一个原生的事件
但是一直触发不了
后面查阅文档发现这个组件内部并没有注册我使用的原生事件
事件修饰符.native就可以直接监听并触发组件的原生事件
说明: 属性绑定(行内属性)
用法: v-bind:属性名="Vue实例中的数据" => 简写 :属性名="Vue实例中的数据"
当Vue实例中的数据改变之后 页面会同步更新
️1.4.1 属性绑定修饰符
️1.4.2 对象的方式绑定class
:class = "{'red' : isRed}"
isRed = true 就有red这个类
isRed = false 就没有red这个类
isRed 在 Vue 实例data中声明
class = "red" :class = "{'yellow' : isYellow}"
️1.4.3 对象的方式绑定style
:style = "{fontSize : mySize + 'px'}"
说明: 双向数据绑定
用法: v-model = "Vue实例中的数据"
️1.5.1 双向
数据能够自动的从内存中显示到页面上去
️1.5.2 双向绑定修饰符
注意: v-model 只能设置给from表单属性
说明: 循环渲染
用法: v-for = "(item,index) in items" :key = "index"
items是源数据数组
item是被迭代的数组元素的别名
index是被迭代的数组元素的下标(索引)
1.6.1 :key
1.6.2 遍历数组注意点
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
...
这种修改数组中的元素是无法实现数据改变后页面会同步改变(只会修改data中的数据 但是页面不会同步改变)
this.arr.splice(index,0,新值)
this.arr.splice(index,1)
this.arr.splice(index,1,新值)
说明: 条件(表达式或布尔值)判断渲染
用法:v-if = "表达式或布尔值"
v-else-if = "表达式或布尔值"
v-else
1.7.1 注意
v-if 和 v-else-if 后面必须跟表达式或布尔值
v-else-if 和 v-else 不能独立使用 必须跟在 v-if 后面
说明: 条件渲染
用法: v-show = "表达式或布尔值"
根据表达式或布尔值的真假切换元素的display属性
1.8.1 注意
v-show 不支持 元素 也不支持
v-else
都是用来判断渲染数据的
1.有较高的切换性能消耗
2.惰性渲染 第一次如果条件为false 则不会渲染到页面 需要等后面条件切换后才会进行第一次渲染
3.条件切换是切换DOM数中这个元素的移除或添加
4.如果运行时条件很少改变则使用v-if
1.有较高的初始渲染消耗
2.初始渲染 不管条件 第一次加载页面的时候都会渲染到页面
3.条件切换只是切换元素的display属性
4.如果运行时条件会非常频繁的切换则使用v-show
说明: 这个指令保存在这个元素上 直到关联实例结束编译
2.0.1 详细说明
插值表达式在网络较满的情况下可能会出现数据闪烁问题
可以通过给实例(#app)盒子添加一个v-cloak
指令
通过这个指令的特性(如页面中还有插值表达式就会存在这个指令 如果页面的插值表达式都被替换成数据 就会自动移除这个标签)
配合css[v-cloak]{display:none|opacity:0}
来解决数据闪烁的问题
说明: 这个指令添加的元素 内部的胡子语法只会在第一次渲染的时候执行解析一次 后面数据发生改变后也不会触发更新
2.1.1.1 用途
某些元素只需要解析一次 后续不需要更新 就可以使用这个指令 提升性能
建议使用id 因为id是唯一的 一个Vue实例绑定一个页面元素
可以通过this.xxx 获取Vue实例上的数据或方法
必须要有 return 值
执行时机:
初始化显示执行和函数中用到了data中的数据变化后会执行
{{计算属性函数名}}
计算属性本质就是一个方法 但是使用的时候是将这些方法的方法名当作属性使用 计算属性的值就是return
出来的值1.使用get和set函数 需要把计算属性函数改成计算属性对象
2.计算属性默认执行get方法(根据相关的数据计算返回当前属性的值)
3.当计算数学值自身改变后执行set方法
4.可以用来计算税前和税后的互推算
缓存 => {计算属性名:"数据结果"} 键值对
形参(newVal,oldVal) => (改变后的值,改变前的值)
watch默认无法侦听复杂数据类型 需要侦听复杂数据类型 得使用深度侦听
watch:{
XXX:{
deep:true,
handler(newVal,oldVal){
// 处理代码
}
}
}
watch: {
// watch里面的 $router 这些对象前面不要带this
"$route.path"(newVal, oldVal) {
if (newVal.indexOf("/login") >= 0) {
this.welcom = "欢迎登陆";
}
if (newVal.indexOf("/register") >= 0) {
this.welcom = "欢迎注册";
}
}
}
watch: {
$route: function(newVal,oldVal) {
console.log(this.$route.path);
}
}
使用或侦听器吗 在Vue中碰到过什么bug
1.侦听器用来检测数据的改变
2.当侦听的那个数据发生改变后就会触发侦听器中的对应函数
3.一般我更多的使用是用侦听路由的变化 => 重新获取数据(如搜索在对应的router-view中显示对应的数据)
4.之前碰到过一个坑点 侦听器默认无法侦听复杂数据类型
5.后面使用深度侦听 depp:true 来解决了这个问题
6.或者侦听精确到对象中的那个值也可
声明全局过滤器 一定要在实例化Vue之前声明
Vue.filter("formatData", (形参=管道符前面的数据,形参=想要传入的数据...) => {
处理数据; `返回`处理之后的数据
});
filters:{
formatTime(形参=管道符前面的数据,形参=想要传入的数据...){
处理数据; `返回`处理之后的数据 }
}
{{data | formatTime | formatTime1 | ...}}
获取data中的所有数据
用于当前Vue实例的初始化选项 可以获取自定义选项
new Vue({
customOption: 'foo',
created: function () {
console.log(this.$options.customOption) // => 'foo'
}
})
返回的是一个DOM对象
组件的出现就是为了拆分Vue实例的代码量 能够让我们以不同的组件来划分不同的功能模块 需要什么功能就去调用对应的模块即可
局部功能界面
是从代码的逻辑角度去划分的 方便代码分层开发 保证每个功能模块的职能单一
是从UI界面的角度进行划分的 前端的组件化方便UI组件的重用
️6.3.1 用法
Vue.component('组件名',{参数})
6.3.2 注意
组件名请使用小写
大写需要驼峰命名法
Vue.component('sayHiBaby',{参数})
页面中标签使用
️6.3.3 组件参数
父向子传参
通过 props 向子组件传递数据
可以在组件实例中通过 this.xxx 拿到传递过来的值
高级写法(props验证)
props:{
xxx:{
// 数据类型
type:"String",
// 必须传递
required:"true",
// 默认值
default:"mystring"
....
}
}
props可以传递任何数据类型 包括函数
组件中的数据data是一个函数 将数据写在返回出去的对象中即可
为什么组件的data是一个函数 而Vue实例的data是一个对象?
1.每一个Vue组件都是一个Vue实例
2.都是通过new Vue() 创建出来的
3.如果data是一个对象的话 那么这些组件的引用指向就会相同
4.一个的值修改后 其他的值也会修改(这是JavaScript语法的特性)
5.如果data是一个函数 函数中再返回一个对象
6.那么每个Vue组件都有了自己的作用域 互不干扰
模版
Vue生命周期钩子 || Vue生命周期函数
Vue提供给开发者一系列的回调函数 让我们可以在Vue的各个阶段添加自定义的逻辑处理
7.1.1 初始化显示
创建期间的生命周期函数(1次)
常用
如果要操作data中的数据和methods中的方法 最早只能在created中调用常用
发送ajax请求 启动定时器等异步任务 操作DOM中的节点Vue渲染解析插值表达式 并不是在页面中直接渲染解析 而是将整个挂载在Vue实例的模版 拿到内存中去解析 等全部解析完成后 再一次性的渲染到页面(批量) (因为有可能页面中有很多一样的data中的值 如果是在页面中直接渲染解析会很耗性能)
7.1.2 更新显示
运行期间的生命周期函数(0次-多次)
7.1.3 销毁
销毁期间的生命周期函数(1次)
常用
做收尾工作 如:清除定时器...想要销毁Vue实例 调用 vm.$destroy() 即可
注意: 这个方法方法并不会销毁Vue实例的一些如 定时器或计时器等方法
会造成 '内存泄漏' 所以在完全销毁之前 需要在 beforeDestory 钩子中清除定时器等...
this.$emit('事件名A','参数')
url地址和组件之间的关系
必须添加 Vue.use(VueRouter)
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
️️9.3.1 HTML
tag属性
来设置最后被渲染的标签to属性
指定跳转的链接登陆
注册
️️9.3.2 JavaScript
const login = { template: "#tempLogin" };
const logout = { template: "#tempLogout" };
const routes = [
{ path: "/login", component: login },
{ path: "/logout", component: logout }
];
const router = new VueRouter({
routes
});
在Vue实例中 绑定router
new Vue({
el:"xxx",
router
})
设置路由匹配成功后 router-link 的样式属性
/login => /login/user
触发 添加样式
/login/user => /login/user
触发 添加样式
点了跳转 没有任何逻辑 类似于(a标签设置了href)
跳转的同时执行其他需要执行的逻辑router.push('地址')
/user
=> /user/:id
:id
只是一个占位/user
=> /user/123
this.$route.params.(id)
获取传递过来的数据{path:"地址1",redirect:"跳转到的新地址2"}
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
next()
})
to
去哪个路由
一般通过to来判断对应路由做对应处理
from
来自哪个路由
next()
必须next()才可以继续跳转页面(像node"express"里面的中间件)
1.判断登陆状态 如判断token...
2.可以在跳转路由时先判断这个页面这个用户是否有权限访问...
3.可以每次路由跳转前都提示用户跳转至什么页面...
meta: { requiresAuth: true }
children:[ ]
注意
嵌套路由的path不要加 /
{ path: '/user', component: User,
children: [
{
path: 'index',
component: Index
}
]
}
配置错误路由规则
{path:"/NotFound",component:NotFound}
{path:"*",redirect:'.NotFound'}
import Foo from "./Foo.vue";
修改成 const Foo = () => import('./Foo.vue')
其他不变 即可️️11.1.1 Axios是什么?
Axios是一个基于 promise(实现了链式调用)
的 HTTP 库 可以用在浏览器和 Node.js 中 专注于发请求 专注于网络请求的一个库`
️️11.1.2 CDN
️️11.1.3 .then
成功回调
11.1.4 .catch
失败回调
11.1.5 get请求
// 为给定 ID 的 user 创建请求
axios.get('/user?ID=12345')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// 可选地,上面的请求可以这样做
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
️️11.1.6 post请求
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
11.1.7 基地址
基础的地址应用 没有必要每次都写 可以直接抽离出来
axios.defaults.baseURL = '设置的基地址'
Vue.prototype.$axios = axios
axios填写路径时后面直接写对应的路径即可
前面的公共部分不需在写(写了也不会影响)
️️11.1.8 设置跨域携带cookie
axios.defaults.withCredentials = true
️️11.1.8.️1 面试问及
11.1.9创建克隆对象 多基地址设置
const xxx = axios.create({
// 即地址
baseURL: 'https://some-domain.com/api/',
// 可以统一设置请求头
headers: {Authorization: token}
});
xxx.get()
xxx.post()
️️11.2 Axios拦截器
️️11.2.1 请求拦截器
axios.interceptors.request.use(function (config) {
// 可以在发请求之前在这里设置一些请求头
`config.headers.Authorization=token`
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
️️11.2.2 响应拦截器
axios.interceptors.response.use(function (response) {
// 可以在获取响应数据之后设置一些提示 如获取失败/成功
`response.data.code == 200?`
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
vue-resource已经不再更新 推荐使用Axios
Vue提供的让程序员可以在动画的各个时机 添加 自定义逻辑 的钩子 也可称之为 动画钩子或动画函数
// 指定显示的transition
xxx-enter-active
// 指定隐藏的transition
xxx-leave-active
// 指定隐藏时的样式
xxx-enter/xxx-leave-to
transition标签包裹
transition-group标签包裹
动画样式的开始类名
解析为的标签名
12.9.1 HTML
12.9.2 JavaScript
// ...
methods: {
// --------
// 进入中
// --------
beforeEnter: function (el) {
// ...
},
// 当与 CSS 结合使用时
// 回调函数 done 是可选的
enter: function (el, done) {
// ...
done()
},
afterEnter: function (el) {
// ...
},
enterCancelled: function (el) {
// ...
},
// --------
// 离开时
// --------
beforeLeave: function (el) {
// ...
},
// 当与 CSS 结合使用时
// 回调函数 done 是可选的
leave: function (el, done) {
// ...
done()
},
afterLeave: function (el) {
// ...
},
// leaveCancelled 只用于 v-show 中
leaveCancelled: function (el) {
// ...
}
}
️️13.2.1 下载
npm install vuex --save
️️13.2.2 创建VueX仓库
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
// 数据
count: 0
},
mutations: {
// 方法
increment (state) {
state.count++
}
}
})
new Vue({
el:xxx,
// 挂载到Vue实例上
store
})
️️13.2.3 在组件中获取VueX的数据
{{$store.state.count}}
this.$store.state.count
13.2.4 在组件中修改VueX的数据
this.$store.commit(''mutations中的方法,'参数')
️️14.1.1 用一个文件能够包含组件的所有内容
️️14.1.2⃣️ 单文件开发的好处
把很多开发中需要用到的功能整合到了一起 让Vue开发人员专注于逻辑代码即可 是用webpack配置出来的
vue create 项目名
<= 项目名不要有中文!!!不要大些cd 项目名
npm run serve
npm init webpack "项目名"
cd "项目名"
npm instal
npm run dev
最后一步选 No, I will handle that myself 自己再npm i 下载速度会快一点
|-- build : webpack 相关的配置文件夹(基本不需要修改)
|-- dev-server.js : 通过 express 启动后台服务器
|-- config: webpack 相关的配置文件夹(基本不需要修改)
|-- index.js: 指定的后台服务的端口号和静态资源文件夹
|-- node_modules
|-- src : 源码文件夹
|-- components: vue 组件及其相关资源文件夹
|-- App.vue: 应用根主组件
|-- main.js: 应用入口 js
|-- static: 静态资源文件夹
|-- .babelrc: babel 的配置文件
|-- .eslintignore: eslint 检查忽略的配置
|-- .eslintrc.js: eslint 检查的配置
|-- .gitignore: git 版本管制忽略的配置
|-- index.html: 主页面文件
|-- package.json: 应用包配置文件
|-- README.md: 应用描述说明的 readme 文件
14.8.1 编码位置
xxx.vue
中assets
文件夹下面 直接使用对应路径引用即可14.8.2 引入css
main.js
=> import "路径"
组件内的script标签
=> @import url("路径")
14.8.3 注册组件
main.js
中import 组件 from 地址
Vue.component('组件名',组件)
import 组件名 form '地址'
components
就可以在导入的组件中通过组件名使用该组件name:值
即可14.8.4 整合路由
14.8.4.1 下包
npm install vue-router
14.8.4.2 导包
import VueRouter from 'vue-router'
14.8.4.3 用包
xxx.vue
import 组件名 from '组件路径'
const routes = [{path:"/xxx/:xx},component:组件名]
`const router = new VueRouter({
routes
})`
`new Vue({
router
})`
14.8.4.4 编码位置
main.js
app.vue
components
assets
14.9.1 面试问及
14.9.2.1 css预处理
14.9.2.1.1使用less
npm install -D less-loader less
也可以直接导入less文件14.9.2.1.2 使用sass
npm install -D sass-loader node-sass
也可以至今导入scss文件14.9.2.1.3 css作用域
scoped
属性即可为元素添加随机属性
样式中添加属性选择器
2者结合 就把css的作用范围 约束
export default xxx
只能写一个 如果需要暴露多个 可以在default后面写对象import xxx from "模块"
export const bbb
导出和导入的名字必须一样import {bbb} from "模块"
饿了么前端团队开发的PC端的基于Vue的组件
内部封装了很多现成的组件
在VueCLI中使用elementUInpm i element-ui
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
有些组件并没有在组件内部使用原生事件
但是有些情况需要一些原生事件
就可以使用.native
修饰符来触发
️️15.1.1 link
️️15.1.2 @import
返回所有匹配成功的值
创建一个新数组,
其包含通过所提供函数实现的测试的所有元素
(数组过滤)
const oldArr = ["dajsk", "dkjdklas", "kgjftlk", "ksf", "ds", "mfksjjks"];
let res = oldArr.filter((val, index) => val.indexOf("d") != -1); // 返回所有匹配成功的值
console.log(res); // [ 'dajsk', 'dkjdklas', 'ds' ]
返回匹配的第一个值
返回数组中满足提供的测试函数的第一个元素的值
没有匹配成功返回undefined
const oldArr = ["dajsk", "dkjdklas", "kgjftlk", "ksf", "ds", "mfksjjks"];
let res1 = oldArr.find((val, index) => val.indexOf("d") != -1); // 返回匹配的第一个值
console.log(res1); // dajsk
将匹配成功的值做对应的计算后再次返回
创建一个新数组
其结果是该数组中的每个元素都调用一个提供的函数后返回的结果
const oldArrMap = [3, 4, 7, 1, 8, 5];
let res2 = oldArrMap.map((val, index) => {
// 将匹配成功的值做对应的计算后再次返回
if (val > 5) {
val = val * 2;
}
return val;
});
console.log(res2); // [ 3, 4, 14, 1, 16, 5 ]
因为这些方法都是返回的新数组 并没有覆盖原来的数组所以可以继续链式调用数组的方法继续过滤
遍历数组
方法对数组的每个元素执行一次提供的函数
const oldArrForEach = [3, 6, 8, 2, 8, 0];
let num = 0;
oldArrForEach.forEach((val, index) => {
num += val;
});
console.log(num); // 27
oldArrForEach.forEach((val, index) => {
if (index == 2) return console.log(val); // 8
});
注意
需要在浏览器声明callback去的函数
需要在script请求前声明
兼容性强
只能发送get请求
网络请求设计方法时
考虑到数据的操作主要:增删改查
方法的命名可以体现这个操作
一般常用的就是get和post
️️15.5.1 Cookie
无状态
的每次请求 浏览器和服务器交互完毕后 彼此并没有留下什么
继续请求 也无法判断你是谁
如登陆功能
为了能够保存一些信息
服务器返回响应报文时 会偷偷的带一个响应头
作用是在浏览器中偷偷保存一些信息set-cookie
浏览器接收到这个响应头后 会在本地保存这个响应头
第二次请求时 浏览器就会自动带上这个信息去服务器
服务器接收到这个信息 就知道你是谁了
ajax跨域请求 默认不携带cookie 需要设置
跨域cookie在浏览器中无法看到 需要抓包
️️15.5.2 Session
Seesion 是将用户数据存储在服务器中
通过sessionId来验证查找服务器中的用户信息
sessionId一般是存放在浏览器的cookie中的
所以Session需要配合浏览器的cookie或者浏览器的其他存储技术一起使用
️️15.5.3 token
和cookie差不多 也可以记录登陆状态
服务器生成的
通过用户浏览器版本、用户信息...生成的一个密钥
浏览器不会自动保存
可以接口本地存储来保存token
浏览器不会自动携带发送
每次请求接口时可以通过headers携带存储的tokenheaders{ Authorization :token }
️️15.5.4 localStorage
可以把数据存储到本地(浏览器) 只要用户不删除 则会一直保存 每个域名都是独立的保存数据 不同域名不能互相访问 长久保存数据可以存储到 localStorage 可以存储5M数据
localStorage.setItem(key,value)
localStorage.getItem(key)
=> 如果没有这个数据 则返回 null
localStorage.removeItem(key)
localStorage.clear()
️️15.5.5 sessionStorage
短暂存储数据 可以多页面传值 相当于localStorage会更安全 浏览器关闭后就不会保存了 可以存储5M数据
sessionStorage.setItem(key,value)
sessionStorage.getItem(key)
=> 如果没有这个数据 则返回 null
sessionStorage.removeItem(key)
sessionStorage.clear()