1.Vue基础
1.Vue基本概念
-
Vue是什么?
Vue是一个javascript渐进式框架
-
什么是渐进式呢?
渐进式就是逐渐使用,集成更多的功能
-
什么是库和框架呢?
库是方法的集合,而框架是一套拥有自己规则的语法
1.库和框架
-
库:封装的属性或方法(例jQuery)
-
框架:拥有自己的规则和元素,比库强大的多(例Vue)
2.@vue/cli脚手架
1.安装
-
全局安装@vue/cli模块包
yarn global add @vue/cli
-
创建项目
vue create vuecli-demo
注意: 项目名不能有大写字母,中文和特殊符号
2.@vue/cli目录
-
脚手架里主要文件和作用?
-
.node modules - 都是下载的第三方包
-
.public/index.html- 浏览器运行的网页
-
src/mainjs- webpack打包的入口
-
src/App.vue- Vue页面入口
-
packagejjson - 依赖包列表文件
-
-
noscript
-
main.js和App.vue,以及index.html作用和关系?
-
main,js -项目打包主入口 - Vue初始化
-
App.vue - Vue页面主入口
-
index.html-浏览器运行的文件
-
App.vue => main,js => index.html
-
3.如何配置端口号
目标:项目中没有webpack.configjs文件,因为Vue脚手架项目用的vue.config.js
-
src并列处新建vue.configjs,填入配置,重启webpack开发服务器
-
vue脚手架项目--默认的配置文件名
-
webpack+node环境- 导出配置对象
-
module.exports = { devServer: { port: 3000, open: true //浏览器自动打开 } }
-
3.Vue-Eslint
-
是什么?
是代码检查工具,违反规定就报错
-
无eslint(暂时关闭)
-
方式1:手动解决掉错误,以后项目中会讲如何解决
-
方式2:暂时关闭eslint检查,(因为现在主要精力在学习vue语法上),在vue.config.js中配置后重启服务
-
module.exports = { //...其他配置 lintOnSave: false //关闭eslint检查 }
-
4.单vue文件
5.main.js
1.new Vue()
-
以下两种写法相同
new Vue({ el:"#app" //vue实例编译后的模板挂载到index.html的id叫app的标签上 render: h => h(App) })
new Vue({ render: h => h(App) }).$mount("#app")
2.Vue基础语法
1.插值表达式
2.MVVM设计模式
-
什么是设计模式?
设计模式是对代码分层,引入一种架构的概念
-
MVVM是什么?
MVVM(模型视图,视图模型双向关联的一种设计模式)
-
MVVM好处?
减少DOM操作,提高开发效率
3.vue指令
1.v-bind
目标:给标签属性设置Vue变量的值
-
v-bind语法和简写
-
语法: v-bind:属性名="vue变量"
-
简写::属性名="vue变量
-
2.v-on绑定事件
目标:给标签绑定事件
-
语法
-
v-on:事件名=“要执行的少量代码
-
v-on:事件名=“methods中的函数名
-
v-on:事件名=“methods中的函数名(实参)
-
-
v-on: 可以简写成@语法: @事件名=“methods中的函数
1.接收事件对象
目标:Vue事件处理函数中,拿到事件对象
-
语法
-
无传参通过形参直接接收
-
传参通过$event指代事件对象传给事件处理函数
2.vue事件-修饰符
目标:在事件后面修饰符名- 给事件带来更强大的功能
-
语法
@事件名修饰符="methods里函数"
-
修饰符列表
-
.stop- 阻止事件冒泡
-
.prevent-阻止默认行为
-
.once - 程序运行期间只触发一次事件处理函数
-
3.vue按键-修饰符
目标:给键盘事件,添加修饰符,增强能力
-
语法:
-
@keyup.enter - 监测回车按键
-
@keyup.esc监测返回按键
-
更多修饰符: 事件处理 — Vue.js
3.v-model
4.v-text
5.v-show
6.v-for
1.认识
目标:列表渲染,所在标签结构,按照数据数量,循环生成
-
语法
-
v-for="(值变量索引变量)in 目标结构
-
v-for="值变量in 目标结构
<li v-for="obj in stuArr" :key="obj.id"> <span>{{ obj.name }}</span> <span>{{ obj.sex }}</span> <span>{{ obj.hobby }}</span> </li>
-
v-for="( value , key ) in 目标结构" (当数据为对象时)
<p v-for="(value, key) in tObj"> <span>{{ value }}</span> : <span>{{ key }}</span> </p>
tObj:{ name: "小黑", age: 18, class: "1期" },
-
2.v-for更新监测
methods: { revBtn(){ //1.数组翻转可以让v-for更新 this.arr.reverse() }, sliceBtn(){ //2.数组slice方法不会造成v-for更新 //slice不会改变原始数组 this.arr.slice(0,3) }, updateBtn(){ //3. 更新某个值的时候,v-for是监测不到的 this.arr[0] = 1000; } }
1.数组变更方法就会导致v-for更新,页面更新
-
push()
-
pop()
-
shift()
-
unshift()
-
splice()
-
sort()
-
reverse()
2.数组非变更方法返回新数组就不会导致v-for更新可采用盖数组或this.$set()
-
filter()
-
concat()
-
slice()
解决---this.$set()
参数1: 更新目标结构
参数2: 更新位置
参数3:更新值
this.$set(this.arr, 0, 1000)
3.v-for 更新性能
4. key的作用
4.动态class
:class="{类名:布尔值}"
5.动态style
:style="{css属性名:值}"
6.过滤器
1.作用
传入一个值,处理后返回另外一个值
2.定义语法
1.全局
-
//main.js - Vue.filter("过滤器的名字",函数体)
Vue.filter("reverse",val=>val.split("").reverse().join(""))
2.局部
-
//某.vue文件-filters:{"过滤器的名字":函数体}
filters: { toUp (val) { return val.toUpperCase() //字符串小写字母转化为大写 } }
3.过滤器传参数
-
如何给过滤器传额外值
-
vue变量|过滤器(值)
-
4.注意事项
<p> {{ msg | reverse('|') }} //使用|分割 </p>
Vue.filter("reverse",(val,s)=>{ return val.split("").reverse().join(s) })
3.使用语法
1. Vue变量|过滤器名字
<p> 原来的样子:{{ msg }} </p> <p> 使用翻转过滤器: {{ msg | reverse}} </p> <p :title="msg | toUp">鼠标长停</p> . . . data(){ return { msg: 'Hello,Vue' } }
2.多个过滤器使用
<p :title="msg | toUp | reverse('|')">鼠标长停 </p>
-
vue变量|过滤器1|过滤器2
只能用于 插值表达式/动态属性
7.计算属性computed
1.基本使用
-
目标:一个变量的值,依赖另外一些数据计算而来的结果
-
计算属性和data属性都是变量,不能重名
computed: { "计算属性名" () { return "值" } }
-
使用
<div> {{ num }} </div>
-
2.缓存特性
-
问题:不用计算属性,用函数调用也可以实现
-
计算属性优势:
-
带缓存
-
计算属性对应函数执行后,会把return值缓存起来
-
依赖项不变,多次调用都是从缓存取值
-
依赖项改变,函数会自动重新执行,并缓存新的值
-
计算属性,基于依赖项的值进行缓存,依赖的变量不变,都直接从缓存取结果
3.完整写法
-
计算属性也是变量
-
给计算属性赋值,不写set会报错,需要setter
<input v-model="full">
-
语法
computed: { //给full赋值触发set方法 "full": { set(值){ }; //使用full的值触发get方法 get(值){ return "值" }; } }
8.侦听器watch
-
可以侦听data/computed属性值的改变
1.基础
-
语法
<input v-model="name">
watch: { "name"(newVal,oldVal){ //使用newVal,oldVal } }
2.深度侦听
-
侦听复杂类型,或者立即执行侦听函数
-
侦听对象里面的值改变
-
语法(侦听对象)(侦听器对象形式)
<input v-model="user.name">
watch: { "user": { immediate: true,// 立即执行(网页打开handler就执行) deep: true,// 深度侦听复杂类型内变化 handler(newVal,oldVal){ //newVal,oldVal是对象 console.log(newVal.name) //拿到user.name } } }
3.组件
1.基础语法
<Pannel></Pannel> //自定义组件
import Pannel from './components/Pannel' export default { components:{ Pannel: pannel } }
2.组件概念:
-
组件是可复用的Vue实例,封装标签,样式和JS代码
-
组件化:封装的思想,在页面上'可重用的部分''封装为'组件',从而方便项目的开发和维护
组件中name属性的作用
注册时可以定义自己的名字 用组件对象的name属性的值
3.基本使用4步
-
创建组件,封装要复用的标签,样式,JS代码
-
引入组件
-
注册组件
-
全局注册-main.js中
import Vue from 'vue' import 组件对象 from 'vue文件路径' Vue.component("组件名",组件对象)
//在.vue文件中直接使用<>
-
局部注册-某vue文件内
import 组件对象 from 'vue文件路径' export default { components: { "组件名": 组件对象 } }
-
4. 使用组件
4.组件内的scoped 是如何工作的?
-
当我们用scoped修饰style后,webpack打包时会给组件内标签添加随机哈希值属性 data-v-hash
-
获取:css选择器都被添加[data-v-hash属性]
5.组件通信
1.组件通信---父传子
-
父引入子eg:
-
父:App.vue
-
子:MyProduct.vue
-
1.步骤
-
子组件内,定义变量,准备接收,然后使用变量
<template> <div class="my-product"> <h3></h3> </div> </template> <script> export default { //虽然是字符串,但是是定义的属性名 props: ['title','price','info'] } </script>
-
父组件
<template> <div> <Product title="好吃的口水鸡" price="50" intro="开业大酬宾,全场8折"></Product> <Product title="好可爱的可爱多" price="20" intro="老板不在家,全场1折"></Product> <Product title="好贵的北京烤鸭" price="290" :intro="str"></Product> </div> </template> <script> export default { data(){ return { str: "好哦贵啊.快来啊,好吃" } } } </script>
会渲染不同的数据
-
父传子口诀(步骤)
-
子组件内,props定义变量,在子组件使用变量
-
父组件内,使用子组件,属性方式给props变量传值
-
2.父传子-配合循环
...
-
注意事项:
每次循环,变量和组件,都是独立的
2.组件通信--单向数据流
-
从父到子的数据流向,叫单项数据流
-
原因:
-
子组件修改,不通知父级,造成数据不一致性
-
Vue规定props里的变量,本身是只读的(不允许重新赋值)
-
3.组件通信--子向父_自定义事件
-
认识:子组件触发父自定义事件方法
-
步骤
-
父组件内,绑定自定义事件和事件处理函数
语法:@自定义事件名="父methods里 函数名"
<MyProduct @subprice="fn"> </MyProduct>
fn(参数,参数){ ... }
-
子组件内,恰当的时机,触发父给子绑的自定义事件,导致父methods里的时间处理函数执行
<button @click="subFn"> </button>
subFn(){ this.$emit("subprice",参数,参数) }
-
-
什么时候使用子传父技术 ?
当子想要去改变父里的数据
4.组件通信-跨组件传值--EventBus事件总线
-
常用于跨组件通信时使用
-
语法
-
src/EventBus/index.js - 创建空白Vue对象并导出
import Vue from 'vue' export default new Vue() //导出空白对象
引入空白对象
import eventBus from ''
-
在要接收值的组件(List.vue) eventBus.$on('事件名',函数体)
created(){ eventBus.$on('send',(index,price) => { console.log(index,price); }) }
-
在要传递值的组件(MyProduc.vue) eventBus.$emit('事件名',值)
kanFn(){ eventBus.$emit('send',this.index,this.price-1) }
-
4.生命周期
-
八个方法,四个阶段
-
从创建到销毁的整个过程-vue实例的生命周期
1.钩子函数
-
Vue框架内置函数,随着组件的生命周期阶段自动执行
-
场景:组件创建完毕后,可以在created生命周期函数中发起Ajax请求,从而初始化data数据
-
分类:四大阶段8个方法
-
初始化 beforeCreate created
-
挂载 beforeMount mounted
-
更新 beforeUpdate updated
-
销毁 beforeDestroy destroyed
-
1.初始化阶段
-
1.beforeCreate
-
new Vue()以后,vue内部给实例对象添加了一些属性和方法,data和method初始化"之前"
beforeCreate(){ console.log(this.msg) //undefined }
-
-
2.created
-
data和method初始化之后
-
场景:网络请求,注册全局事件
-
能获取data,不能获取真实DOM(只是实例化对象,与页面编译还没有关系)
created(){ console.log(this.msg) //渲染的值 }
-
2.挂载阶段
-
问题1:template里写的是真是的DOM吗--不是
template中写的只是模板语法,浏览器不认识,会被编译成虚拟DOM,然后才被替换成真实DOM
-
获取真实DOM阶段
-
挂载步骤
-
template选项检查
-
虚拟DOM挂载成真是DOM之前
-
beforeMount - 生命周期函数被执行
-
Create - 把虚拟DOM和渲染的数据一并挂载到真实DOM上
-
真实DOM挂载完毕
-
mounted - 生命周期钩子函数被执行
-
1.beforeMount
-
真实DOM挂载之前
-
场景:预处理data,不会触发updated钩子函数
beforeMount(){ console.log(ument.getElementById("myP")) //null }
-
-
2.mounted
-
真实DOM挂载之后
-
挂载后真实DOM
mounted(){ console.log(document.getElemtById("myP")) // <p...></p> }
-
3.更新阶段
-
data数据更新
-
步骤
-
当data数据改变,更新DOM之前
-
beforeUpdate - 生命周期钩子函数被执行
-
虚拟DOM重新渲染,打补丁到真实DOM
-
updated - 生命周期钩子函数被执行
-
当data数据改变,重复这个循环
-
-
1.beforeUpdate()
-
当data数据未改变时不会被触发,只有data数据改变才会执行
-
-
2.updated()
-
场景:获取更新后的真实DOM
-
4.销毁阶段
-
步骤
-
当$destroy()被调用 - 比如组件DOM被移除(例v-if)
-
beforeDestroy - 生命周期钩子函数被执行
-
拆卸数据监听器,子组件和时间侦听器
-
实例销毁后,最后触发一个钩子函数
-
destroyed - 生命周期钩子函数被执行
-
-
1.beforeDestory
-
场景:移除全局事件,移除当前组件,计时器,定时器,eventBus溢出时间$off方法
beforeDestory(){ clearInterVal(this.timer) }
-
-
2.destoryed
destoryed(){ clearInterVal(this.timer) //写到上面下面无区别 }
-
一般在beforeDestroy/destroyed里做什么?
手动消除计时器/定时器/全局事件
5.axios使用
1.介绍
-
ajax是什么
一种前端异步请求后端的技术
-
ajax原理?
浏览器window接口的XMLHttpRequest
-
axios是什么
-
axios是一个专门用于发送ajax请求的库
-
基于原生ajax+Promise技术封装通用于前后端的请求库
-
-
特点
-
支持客户端发送Ajax请求
-
支持服务器Node.js发送请求
-
支持Promise相关用法
-
支持请求和响应的拦截器功能
-
自动转换JSON数据
-
-
axios底层还是原生js实现,内部通过Promise封装的
axios({ method: '请求方式', //get post url:'请求地址', data:{ //拼接到请求体的参数,post请求的参数 xxx: xxx }, params:{ //拼接到请求行的参数,get请求的参数 xxx: xxx } }).then(res=>{ console.log(res.data) //后台返回的结果 }).catch(err => { console.log(err) //后台报错返回 })
...未完待续
6.ref
1.ref获取原生DOM元素
-
$emit,$on都是vue实例(组件)内置的方法属性
-
而vue内置方法属性:
-
Vue中如何获取真实DOM元素
-
原生:使用ducment.getElementById()
-
Vue:通过id或ref属性获取原生DOM
-
-
在mounted生命周期 - 2种方式获取原生DOM标签
-
目标标签 - 添加id/ref
<h1 ref="myH1" id="h"></h1>
-
恰当时机,通过id/通过ref属性获取目标标签
mounted(){ console.log(document.getElementById("h")) console.log(this.$refs.myH1) }
-
2.ref属性_通过ref属性获取组件对象
-
id不可获取到组件对象,只能获取到原生对象
-
获取组件对象只能用ref
-
步骤
-
创建Demo组件,写一个方法
-
App.vue使用Demo组件,给ref属性 - 名字随意
<Demo ref="de"></Demo>
-
恰当时机,通过ref属性 获取组件对象 可调用组件对象里的方法等
this.$refs.名字
mounted(){ this.$refs.de.fn() }
获取组件对象,就可调用组件对象中的一切
-
3.nextTick基础使用
1.问题
vue监测数据更新,开启一个DOM更新队列,而这是异步任务
vue更新DOM是异步的!
<p ref="myP" @click="btn">{{ count }}</p>
methods: { btn(){ this.count++; console.log(this.$refs.myP.innerHTML) //发现并没有改变 } }
2.解决
-
语法 this.$nextTick
-
等DOM更新后,触发此方法里的函数体执行
methods: { btn(){ this.count++; this.$nextTick(() => { console.log(this.$refs.myP.innerHTML() }) //渲染更新后DOM元素 } }
3.可以在哪俩个地方访问到更新后的DOM呢?
-
this.$nextTick里的函数体
-
updated生命周期钩子函数
4.使用场景
-
点按钮输入框出现并聚焦
-
先this.$nexTick,再this.$ref调用.focus()
-
$nextTick函数原地返回什么
Promise对象