之前做的笔记搬过来
Vue
介绍
- 组件化
- 声明式编码,让编码人员无需直接操作DOM,提高开发效率
- 使用虚拟DOM+优秀的Diff算法,尽量复用DOM节点
- Vue需要创建一个实例,且需要传入一个配置对象
- 容器代码依然符合html规范,混入了一些特殊的Vue语法;
- 容器中的代码被称为[Vue模板]
- Vue实例和容器是一一对应的
- 开发中只有一个Vue实例,并且会配合着组件一起使用
- {{XXX}}中要写JS表达式,且XXX可以自动读取到data中的所有属性
- 一旦data数据发生改变,页面会自动更新
区分代码和表达式
-
JS表达式: 是特殊的JS语句会产生一个值,可以放在任何需要值的地方:
- (1). a 变量里有值
- (2). a+b 加法运算表达式
- (3). demo(1) 函数调用表达式
- (4).x === y ? 'a' : 'b'
-
JS语句
- .if(){} 判断
- . for(){} 循环语句
实例(instance)和对象都是一一对应
入门
<div id="root">
<h1>Hello,{{name}}</h1>
<h1>年龄为:{{age}}</h1>
</div>
<script>
Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示
//创建Vue实例
const x = new Vue({
el: '#root',//el用于指定当前Vue实例为哪个容器服务,值通常为css选择器
data: {//data中用于存储数据,数据供el所指定的容器去使用,值暂时写成一个对象 以后是函数
name: '贾培东',
age: '20'
}
})
</script>
模板语法
-
插值语法
功能 : 用于解析标签体内容
写法 : {{xxx}},xxx是js表达式,可以直接读取到data中的所有值
-
指令语法
用于解析标签(包括:标签属性 标签体内容 绑定事件)
v-bind 单向数据绑定
数据绑定
- 单向绑定(v-bind):数据只能从data流向页面
- 双向绑定(v-modle)数据也可从页面流向data
双向绑定一般应用再表单元素类上
(如: input,selsct) v-model:value
可简写为v-model因为v-model默认收集value值
el与data的写法
1.el的两种写法
- new Vue对象时就配置el属性
- 先创建Vue实例,后面用 v.$mount('#选择器')指定el的值 优点是更灵活,mount有挂载的意思
2.data的两种写法
-
对象式 data{ 对象:'数据'}
-
函数式 先写一个函数 返回你要的对象
由Vue管理的函数 不要写成箭头函数,this就不在是Vue实例 而是 window
data:function(){ return{ 对象:'数据' } }
MVVM
-
M (model) : 对应data中的数据 Plain JS Object
V (view) : 模板 就是DOM
VM:(ViewModel)视图模型 : Vue 实例对象
Data Bindings 数据绑定 在模型中把数据放到指定位置
DOM Listeners 监听DOM的改变 返回数据给模型数据
数据代理
复习
1.Object.define(定义)property(属性)方法
用于给一个对象定义属性
let number = 18
let person = {
name:'张三',
sex:'男'
}
Object.defineProperty(person,'age',{value:18,
enumerable(可列举的):ture
//控制属性是否可以枚举,默认值是false
writable:ture//控制属性是否可以被修改
configurable:true//控制属性是否可以被删除
get:function('有人读取age属性了'){
ruturn number
}
//当有人读取person的age属性时,get函数(getter)就会被调用,且返回值是age的值 set修改用法和get一样
})
//添加了一个对象
/*这个方法传三个参数
第一个:给哪个对象添加属性
第二个:添加属性的名字
第三个:配置项 常用的有value
和直接添加的对象不同 这个age是不能被枚举的
就是参与遍历
*/
console.log(person)
1.定义:
通过一个对象代理另一个对象中属性的操作
通过vm对象来代理data对象中属性的操作(读/写)
2.优点:
更加方便的操作data中的数据
3.代理过程:
- 加工data
- vm._data = data
4.基本原理:
通过Object.defineProperty()把data对象中所有属性添加到vm的_data上.
为每一个添加到vm上的属性.都指定一个getter/setter.
在getter/setter内部去操作(读/写)data中对应的属性.
事件处理
v-on:的简写是 @
- 使用v-on:xxx 或 @xxx 绑定事件,xxx是事件名
- 事件的回调需要配置在methods对象中,最终会在vm上
- methods中配置的函数,不要用箭头函数!否则this就不是vm了
- methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象
- @click="demo" 和 @click="demo($event)"效果一致,但后者可以传参
const vm = new Vue({
el: '#root',
data: {
name: '贾培东',
},
methods: {
showInfo1(event) {
// console.log(event.target);
//console.log(this); 此处的对象是vm
alert('加油')
},
showInfo2(number) {
console.log(number);
// console.log(event.target);
//console.log(this); // 此处的对象是vm
alert('加大油')
}
}
})
事件修饰符
修饰符可以连续写
1.prevent: 阻止默认事件(常用)
2.stop:阻止事件冒泡(常用)
3.once:事件只触发一次(常用)
4.capture:使用事件的捕获模式
5.self:只有event.target是当前操作的元素时才触发事件
6.passive: 时间的默认行为立即执行
键盘事件
1.vue中常用按键别名:
- 回车 => enter
- 删除 => delete
- 退出 => esc
- 空格 => space
- 换行 => tab 会在按下就会切走 要用 ketdown
- 上下左右 up down left righ
键盘上每个按键都有自己的名字和编码
caps-look
<div id="root">
姓: <input type="text" v-model="firstName"> <br>
名: <input type="text" v-model="lastName"> <br>
全名: <span>{{fullName}}</span>
</div>
<script>
const vm = new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三'
},
computed: {
// 完整写法
// fullName: {
// // 当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
// // get什么时候调用? 1.初次读取fullName时. 2.所依赖的数据发生变化时.
// get() {
// console.log('get');
// return this.firstName + '-' + this.lastName
// },
// // 当fullName被修改时,调用set
// set(value) {
// console.log('set', value);
// const arr = value.split('-')
// this.firstName = arr[0]
// this.lastName = arr[1]
// }
// }
// 如果不需要修改计算属性set滴不要 简写
fullName: function () {
console.log('get被调用了');
return this.firstName + '-' + this.lastName //放在上面的时函数执行调用的结果
}
}
})
</script>
事件总结
修饰符可以连着写
计算属性
1.定义: 要用的属性不存在,要通过已有属性计算得来
2.原理: 底层借助了Object.defineproperty方法提供的getter和setter
3.get函数在最初读取 和 依赖的数据发生改变时调用
4.与methods实现相比,内部有缓存机制(复用),效率更高,调试方便
5.计算属性最总会出现在vm上, 如果计算属性要被修改,要写set
简写
监视属性
1.当监视属性变化时,回调函数自动调用
2.监视属性必须存在才能监视
// 监视属性的两种写法:
// 1.new Vue 时传入watch配置
// 2. 通过vm.$watch监视
const vm = new Vue({
el: '#root',
data: {
isHot: true,
},
computed: {
info() {
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather() {
this.isHot = !this.isHot
}
},
// watch: {
// info: {
// immediate: + true, // 初始化时让handler调用一下
// // 当isHot发生改变时 调用handler(){}
// handler(newValue, oldVlaue){
// console.log('info被修改了', newValue, oldVlaue)
// }
// }
// }
})
vm.$watch('isHot',{
immediate: true,
// 初始化时让handler调用一下
// 当isHot发生改变时 调用handler(){}
handler(newValue, oldVlaue){
console.log('info被修改了', newValue, oldVlaue)
}
})
深度监视
// 监视多级结构中某个属性的变化
'numbers.a':{
handler(){
console.log('a被改变了');
}
}
监视多级结构中所有属性的变化
numbers:{
deep:true,
handler(){
console.log('numbers改变了');
}
}
1.Vue中的watch默认不监测对象内部值得改变(一层)
2.配置deep:true可以监测对象内部多层得改变
监视属性简写
当配置项里只有 handler 时可以简写
// 监视属性简写1
isHot(newValue, oldVlaue){
console.log('info被修改了', newValue, oldVlaue)
},
// 监视属性简写2
vm.$watch('isHot',function(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue);
})
watch与computed之间的区别
computed行的wartch都行,watch行的computed不一定行 还有watch可以进行异步操作
绑定样式
<body>
<div id="root">
<!-- 绑定class样式--字符串写法, 适用于: 样式的类名不确定,需要动态指定 -->
<div class="basic" :class="mood" @click="changeMood">{{name}}</div><br>
<!-- 绑定class样式--数组写法, 适用于: 要绑定的样式个数不确定,名字也不确定 -->
<div class="basic" :class="classArr">{{name}}</div><br>
<!-- 绑定class样式--对象写法, 适用于: 要绑定的样式个数确定,名字确定,但要动态决定用不用 -->
<div class="basic" :class="classObj">{{name}}</div><br>
// :style="{fontSize: xxx}" 其中xxx是动态值
// :style="[a,b]" 其中a,b是样式对象
<div class="basic" :style="{styleObj}">{{name}}</div>
</div>
<script>
const vm = new Vue({
el:'#root',
data:{
name:'学习',
mood:'normal',
classArr:['atguigu1','atguigu2','atguigu3'],
classObj:{
atguigu1:false,
atguigu2:false,
},
styleObj:{
fontSize:'40px'
}
},
methods: {
changeMood(){
const arr =['happy','sad','normal']
const index = Math.floor(Math.random()*3)
this.mood = arr[index]
}
},
})
条件渲染
1.v-if 写法: 1.v-if="表达式" 2.v-else-if="表达式" 3.v-else="表达式"
适用于: 切换频率低的场景
特点: 不展示DOM元素直接移除
2.v-show="表达式"
适用于: 切换频率较高的场景
特点: 不移除 只是隐藏
列表渲染
v-for指令:
1.用于展示列表数据
2.语法: v-for="(item, index) in xxx" :key="yyy"
3.可遍历 数组 对象 字符串和指定次数
KEY的基本原理
<div id="root">
<!-- 遍历数组 -->
<button @click.conce='add'>添加一个老刘</button>
<ul>
<li v-for="(p,index) of personArr" :key="p.id">
{{p.name}}-{{p.age}}
<input type="text">
</li>
</ul>
<script>
new Vue({
el:'#root',
data:{
personArr:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20},
]
},
methods: {
add(){
const p = {id:"004",name:'老刘',age:'40'}
this.personArr.unshift(p)
}
},
})
-
虚拟DOM中KEY的作用: key是虚拟DOM对象的标识,当状态中的数据发生变化时,Vue会根据(新数据)生成(新的虚拟DOM),随后Vue进行 新旧虚拟DOM的差异比较
-
找到相同的KEY
- 虚拟DOM中内容没变,直接使用之前的真实DOM
- 如果改变了, 生成新的替换之前旧的
-
最好使用每条数据的唯一标识作为,key比如id,手机号,学号等 , 如果不存在数据的逆序添加,逆序删除等破坏顺序操作,仅用于渲染列表展示用index也无问题
列表过滤
<div id="root">
<!-- 遍历数组 -->
<input type="text" placeholder="请输入名字" v-model="keyWord">
<ul>
<li v-for="(p) in filPersonArr" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
<script>
// new Vue({
// el:'#root',
// data:{
// keyWord:'',
// personArr:[
// {id:'001',name:'马冬梅',age:28,sex:'女'},
// {id:'002',name:'周冬雨',age:19,sex:'女'},
// {id:'003',name:'周杰伦',age:20,sex:'男'},
// {id:'004',name:'温兆伦',age:22,sex:'男'},
// ],
// filPersonArr:[]
// },
// // watch:{
// // keyWord(val){
// // this.filPersonArr = this.personArr.filter((p)=>{ // p形参每一个人的对象
// // // fileter 筛选完后会返回一个全新的数组 不会改变原有数组
// // return p.name.indexOf(val) !== -1 // return返回的是你需要的
// // // indexOf 判断字符串里有没有指定val 返回的是字符所在的索引号
// // })
// // }
// watch:{
// keyWord:{
// immediate:true,
// handler(val){
// this.filPersonArr = this.personArr.filter((p)=>{
// return p.name.indexOf(val) !== -1
// })
// }
// }
// }
// })
// 计算属性
new Vue({
el:'#root',
data:{
keyWord:'',
personArr:[
{id:'001',name:'马冬梅',age:28,sex:'女'},
{id:'002',name:'周冬雨',age:19,sex:'女'},
{id:'003',name:'周杰伦',age:20,sex:'男'},
{id:'004',name:'温兆伦',age:22,sex:'男'},
],
},
computed:{
filPersonArr(){
return this.personArr.filter((p)=>{ // 第一个return是计算属性需要的
return p.name.indexOf(this.keyWord) !== -1 // 第二个return是filter决定的
})
}
}
})
列表排序
<div id="root">
<!-- 遍历数组 -->
<input type="text" placeholder="请输入名字" v-model="keyWord">
<button @click="sortType = 2">年龄升序</button>
<button @click="sortType = 1">年龄降序</button>
<button @click="sortType = 0">年龄原序</button>
<ul>
<li v-for="(p) of filPersonArr" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
<script>
new Vue({
el:'#root',
data:{
keyWord:'',
sortType:0, // 0表示原顺序 1表示降序 2表示升序
personArr:[
{id:'001',name:'马冬梅',age:28,sex:'女'},
{id:'002',name:'周冬雨',age:19,sex:'女'},
{id:'003',name:'周杰伦',age:20,sex:'男'},
{id:'004',name:'温兆伦',age:68,sex:'男'},
],
},
computed:{
filPersonArr(){
const arr = this.personArr.filter((p)=>{ // 第一个return是计算属性需要的
return p.name.indexOf(this.keyWord) !== -1 // 第二个return是filter决定的
})
// 判断一下是否需要排序
if(this.sortType){
arr.sort((p1,p2)=>{
return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age
})
}
return arr
}
}
})
监视数据的原理
我没怎么听懂,,,,,,
1.Vue会监视data中所有层次的数据
2.通过setter监视对象中的数据 , 且要在new Vue时就传入要监测的数据 如果需要给后添加的数据做响应式 使用一下API : Vue.set(target.propertyName/index.value)
3.通过包裹数组更新元素的方法 监视数组中的数据 本质就是: 调用原生对应的方法对数组进行更新 然后 重新解析模板更新页面
4.在Vue中修改数组中某个元素一定要用如下方法:
- API : push() pop() ... Vue.set() Vue.$set() 不能给vm 和vm的根数据对象 添加属性
Vue.set(target,key,val) 添加可以动态代理的对象
数组操作方法
push 后面添加
pop 后面删除
shift 首个删除
splice(0,1,'替换为')
收集表单数据
// 1.如果没有配置input的value属性,呢么收集的就是checked (勾选 or 未勾选 , 是布尔值)
// 2.配置input的value属性:
// v-model的初始值是非数组,呢么收集的就是 checked
// v-model的初始值是数组,那么收集的就是value组成的数组
// v-model的三个修饰符:
// lazy: 失去焦点再收集数据
// number: 输入字符串转为有效数字
// trim: 输入首尾空格过滤
<div id="root">
<form @submit.prevent="demo">
账号: <input type="text" v-model.trim="userInfo.account"> <br>
密码: <input type="password" v-model="userInfo.password"> <br>
性别:
男<input type="radio" name="sex" v-model="userInfo.sex" value="male">
女<input type="radio" name="sex" v-model="userInfo.sex" value="female"> <br>
爱好:
学习<input type="checkbox" v-model="userInfo.hobby" value="study">
吃饭<input type="checkbox" v-model="userInfo.hobby" value="game">
还是学习 <input type="checkbox" v-model="userInfo.hobby" value="eat"> <br>
所属校区
<select v-model="userInfo.city">
<option value="">请选择校区</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="shengzhen">深圳</option>
</select> <br>
其他信息:
<textarea v-model.lazy="userInfo.other"></textarea> <br>
<input type="checkbox" v-model="userInfo.agree"> 阅读并接受<用户协议>
<button>提交</button>
</form>
</div>
<script>
new Vue({
el:'#root',
data :{
userInfo:{
account:'',
password:'',
sex:'',
hobby:[],
city:'beijing',
other:'',
agree:''
}
},
methods: {
demo(){
console.log(JOSN.stringify(this.userInfo));
}
},
})
过滤器
定义 :对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)
语法:
1.注册过滤器 : Vue.filter(name,callback) 或 new Vue{filters:{ }}
2.使用过滤器: {{ xxx | 过滤器名}} 或 v-bind:属性 = "xxx | 过滤器名"
3.并没有改变原数据 产生新数据
内置指令
v-text : 向其所在的节点中渲染文本内容 与插值语法的区别: v-text会替换掉节点中的内容. {{xx}} 则不会
v-html : 向所在节点中渲染包含html结构的内容, v-html会替换掉节点中的内容 {{xx}}则不会 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击, 不要用在用户提交内容上
v-click : 没有值 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性 使用CSS配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题
v-once : v-once所在的节点在初次动态渲染后,就视为静态内容了 以后的数据的改变不会引起v-once所在结构的更新,可以用于性能优化
v-pre : 跳过其所在节点的编译过程 可以用它跳过 : 没有使用指令语法,没有使用插值语法的节点,会加快编译
自定义指令
定义语法:
局部指令:
new Vue({
directives:{指令名:配置对象}
})
或
new Vue({
directives:{指令名:回调函数} // 回调函数 我们定义的但是没执行 最终执行了
})
--------------------------------
全局指令:
Vue.directive(指令名,配置对象)
或
Vue.directive(指令名,回调函数)
// 配置对象中常用的三个回调
1.bind: 指令与元素成功绑定时调用
2.inserted: 指令所在元素被插入页面时调用
3.update: 指令所在的模板结构被重新解析时调用
// 指令名定义时不加 v-,但使用时要加v-
指令名如果是多个单词,要使用kebab-case(user-name)命名方式,不要使用camelCase(userName)命名
<body>
<div id="root">
<h2>当前的n值是: <span v-text="n"></span></h2>
<h2>放大十倍后的的n值是: <span v-big="n"></span></h2>
<button @click="n++">点我n+1</button>
<hr>
<input type="text" v-fbind:value="n">
</div>
</body>
<script>
new Vue({
el:'#root',
data:{
n:1
},
directives:{
big(element,binding){
element.innerText = binding.value * 10
},
fbind:{
// 当指令与元素成功绑定时(一开始)
bind(element,binding){
element.value = binding.value
},
// 指令所在元素被插入页面时
inserted(element,binding){
element.focus()
},
// 指令所在的模板被重新解析时
update(element,binding){
element.value = binding.value
}
}
}
})
</script>
生命周期
1.又名:生命周期回调函数,生命周期函数,生命周期钩子
2.是 Vue在关键时刻帮我们调用的一些特殊名称的函数
3.名字不可更改 , 具体内容由我们编写
4.生命周期函数中的this指向是vm或组件的实例对象
常用的有两个
1.mounted: 发送ajax请求,启动定时器,绑定自定义事件,订阅消息等初始化操作
2.beforeDestory: 清除定时器,解绑自定义事件,取消订阅
生命周期挂载流程
beforeCreate
create
beforeMount
mounted
生命周期更新流程
beforeUpdate 数据是新的 页面还是旧的
updata 数据也是新的
生命周期销毁
beforeDestory 销毁之前
destroyed
vm.$destroy() 完全销毁一个实例, 清理与其他实例连接,解绑所有指令及自定义事件监听器
组件
组件就是 实现应用中 局部 功能代码和资源的集合
使用组件的步骤:
1.定义组件(创建组件)
使用Vue.extend(options)创建
2.注册组件
局部注册: new Vue的时候传入components
全局注册: Vue.component('组件名',组件)
3.使用组件(写组件标签)
<组件名>
VueComponent构造函数
1.组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的.
2.我们只需要写<组件名/> Vue解析时会帮我们创建<组件>的实例对象,即Vue帮我们执行 new VueComponent(options).
3.每次调用Vue.extend时 返回的都是一个全新的VueComponent !
4.this指向:
- 组件配置中: data函数,methods中的函数,watch中的函数,computed中的函数 this均是VueComponent实例对象
- new Vue(options) 配置中: data函数,methods中的函数,computed中的函数, 他们的this均是Vue实例对象
Vue _rander函数
因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收到的createElement函数去指定具体内容
修改脚手架默认配置
props配置
让组件接受外部传来的数据
1.传递数据:
2.接收数据
- 只接收
props:['name']
- 限制类型
props:{
name:String
}
限制类型,限制必要性,指定默认值
- props:{
name:{
type:String,
required: true
default:'老王'
}
}
mixin混入
可以把多个组件共用的配置提取成一个混入对象
// 定义
{
data(){},
methods:{}
}
// 混入
全局混入: Vue.mixin(xxx)
局部混入: mixins:['xxx']
插件
用于增强Vue ,本质是包含install方法的一个对象, install的第一个参数是Vue,后面的参数是插件使用者传递的数据
对象.install = function (Vue,options){
// 添加全局过滤器
Vue.filter()
// 添加全局指令
Vue.directive()
// 配置全局混入
Vue.mixin
// 添加实例方法
Vue.prototype.$myMethos = function () {..}
Vue.prototype.$myProperty = xxx
}
TodoList案例
儿子给父亲传数据 父亲之前给儿子一个函数 然后儿子去调用
1.组件化编码流程:
-
拆分静态组件: 组件要按照功能点拆分,命名不要与html元素冲突
-
实现动态组件: 考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用
- 一个组件用就放在组件自身即可
- 一些组件放在共同的父组件上(状态提升)
-
实现交互: 从绑定事件开始
2.props适用于
- 父组件 ===> 子组件 通信
- 子组件 ===> 父组件 通信 (要求父先给子一个函数)
3.使用v-model时要切记 : v-model绑定的值不能是props传过来的值,因为props是不可以修改的
4.props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但是也不推荐
浏览器的本地存储
sessionStorage
localStorage
xxxxxStrage.setItem('key','value')
把键值对添加到存储中
xxxxxStrage.getItem('person')
接收一个键名作为参数,返回键名对应的值
xxxxxStrage.removeItem('key')
接受一个键名作为参数,并删除
SessionStorage存储会随着浏览器窗口关闭而消失
组件的自定义事件
-
组件间通信的方式,适用于 子组件 ===> 父组件
-
子组件想给父组件传数据,就要在父组件中给子组件绑定自定义事件(事件的回调在父组件中)
-
绑定自定义事件:
- 第一种方式,在父组件中:<Demo @thing="test">
- 第二种方式,在父组件中给子组件用ref打一个标识,之后父组件挂载之后
<Demo ref="demo"/> ... mounted(){ this,$refs.xxx.$on('thing',this.test) }如果想让自定义事件只能触发一次,可以使用once修饰符,或$once方法
-
触发自定义事件: this.$emit('thing',数据)
-
解绑自定义事件this,$off('thing')
-
组件上也可以绑定原生DOM事件,需要使用native修饰符
-
注意: 通过this.on('thing',回调)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题
全局事件总线
适用于任意组件间通信
1.安装
new Vue ({
......
beforeCreate(){
Vue.prototype.$bus = this // 安装全局事件总线,$bus就是当前应用的vm
}
})
2.使用
-
接收数据: A组件想要接收数据,就在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身
methods(){ demo(data){......} } ..... mounted() { this.$bus.$on('xxxxx',this,demo) } -
提供数据: this.on('xxxx',数据)
3.最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件
消息订阅与发布
需要数据的组件订阅消息,提供数据的人发布消息
nextTick
在下一次DOM更新结束后执行其指定的回调
Vue封装的过度与动画
1.作用: 在插入,更新或移除DOM元素时,在合适的时候给元素添加样式类名.
2.写法:
- 准备好样式;
- v-enter: 进入的样式
- v-enter-active: 进入过程中
- v-enter-to: 进入的终点
- v-leave-active; 退出过程中
进入的起点就是离开的终点,进入的终点就是离开的起点
3.使用包裹要过度的元素,并配置name属性
修改Vue打开端口
node_modules 下的 @Vue 中cli-service 下的commands 的 serve.js
插槽
作用: 让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式
1.默认插槽: 内容写在App中组件中用标签占个位
2.具名插槽: 给加name属性 给需要加入的标签加slot属性值时前面的name
3.作用域插槽
数据在组件自身,但根据数据生成的结构需要组件的使用者来决定
子组件里留插槽,放数据
Vuex
专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对Vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信
Vue router
\