1.简单理解
1.必须创建一个Vue实例,且要传入一个配置对象;
2.这里使用的实例通常用id="xxx",在new Vue({el:'#xxx',})中指定为那个容器服务;
3.root容器里的代码被称为Vue模板
4.Vue实例和容器是一一对应的;
5.真实开发中只有一个Vue实例,并且会配合着组件一起使用;
6.插值语法{{xxx}}中要写js表达式,且xxx会自动读取到data中的所有属性;
7.一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新;
2.模板语法
1. 插值语法:
功能:用于解析标签体内容。<标签>标签体</标签>
写法:{{xxx}}
2.指令语法:
功能:用于解析标签(包括标签属性、标签体内容、绑定事件..)。
举例:v-bind:href="xxx"====>简写:href="xxx",xxx也写为js表达式形式,会自动读取到data中的所有属性。不写:时,html自动按字符串形式进行解析。Vue中很多指令形式都是v-???。
3.数据绑定方式
单向绑定(v-bind)
只能从data流向页面
双向绑定(v-model)
数据不仅能从data流向页面,也能从页面流向data。但是一般都应用在表单类元素上(input/select等)。v-model:value====>v-model
4.data和el的两种写法
el
1)new Vue时直接配置
2)先创建Vue实例,再通过vm.$mount('#root')指定El的值
data
vue把data里的键值对看成vue的属性名和属性值
1)对象式
2)函数式
使用这种形式!!!不能写成箭头函数(只要vue所管理的函数),要不this指向就是Window;function指向就是vue
5.MVVM模型
M:模型model:data中的数据。
V:视图view:模板代码。
VM:视图模型viewmodel:Vue实例。
data的所有属性都出现在了VM身上。VM身上的所有属性及Vue原型上的所有属性,在Vue模板中都可以直接使用。
6.defineProperty
defineProperty带个参数是要修改的对象,第二个参数是要修改的对象的属性值,第三个参数是配置对象。get获取属性,set修改属性
7.数据代理
好处:更方便操作data中的数据,可以通过{{}}和指令方式直接修改,就不用再写_data了。
数据代理:通过vm对象代理data对象中的属性操作(读、写)
基本原理:通过Object.defineProperty()把data对象中所有属性添加到vm上,为每个添加到vm上的属性指定一个getter和setter。在getter和setter内部去操作读写data中对应的属性。画圈的那两条线才是真正的数据代理。
8.事件的基本使用
-
1)v-on:...=@...绑定事件,...是事件名;
-
2)事件的回调(绑定函数)需要配置在methods对象中,最终会在vm(vue实例)上;
-
3)methods中配置函数不要用箭头函数,否则this将指向window;
-
4)methods中配置的函数,都是被Vue所管理的函数,this指向是vm或组件的实例对象;
-
5)@click="demo"和@click="demo($event)"效果一致,但后者可传参。
如果想传参直接在事件回调后加小括号
事件修饰符
(@...后.修饰符,可以连续写:@...后.修饰符.修饰符):
-
1)prevent:阻止默认事件(常用
-
2)stop:阻止事件冒泡,写到里面的元素上(常用
-
3)once:事件只触发一次(常用
-
4)capture:使用事件的捕获形式;
-
5)self:只有event.target是当前操作元素时才触发事件;
-
6)passive:事件的默认行为立即执行,无需等待事件回调执行完毕
自定义事件绑定原生DOM事件
需要加.native修饰符修饰,本质是给子组件的根节点绑定了原生DOM事件---利用事件的委派
9.计算属性computed
定义:要用的属性不存在,要通过已有的属性(不是变量哦,是Vue控制下的属性)计算得来。
原理:底层借助了Objcet.defineproperity方法提供的getter和setter。 data和methods中的属性直接是vm的属性,但是computed的属性还要加个get(),调用时不要加小括号。
get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值。
get什么时候被调用?1.初次读取fullName时2.所依赖的数据发生变化时。(不发生变换连续调用时,使用缓存机制(复用),computed比methods更加高效,调试方便)
如果计算属性要被修改,必须写set函数去响应修改,且set中要引起计算时依赖的数据发生变化。
简写形式
绑定事件的时候:@xxx="yyy" yyy可以写一些简单的语句
10.监视属性watch(侦听属性)
1)当被监视的属性变化时,回调函数自动调用,进行相关操作
2)监视的属性必须存在,才能进行监视!
3)两种写法:
深度监视
1)Vue中的watch默认不检测对象内部值的改变(Vue自身可以检测对象内部值的改变,但watch默认不可以。使用watch时根据数据的具体结构决定是否采用深度监视)
2)配置deep:true可以检测对象内部值的改变(多层)
简写 代价就是不能配置deep和immediate
computed和watch的区别
1.computed能完成的功能,watch都能完成
2.watch能完成异步操作,computed不可以
两个重要的小原则:
1.所有被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象
2.所有不被Vue所管理的函数(定时器的回调函数、Ajax的回调函数、promise的回调函数),最好写成箭头函数,这样this的指向才是vm或组件实例对象(箭头函数没有构建自己的this,需要向上层查找,跟上层函数的this指向相同)
11.绑定class、style
绑定class三种写法:
绑定style: 注意Vue中的样式都是驼峰,动态变化的才写到Vue中
条件渲染
1.v-if v-else-if v-else
适用于切换频率较低的场景,不展示的DOM元素直接被移除,结构不能被打断。
2.v-show
适用于切换频率较高的场景,不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
template不改变CSS结构,只能与v-if组合使用,不能与v-show组合使用
12.表格数据
v-for指令:
1.展示列表数据
2.语法:v-for="(item,index) in/of xxx" :k="yyy"//in of等价
3.可遍历:数组、对象、字符串(用得少)、指定次数(用得少)
Key的内部原理
列表过滤
优先使用computed 简单
13.Vue监视数据的原理
1.Vue会监视data中所有层次的数据
2.如何检测对象中的数据?
通过setter实现监视,且要在new Vue时就传入要检测的数据
1)对象中后追加属性,Vue默认不做响应式处理
2)如需给后添加的属性做响应式,使用以下API:
Vue.set(target,propertyName/index,value)或者
vm.$set(target,propertyName/index,value)
3.如何检测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事:
1)调用原生对应的方法对数组进行更新。
2)重新解析模板,进而更新页面。
4.在Vue修改数组中的某个元素(响应式)一定要用如下方法:
1)使用pop()、push()、shift()、unshift()、splice()、sort()、reverse()【这7种方法都是对原数组进行修改】
使用filter()、concat()、slice()时不会变更原始数组,而是返回一个新数组。使用非变更方法时,可以用新数组替换旧数组。
2)Vue.set()或者vm.$set()
注意:Vue.set()或者vm.$set()不能给vm或vm的根数据对象(_data)添加属性
json转换成简单明了的对象
14.收集表单数据
若:type="text">,则v-model收集的是value值,用户输入的就是value值。
若:type="radio">,(单选框),则v-model收集的是value值,且要给标签配置value值。
若:type="checkbox">,勾选框
1)没有配置input的value属性,那么收集的就是checked(true or false 勾选或者未勾选)
2)配置了input的value属性,
1))v-model初始值是非数组,那么收集的就是checked(true or false 勾选或者未勾选) 2))v-model初始值是数组,那么收集的是value组成的数组
v-model的三个修饰符(v-model.xxx)
lazy:失去焦点再收集数据
number:输入字符串转为有效的数字
trim:输入收尾空格过滤
补充内容:过滤器
15.指令
不要乱加
补充JS知识,有些内容要放在插入element之后添加才有效:
自定义指令
1)定义语法
1))局部指令:
new Vue({
directives:{指令名:配置对象/回调函数}
})
2))全局指令:
Vue.dirctive(指令名,配置对象/回调函数)
2)配置对象中常用的3个回调:
(1)bind:指令与元素成功绑定时调用
(2)inserted:指令所在元素被插入页面时调用
(3)update:指令所在模板结构被重新解析时调用
备注:指令定义时不加v-,但使用时要加;如果是多个单词,用-连接,不要使用大写
16.生命周期
又名:生命周期回调函数、生命周期函数、生命周期钩子。
是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
生命周期函数名字不可更改,但函数的具体内容是程序员根据需求编写的。this指向是vm或组件实例对象。
常用的生命周期钩子:
1.mounted:发送Ajax请求、启动定时器、绑定自定义事件、订阅消息等初始化操作
2.beforeDestory:清除定时器、解绑自定义事件、取消订阅消息等收尾工作
关于销毁Vue实例
1.销毁后借助Vue开发者工具看不到任何信息
2.销毁后自定义事件会失效,但原生DOM事件依然有效。
3.一般不会在beforeDestory操作数据,因为即使操作数据,也不会再触发更新流程了。
17.组件
定义:实现应用中局部功能代码和资源的集合
三大步骤
1.定义组件(创建组件)2.注册组件3.使用组件(写组件标签)
1.定义组件?
使用Vue.extend(options)创建,其中options和new Vue(options)时传入的options几乎一样,区别:
el不要写————因为最终所有组件都要经过一个VM管理,由vm中的el决定服务哪个容器。
data必须写成函数————避免组件被复用时,数据存在引用关系。
备注:使用template可以配置组件结构。
2.注册组件
局部注册:靠new Vue时候传入components选项
全局注册:靠Vue.component('组件名',组件)
school:school==>school
3.编写组件标签
属性修饰符sync[组件通信方式的一种]
可以实现父子组件数据同步,:money.sync,代表父组件给字符串传递props[money]。给当前子组件绑定一个自定义事件(updata:money)
关于Vuecomponent:
- 1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。
- 2.我们只需要写或,Vue解析时会帮我们创建school组件的实例对象,即帮我们执行:new VueComponent(options)。
- 3.特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!
- 4.关于this指向:(1)组件配置中:data、methods、watch、component中的函数,this均是VueComponent实例对象(vc)(2)new Vue(options)中data、methods、watch、component中的函数,this均是Vue实例对象(vm)
vc不能使用el,vm可以,vc中data使用函数形式,其他相同。
attrs
他们二者都是组件实例的属性,可以获取到父组件给子组件传递props与自定义事件.attrs获取不到。$listeners可以获取到父给子传递的自定义事件。
parent
ref可以获得某一个组件。parent可以获得当前组件的父组件,进而操作其数据与方法
内置关系
回顾原型链
为什么要有这个关系:让组件实例对象vc可以访问到Vue原型上的属性/方法
17.单文件组件
index.html准备容器,App.vue综合其他vue,main.js入口文件,引入Vue
Vue.extend可省略。export default暴露(es6)。花括号里添加name:'尽量跟文件名一致'
18.脚手架
ref属性
1.被用来给元素或子组件注册引用信息(id的替代者)
2.应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
真实DOM元素:
组件实例对象:
配置项props
功能:让组件接收外部传过来的数据
1.只接收2.限制类型3.限制类型、限制必要性、指定默认值
props是只读的,如果进行修改,会发出警告。如果业务需求对其进行修改,那么复制props的内容到data中一份,再去修改data中的数据。
混入mixin
功能:可以把多个组件共用的配置提取成一个混入对象 定义混入,例如
{
data(){},
methods:{}
...
使用混入,局部混入
全局混入
Vue.mixin(xxx)
插件
功能:用于增强Vue
本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。
定义插件:
对象.install = function(Vue,options){
//添加全局过滤器
Vue.filter(...)
//添加全局指令
Vue.directive(...)
//配置全局混入
VUe.mixin(...)
}
添加实例的方法
Vue.prototype.$myMethod = function(){...}
Vue.prototype.$myProtoperty = xxx
scoped样式
作用:让样式在局部生效,防止多个components中样式的名字发生冲突
自己下载第三方库nanoid并使用他生成一个独一无二的id值
es6中的reduce
数组长度多少调用几次函数,pre是上一次的返回值,0是初始值。常用于做统计计数。
todolist小总结
1.组件化编码流程:
(1)拆分静态组件:组件要按照功能点拆分,命名不要与HTML元素冲突。
(2)实现动态组件:考虑好数据的存放位置,数据是一个组件在用(放在组件自身),还是一些组件在用(放在他们共同的父组件上---状态提升)
(3)实现交互:从绑定事件开始。
2.props适用于
(1)父组件==>子组件 通信
(2)子组件==>父组件 通信(要求父先给子一个函数)
3.使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的!
4.如果props传过来的值是对象类型的,修改对象中的值,不报错但不推荐。
webStorage
1.储存内容大小一般支持5mb左右(不同浏览器可能不一样)
2.浏览器端通过Window.sessionStorage和Window.localStorage属性实现本地储存机制
3.相关API
JSON.stringify把对象转换成字符串,JSON.parse把字符串转换成对象
4.sessionStorage存储的内容会随着浏览器窗口关闭而消失,localStorage存储的内容需要手动清除才会消失。
xxxxxxStorage.getItem(xxx)如果xxx对应的value获取不到,那么返回值是nullJSON.parse(null)的结果也是null。
19.子传父
父组件
子组件
补充:解绑
20.全局事件总线:任意组件间通信
在main.js中安装全局事件总线
21.消息订阅与发布
第三方库
21.nextTick
语法this.$nextTick(回调函数)
作用:在下一次DOM更新结束后执行其指定的回调
什么时候使用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。
22.动画
appear一开始就过度
第三方库
引入
import animate.css
23.发送axios
看到这两个关键词就知道代码违背了同源策略。
跨域的两个方法
都在vue.config.js中修改
方法1
优点:配置简单,请求资源时直接发给前端即可。
缺点:不能配置多个代理,不能灵活控制请求是否走代理。
工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器(优先匹配前端资源)
方法2
优点:可以配置多个代理,且可以灵活的控制请求是否走代理。
缺点:配置略繁琐,请求资源时必须加前缀
补充:es6模板字符串
${}里面的当语句解析
补充:es6的语法,后者对象里如果有跟前者对象里属性名相同的属性,属性值以后者为准,如果没有匹配,就保持前者不变。
5种方法
24.插槽
作用:让父组件可以向子组件指定位置插入HTML结构,是一种组件间通信,适用于父=>子
1.默认插槽
2.具名插槽
3.作用域插槽
理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定(games数据在category组件中,但是用数据所遍历出来的结构由APP组件决定)
slot-scope是scope的新写法
25.Vuex
概念
专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式管理(读、写),也是一种组件间通信的方式,适用于任意组件间通信。
什么时候使用Vuex
多个组件依赖于同一状态;来自不同组件的行为需要变更同一状态
补充:加冒号,引号里面的按JS表达式解析,所以当数字类型看。如果不加冒号(v-bind),加不加引号都是字符串类型。
action里写判断逻辑条件,mutation里写具体执行函数,vuex的开发者工具监视的是mutation.
如果逻辑太复杂,action里链式处理,通过dispatch传,但是传给mutation需要用commit
1.基本使用
2.组件中读取vuex中的数据$store.state.sum(在组件中获取不用加this,在JS脚本中需要添加)
3.组件中修改vuex中的数据$store.dispatch('action中的方法名',数据)或$store.commit('mutations中的方法名',数据)。一般action中的方法名小写,mutations中的方法名大写。
备注:若没有网络请求或其他业务逻辑,组件也可以越过actions,即不写dispatch,直接写commit。
getters的使用
1.概念
当state中的数据需要经过加工后再使用时,可以使用getters加工。
2.在store.js中追加getters配置
const getters = {
bigSum(state){
returen state.sum * 10
}
}
//创建并暴露store
export default new Vuex.Store({
.........
getters
})
3.组件中读取数据
$store.getters.bigSum
四种Map方法的使用
补充:es6中的...表示展开,把后面对象的属性键值对放入到computed对象中。不加引号就是寻找变量。属性的KEY值无论加不加引号都按字符串形式解析,不加引号是简写形式。es6中'sum'='sum'可简写成'sum'。
1.mapState
帮助我们映射state中的数据为计算属性
2.mapGetters
帮助我们映射getters中的数据为计算属性
3.mapActions
帮助我们生成与actions对话的方法,即:包含$store.dispath(xxx)的函数
4.mapMutations方法
帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数
store的模块化编码
目的:让代码更好维护,让多种数据分类更加明确
index.js开启命名空间
组件vue
或者直接拆分成不同js文件,然后在index.js中引用
26.路由
vue-router是vue的一个插件库,专门用来实现SPA(single page web application)应用
SPA
整个应用只有一个完整的页面。
点击页面中的导航连接不会刷新页面,只会做页面的局部更新。
数据需要通过ajax请求获取。
路由相关
一个路由就是一组映射关系(key-value),key为路径,value可能是function或component。
路由的分类
1.后端路由
value是function,用于处理用户端提交的请求。
工作过程:服务器接收到一个请求时,根据请求路径找到匹配的函数来处理请求,返回相应数据。
2.前端路由
value是component,用于展示页面内容。
工作过程:当浏览器路径改变时,对应的组件就会显示。
具体使用
几个注意点
路由组件通常存放在pages文件夹,一般组件通常存放在components文件夹。
通过切换,’隐藏‘了的路由组件,默认是被销毁的,需要的时候再去挂载
每个组件都有自己的$route属性,里面存储着自己的路由信息
整个应用只有一个router,可以通过组件的$router属性获取到
嵌套路由(多级路由)
children配置项,里面的path开头不需要加/
路径要把父级路由也写上
路由的query
传参:?key1=value1&key2=value2&...
路由命名
路由的params
特别注意:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置。
路由的props
补充:解构幅值的连续写法。在query中拿到id和title.
router-link 的replace属性
编程式路由导航
go里要写数字参数,可正可负,正是向前走,负是向后走
缓存路由组件
要在缓存的路由组件外侧包裹keep-alive,include=’组件名‘
两个新的生命周期钩子
路由守卫
作用
对路由进行权限控制
分类
1.全局守卫
全局前置守卫 全局后置守卫 to去哪 from从哪来 next放行
2.独享守卫
只有前置
3.组件内守卫
必须通过路由规则才能触发
路由的两种工作模式
27.UI组件库
main.js
babel.config.js