初始Vue
- 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象
- root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法
- root容器里的代码被称为vue模板
- Vue实例和容器是一一对应的
- 真实开发中只有一个Vue实例,并且会配合组件一起使用
- {{xxx}}中的xxx要写js表达式,并且xxx可以自动读取到data中的所有属性,一旦data中的数据发生改变,那么模板中用到该数据的地方也会自动更新
- js表达式和js语句的区别:表达式:一个表达式会产生一个值,并且可以放在任何一个需要值的地方,如:a,q+b,function(1),x===y?a:b;js语句:if(),for()
<body>
<div id="root">
<h1>hello,{{name}}</h1>
</div>
<script>
Vue.config.productionTip = false //防止vue在启动时生成生产提示
//创建Vue实例
const x = new Vue({
el:'#root', //el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串
data:{ //data中用于存储数据,数据供el所指定的容器去使用
name:"呵呵世界"
}
})
</script>
</body>
模板语法
- 插值语法:
功能:用于解析标签体内容
写法:{{xxx}},xxx是js表达式,并且可以直接读取到data中的所有属性 - 指令语法:
功能:用于解析标签(包括:标签属性,标签体内容,绑定事件...)
举例:v-bind:href="xxx" 或 简写成 :href="xxx",xxx同样要写成js表达式,并且可以直接读取data值的所有值
数据绑定
vue中有两种数据绑定的方式
- 单向绑定(v-bind):数据只能从data流向页面
- 双向数据流(v-model):数据不仅能从data流向页面,还能从页面流向data
1.双向绑定一般懂用于表单类元素上(如:input,select等),2.v-model:value 可以简写成v-model,因为v-model默认的是value的值
el与data的两种写法
- el的两种写法:a:new Vue()的时候配置el属性,b:先创建Vue实例,随后通过vm.$mount("#root")指定el的值
- data的两种写法:a:对象式,b:函数式.如何选择:在组件中写的时候必须用函数式,否则会报错.
一个重要的原则:由Vue管理的函数,一定不要写成箭头函数,一旦写成箭头函数,this的指向就不再是Vue实例了
Object.defineProperty
<script>
let number = 18
let person = {
name:'张三',
sex:'男',
}
Object.defineProperties(person,'age',{
// value:15,
// enumerable:true, //控制属性是否可以枚举,默认false
// writeable:true, //控制属性是否可以被修改.默认fasle
// configurable:true,//控制属性是否可以被删除.默认false
get(){ //当有人读取person的age属性值时,get函数(getter)就会被调用,且返回值就是age的值
console.log("有人读取age属性了")
return number
},
set(value){ //当有人修改age属性时,set函数(setter)就会被调用,切会收到修改的具体值
console.log("有人修改了age的值,且值是",value)
number = value
}
})
</script>
数据代理
- 通过一个对象代理对另一个对象中属性的操作(读/写)
let obj = {x:100}
let obj2 = {y:200}
Object.defineProperties(obj2,'x',{
get(){
return obj.x
},
set(value){
obj.x = value
}
})
console.log(obj2.x) //输出结果为100
obj2.x = 300,
console.log(obj.x) //输出值为300 直接打印obj也可以看出
//上述代码通过数据代理,通过obj2就可以操作obj中x的值
Vue中的数据代理
- 1.Vue中的数据代理:通过vm对象来代理data对象中属性的操作(读/写)
- 2.Vue中数据代理的好处:更加方便的操作data中的数据
- 3.基本原理:通过Object.defineProperties()把data中的所有属性添加到vm身上.为每一个添加vm身上的属性都指定一个对应的setter和getter.在getter和setter内部去操作(读/写)data中对应的属性
常见指令
- 事件处理v-on:xxx
事件的基本使用:1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名.2.事件的回调需要配置在methods对象中,最终会在vm上.3.mehods中配置的函数,不要用箭头函数,否则this就不是vm了.4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象.5.@click="demo"和@click=demo($event)效果一样,但后者可以传参
<!-- <button v-on:click="showinfo"></button>
<button v-on:click="showinfo1($event,66)"></button> -->
<button @click="showinfo"></button>
<button @click="showinfo1($event,66)"></button>
<!-- v-on:click可简写成@click -->
vue中的事件修饰符
- prevent 阻止默认事件(常用)
- stop 阻止冒泡事件(常用)
- once 事件只触发一次(常用)
- capture 使用事件的捕获模式
- self 只有event.target是当前操作的元素时才触发事件
- passive 事件的默认行为立即执行,无需等待事件回调执行完毕
键盘事件
- enter 会车键
- delete 删除
- esc 退出
- tab 换行(特殊,必须配合keydown使用)
计算属性与监视
<body>
<div id="root">
<p>{{fullName}}</p>
</div>
<script>
const vm = new Vue({
dta:{
firstName:"张",
lastName:"三"
},
//计算属性
computed:{
//完整写法
// fullName:{
// get(){
// return this.firstName + '-' + this.lastName
// },
// set(value){
// const arr = value.split('-')
// this.firstName = arr[0]
// this.lastName = arr[1]
// }
// },
//如果没有set至于get的话以简写
fullName(){
return this.firstName + '-' + this.lastName
}
}
})
</script>
</body>
深度监视
- vue中的watch默认不监测对象内部值的改变(一层)
- 配置deep:true可以检测对象内部的改变(多层)
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="ishot = !ishot"></button>
</div>
<script>
const vm = new Vue({
dta:{
ishot: false,
numbers:{
a:1,
b:2
}
},
//监视,不仅可以监视普通的属性,也可以监听计算属性
watch:{
// ishot:{
// // immediate:true, //初始化时让handler调用一次,默认为fasle
// handler(newVlaue,oldValue){
// console.log("ishot被修改了",newValue,oldValue)
// }
// },
//监视属性简写(ishot的监听)
ishot(newVlaue,oldValue){
console.log("ishot被修改了",newValue,oldValue)
},
//监视numbers中a的变化
'numbers.a':{
handler(newVlaue,oldValue){
console.log("numbers.a被修改了",newValue,oldValue)
}
},
//只有有对象中有属性变化就监听(深度监听)
numbers:{
handler(newVlaue,oldValue){
deep:true, //开启深度监听. 默认是false
console.log("numbers被修改了",newValue,oldValue)
}
}
}
})
// //还可写到vm外面
// vm.$watch('ishot',{
// handler(newVlaue,oldValue){
// console.log("ishot被修改了",newValue,oldValue)
// }
// })
</script>
</body>
computed和watch的区别
1.computed能完成的功能,watch都可以完成,2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作
两个重要小原则
1.所被vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象
2.所有不被vue所管理的函数(定时器的回调函数,ajax的回调函数,promise的回调函数)
,最好写成箭头函数,这样this的指向才是vm或组件实例对象
绑定样式
- class样式
:class="xxx", xxx可以是字符串,对象,数组.字符串写法用于:类型不确定,需要动态获取.对象写法适用于:要绑定多个样式,个数不确定,名字也不确定.数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用 - style样式
:style = "{fontSize:xxx}" 其中xxx是动态值.:style='[a,b]' 其中a,b是样式对象
<body>
<div id="root">
<!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定-->
<div class="basic" :class="mood" @click="changeMood">{{name}}</div><br/><br/>
<!-- 绑定class样式--数组写法,适用于绑定样式的个数不确定,名字也不确定 -->
<div class="basic" :class="classArr">{{anme}}</div><br/><br/>
<!-- 绑定class样式--对象写法,适用于绑定样式的个数确定,名字也确定,但要动态决定用不用 -->
<div class="basic" :class="classObj">{{anme}}</div><br/><br/>
<!-- 对象形式或者这样写 -->
<div class="basic" :class="{'style1':false,'style2':true}">{{anme}}</div><br/><br/>
<!-- 内联样式style绑定--对象写法,key中不能有-连字符,省去连字符,后面字母大写 -->
<div class="basic" :style="{fontSize : a+'px'}">{{anme}}</div><br/><br/>
<!-- 或者这样写 -->
<div class="basic" :style="styleObj">{{anme}}</div><br/><br/>
<!-- 内联样式style绑定--数组写法,数组中包括的是多个对象 -->
<div class="basic" :style="[styleObj,styleObj2]">{{anme}}</div><br/><br/>
</div>
<script>
// ps:normal,style1,style2,style3为类名,有具体的样式
const vm = new Vue({
dta:{
name:"小镇做题家",
mood:"normal",
classArr:['style1','style2','style3'],
classObj:{
style1:false,
style2:true
},
a:40,
styleObj:{
fontSize:'35px'
},
styleObj2:{
backgroundColor:'red'
}
},
methods: {
changeMood(){
this.mood = "style1"
}
},
})
</script>
</body>
条件渲染 v-show v-if
v-show是在样式上隐藏disply:none,v-if直接不创建这个组件.在开发中如果切换频率高的显示和隐藏用v-show
列表渲染 v-for
可以遍历数组,字典,字符串,指定次数
<body>
<div id="root">
<h2>人员列表</h2>
<ul>
<!----遍历数组>
<li v-for='p in persons' :key="p.id">
<!--可以接收两个参数,第一个参数是item,第二个参数是index-->
<!--<li v-for='(p,index) in persons' :key="index">-->
{{p.name}}---{{p.age}}
</li>
</ul>
</div>
<script>
const vm = new Vue({
dta:{
persons:[
{id:"001",name:"小李",age:18},
{id:"002",name:"小红",age:19},
{id:"003",name:"小张",age:20},
],
car:{
name:'奔驰',
price:'30万',
color:"红色"
}
}
}
})
</script>
</body>
Vue中key的作用
key是虚拟Dom对象的标识,当数据发生变化时,Vue会根据新数据生成新的虚拟Dom,随后Vue进行新虚拟Dom与旧虚拟Dom的差异比较,比较规则如下:
- 旧虚拟Dom中找到了与新虚拟Dom相同的key:1.若虚拟Dom中内容没有变化,直接使用之前的真实Dom.2.若虚拟Dom中内容变化了,则生成新的真实Dom,随后替换掉页面中之前变化的真实Dom
- 旧虚拟Dom中未找到与新虚拟Dom相同的key:创建新的真实Dom,随后渲染到页面
Vue监视数据的原理
1.vue会检测data中的所有层次的数据
2.如何检测对象中的数据
通过setter实现监视,且要在new Vue的时就传入检测的数据
- 对象中后裔追加的属性,Vue默认不做响应式处理
- 如需给后添加的属性做响应式,请使用如下API:
Vue.set(target,propertyName/index,value)或者Vue.$set(target,propertyName/index,value)
3.如何检测数组中的数据?
通过包装数组更新元素方法的实现,本质上就是做了两件事
- 1.调用原生对应的方法对数组进行更新
- 2.重新解析模板,进而更新页面
4.在Vue中修改数组中的某个元素一定要用如下方法(不要用下标赋值的方法去做):
1.使用这些API:push(),pop(),shift(),splice(),sort(),reverse()
2.Vue.set() 或 Vue.$set()
特别注意:Vue.set()和Vue.$set()不能给vm或者vm的根元素(data)添加属性
input表单有关
- 若:<input type="text"/>,则v-model收集的是vlaue值,用户输入的就是value
- 若:<input type="radio"/>,则v-model收集的是value值,且要给标签配置value值
- 若:<input type="checkbox"/>
1.没有配置input的value值,那么收集的就是checked(勾选 或 未勾选,是布尔值)
2.配置input的value值:
(1)v-model的初始值是非数组,那么收集的就是checked(勾选 或 未勾选,是布尔值)
(2)v-model的初始值是数组,那么收集的就是value值组成的数组
v-model的三个修饰符:lazy:失去焦点再收集数据.number:输入字符串转为有效的数组.trim:输入收尾空格过滤
过滤器
定义:对现实的数据进行特定格式化后再显示(适用于一些简单的逻辑处理)
语法:
1.注册过滤器:Vue.filter(name,callback) 或 new Vue{ filter:{} }
2.使用过滤器:{{xxx | 过滤器名}} 或v-bind:"xxx | 过滤器名"
备注: 1.过滤器也可以接收额外的参数,多个过滤器也可以串联.2.并没有改变原本的数据,是产生新的对应的数据.(过滤器的值是挨个传递的,第一个过滤器返回的值作为第二个返回值的参数使用值)
<body>
<div id="root">
<h2>过滤器,显示格式化之后的时间</h2>
<h3>现在的时间是:{{time}}</h3>
<h3>现在的时间是):{{time | timeForamter}}</h3>
<h3>现在的时间是:{{time | timeForamter('YYYY_MM_DD') | mySlice}}</h3>
<h3 :msg="msg | amySlice"></h3>
</div>
<script>
const vm = new Vue({
dta:{
time:16358527825,
msg:"你好,世界啊"
},
// 局部过滤器
filters:{
timeForamter(value,str='YYYY年MM月DD日 HH:mm:ss'){
// time作为参数value的值
return dayjs(value).format(str)
},
mySlice(){
return value.slice(0,4)
}
}
})
//全局过滤器
Vue.filters('amySlice',function(value){
return value.slice(0,4)
})
</script>
</body>
内置指令
- v-text:向其所在的节点中渲染文本内容,与插值语法的区别:v-text会替换掉节点中的内容,{{xxx}}则不会
- v-html:像指定节点渲染包含html结构的内容.ps:v-html有安全性问题,容易导致xss攻击(获取到网站上的cookie)
- v-cloak:可以通过设置属性形式[v-cloak]的display:none在数据未加载之前隐藏节点,避免出现插值语法
- v-once:只渲染一次
- v-pre:预编译指令,跳过其所在的节点编译过程(不会解析节点所在的插值语法,指令语法)
自定义指令
<body>
<!--
需求一:定义一个v-big指令,和v-text功能类似,但回把绑定的数值放大10倍
需求二:定义一个v-fbind指令,和v-bind功能类似,但可以让其绑定的input元素默认获取焦点
自定义指令总结:
一.定义语法:
1.局部指令: new Vue({
directives:{
指令名:配置对象
}
})
或者 new Vue({
directives(){
}
})
2.全局指令:
Vue.directive(指令名,配置对象) 或者 Vue.directive(指令名,回调函数)
二.配置中常用的三个回调:
1.bind:指令与元素绑定时调用
2.inserted:指令所在的元素被插入页面时
3.update:指令所在的模板结构被重新解析时调用
三.备注:
1.指令定义时不用加v-,但使用时需要加v-.
2.指令如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名
-->
<div id="root">
<h2>{{name}}</h2>
<h2>当前的值是:<span v-text="n"></span></h2>
<h2>增加10倍的值是:<span v-big="n"></span></h2>
<button @click="n++"></button>
<input type="text" v-fbind:value='n' />
</div>
<script>
const vm = new Vue({
dta:{
name:"世界你好",
n:1
},
// 注意:自定义指令里面的this都是window,不是vm
directives:{
// big函数何时会被调用?1.指令与元素成功绑定时(一上来).2.指令所在的模板被重新解析时
big(element,binding){
// element指令所在的真实dom,binding是个对象,其中value是绑定的值
console.log('big')
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
element.focus()
}
}
}
})
// --------------------------------------------------------------------------
// 全局的自定义指令写法
Vue.directive("fbind",{
// 指令与元素绑定成功时调用
bind(element,binding){
element.value = binding.value
},
// 指令所在元素被插入页面时(获取焦点看,拿到父元素)
inserted(element,binding){
element.focus()
},
// 指令所在的模板被重新解析时
update(element,binding){
element.value = binding.value
element.focus()
}
})
Vue.directive('big',function(element,binding){
console.log('big')
element.innerText = binding.value * 10
})
</script>
</body>
生命周期
常用的生命周期钩子:
1.mounted:发送ajax请求,启动定时器,绑定自定义事件,订阅消息[等初始化操作]
2.beforeDestroy:清除定时器,解绑自定义事件,取消订阅消息等[收尾工作]
关于销毁Vue实例:
1.销毁后借助Vue开发者工具看不到任何消息
2.销毁后自定义事件会失效,但原生的Dom事件依然有效
3.一般不会在beforeFestory操作数据,因为即便操作数据,也不会再触发更新流程
//无法通过vm访问data中的数据,methods中的方法
beforeCreate() {
},
//可以通过vm访问到data中的数据,methods中配置的方法
created() {
},
// 此时1.页面呈现的是未经Vue编译的Dom结构.2.所有对Dom的操作,最终都不奏效
beforeMount() {
},
//Vue完成模板的解析,并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted.此时1.页面中呈现的是经过Vue编译的Dom.2.对Dom的操作均有效(尽可能避免).
//至此初始化过程结束,一般在此进行:开启定时器,发送网络请求,订阅消息,绑定自定义事件等初始化操作
mounted() {
},
//此时:数据是新的,但页面是旧的,即:页面尚未和数据保持同步
beforeUpdate() {
},
// 此时:数据是新的,页面也是新的.即:页面和数据保持同步
updated() {
},
// 此时:vm中所有的:data,methods,指令等等.都处于可用状态,马上要执行销毁过程.一般在此阶段:关闭定时器,取消订阅消息,解绑自定义事案件等收尾操作
beforeDestroy() {
},
// 销毁完毕
destroyed() {
},
组件
实现应用中局部功能代码和资源的集合.分为非单文件组件和单文件组件.非单文件一般是在html中包含很多组件.单文件组件一般是值一个.vue文件就是一个组件
使用(非单文件组价)组件的步骤:
- 1.创建组件
//Vue.extend()可以省略
const school = Vue.extend({
// 注意Vue2只允许也有个根标签
template:`
<div>
<h3>{{schoolname}}</h3>
<h3>{{schooladdress}}</h3>
</div>
`,
// 组件中的data必须用函数式,不然不能保证数据修改不互相影响
data() {
return {
schoolname:'上海高级中学',
schooladdress:'青浦区十二河西路45号'
}
},
})
- 2.注册组件
const vm = new Vue({
dta:{
name:"世界你好",
n:1
},
// 此处为局部注册
components:{
school:school
}
})
//全局注册
vue.component('school',school)
- 3.使用组件
<div id="root">
<school></school>
</div>
- 关于组件名的注意点:
一个单词组成的:school,School.多个单词组成的my-school,MyScool(需要脚手架支持)
关于VueComponent
- 1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
- 2.我们只需要写<school/>或<school></school>,Vue解析时会帮助我们创school的实例对象,即帮助我们执行:new VueComponent(optios)
- 3.特别注意:每次调用Vue.extend({}),返回的都是一个全新的VueComponent
- 4.关于this的指向
(1).组件配置中:
data函数.methods函数,watch中的函数,computed中的函数,他们的this均是(VueComponent实例对象)
(2).new Vue()配置中:
data函数.methods函数,watch中的函数,computed中的函数,他们的this均是(Vue实例对象)
- 5.Vuecomponent的实例对象,以后简称VC(也可成为组件实例对象).vue的实例对象简称VM
Vue中重要的内置关系
- 1.VueComponent.prototype.proto === Vue.prototype
- 2.为什么有这个内置关系:让组件的实例对象(vc)可以访问到Vue原型上的属性和方法
//参考原型
//实例的隐式原型属性永远指向自己缔造者的原型对象
//定义一个构造函数
function Demo(){
this.a = 1
this.b = 2
}
//创建一个demo的实例对象
const d = new Demo()
console.log(Demo.prototype) //显式原型属性(只有函数才有的)
console.log(d.__proto__) //隐式原型属性(对象中有的)
//指向同一个原型对象
console.log(Demo.prototype === d.__proto__) //输出true
//程序员通过显式原型属性操作原型对象,追加一个x属性,值为99
Demo.prototype.x = 99
// 下面两种写法一样
console.log(d.__proto__.x)
console.log(d.x)
单文件组件(xxx.vue)
//快捷键<v
<template>
<!-- 组件结构 -->
<div class="demo">
<h2>学校名字:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<button @click="tipClick">点我</button>
</div>
</template>
<script>
// 与组件交互相关的代码(数据,方法等)
// 注意:这里采用默认暴露的方式:export default,此处也省略了Vue.extend()
export default {
name:'school', //组件的名字,在开发者工具中会显示这个名字
data() {
return {
name:"第一初级中学",
address:"上海市海防大学路"
}
},
methods: {
tipClick(){
alert("哈哈哈")
}
},
}
</script>
<style>
/* 样式 */
.demo{
background-color: aquamarine;
}
</style>
ref属性
- 被用来给元素或子组件注册引用信息(通过id获取元素的替代者)
- 应用在html标签上获取的是真实的DOM元素,应用在组件标签上是组件实例对象(vc)
- 使用方式:
打标识:<h1 ref="xxx">...</h1> 或者<HelloWorld ref="xxx"></HelloWorld>
获取:this.$refs.xxx
<template>
<div id="app">
<h1 ref="title">略略略</h1>
<HelloWorld ref="hell"/>
<button @click="btnClick">点我</button>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
},
methods:{
btnClick(){
console.log(this.$refs.title) //输出真实Dom元素<h1>略略略</h1>
console.log(this.$refs.hell) //输出HelloWorld组件的VueComponent对象(vc)
}
}
}
</script>
props属性
让组件接收外部传过来的数据
- 1.数据传递
<Demo name="xxx" />
- 2.接收数据
第一种方式(只接受):
props:['name']<br/>
第二种方式(限制类型):
props:{
name:String
}
第三种方式(限制类型,限制必要性,指定默认值):
props:{
name:{
type:String, //类型
require:true, //必要性
default:'老王' //默认值
}
}
props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告.若业务需求确实要修改,那么请复制props的内容到data中一份,然后去修改data中的数据
mixin 混入
// mixin.js把公共的抽离出来
export const hunhe = {
data:{
x:10,
y:100
},
//methods中的方法如果和被混入对象中的方法一样时,以被混入对象的为准
methods:{
click(){
console.log('点击了')
}
},
//和被混入对象中的钩子函数都调用
mounted(){
console.log('这是钩子函数')
}
}
//-------------------------
//组件vc
// 1.导入 2.使用
import { hunhe } from '../mixin.js'
{
data:{
name:小明
},
//以数组形式加入混合
mixins:[ hunhe ]
methods:{
},
mounted(){
}
}
插件
功能:用于增强Vue
本质:傲寒install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据.
定义插件:
//plugis.js
export default {
inastall (Vue,options){
//1.添加全局过滤器
Vue.filter(...)
//2.添加全局指令
Vue.directive(...)
//3.配置混入对象
Vue.mixin(...)
//添加实例方法
Vue.prototype.$myMethod = function(){...}
Vue.prototype.$myProperty = xxx
}
}
使用插件:
导入 import plugin from '../plugins.js'
//用Vue.use(插件名)
Vue.use(plugin)
scoped样式
作用:让样式在局部生效,防止冲突.
写法:<style scoped>
浏览器的本地存储(localStorage,sessionStorage)
//存储
localStorage.setItem(key,value) //key和value必须都是字符串
//读取
localStorage.getItem(key)
//删除
localStorage.removeItem(key)
//清空
localStorage.clear()
//ps:sessionStorage和localStorage的用法一样,只不过浏览器关闭sessionStorage会被清除,而localStorage不会被清除
组件的自定义事件
- 一种组件间通信的方式,适用于:子组件 ===>父组件
- 使用场景:A是父组件,B是子组件,B想给A传数据,那么就在A中给B绑定自定义事件(事件的回调在A中)
//通过父组件子组件传递函数类型的props事件(函数回调传值),子给父传递数据
<School :getSchoolName='schoolNameMthod' />
//通过父组件给子组件定义一个自定义事件实现:子给父传递数据(使用V-on或者@)
<Studen @myClcik="clickMthods" /> //子组件通过this.$emit('myClcik',"666","888"),后面参数也可以包装成一个对象
//通过父组件给子组件绑定一个自定义事件:子给父传递数据(使用ref)
<HelloWoreld ref='hell' /> // this.$refs.hell.$on('监听的事件名',function(){
//注意:如果函数直接写在这里,以普通函数的写法去写,那这里的this是HelloWoreld的VueComponent(vc).解决办法:第一种箭头函数,第二种可以把这个函数拆分到methods中去
})
//解绑自定义事件
this.$off('clickMthods') //解绑一个
this.$off(['clickMthods','schoolNameMthod']) //解绑多个
this.$off() //解绑所有的自定义事件
组件绑定原生事件,如@click,系统会判定会这是一个自定义事件,想要原生事件生效,应该用native修饰.@click.native='xxx'
全局事件总线(GlobalEventbus)
- 1.一种组件间通信的方式,适用于任意组件间通信
- 2.安装全局事件总线:
new Vue({
.....
beforeCreate(){
Vue.prototype.$bus = this //暗转全局事件总线,$bus就是当前应用的vm
}
})
- 3.使用事件总线
1.接收数据:A组件想接受数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身
methods(){
demo(prams){
.....
}
....
mounted(){
this.$bus.$on('xxx',this.demo)
}
}
2.提供数据:this.emit('xxx',传递的数据)
- 4.最好在beforeDestory钩子中,用$off去解绑当前组件所用到的事件
消息的订阅与发布
-
1.一种组件间通信的方式,适用于任意组件
-
2.使用步骤:
1.安装pubsub:npm i pubsub-js
2.引入:import pubsub from 'pubsub-js'
3.接收数据:A组件想接受数据,则在A组件中订阅消息,订阅的回调留在A组件自身.methods(){ demo(parmas){ .... } .... mounted(){ this.pid = pubsub.subscribe('xxx',this.demo) }, deforeDestory(){ Pubsub.unsubscribe(this.pid) } }
4.提供数据:pubsub.publish('xxx',数据)
5.最好在deforeDestory钩子中,用Pubsub.unsubscribe(pid)去取消订阅nextTick
- 1.语法:this.$nextTick(回调函数)
- 2.作用:在下一次DOM更新结束后执行其指定的回调
- 3.什么时候调用:当改变数据后,要基于更新后的新DOM进行某些操作时(如输入框的失去焦点),要在nextTick所指定的回调函数中执行
Vue封装的过渡和动画
作用:咋插入和移除DOM元素时,在合适的时候给元素添加样式类名
写法(-).准备好样式: 元素的进入样式 1.v-enter:进入的起点 2.v-enter-active:进入过程中 3.v-enter-to:进入的终点 元素离开的样式: 1.v-leave:离开的起点 2.v-leave-active:离开过程中 3.v-leave-to:离开的终点 (二)使用<transition>包裹要过渡的元素,并配置name属性 <transition name="hello"> <h1 v-show='isShow'>你好啊</h1>
</transition>
(三)若有多个元素需要过渡,则需要使用:<transition-group>,且每个元素都要指定key值
> 项目中可以用第三方动画库,如:animate.css
#### 配置代理(解决跨域问题)
什么是跨域:当一个请求url的协议,域名.端口号三者之间任意一个与当前页面url不同即为跨域
- 方法1:在Vue.config.js中添加如下配置
devServer:{
proxy:'http://localhost:5000'
}
//说明:
1.优点:配置简单,请求资源时直接发给前端(8080)即可
2.缺点:不能配置多个代理,不能灵活的控制请求是否走代理
3.工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器
- 方法2:编写vue.config.js配置具体代理规则
module.exports= {
devServer:{
proxy:{
'/api1':{//匹配所有以'/aopi1'开头的请求
target:"http://localhost:5000",//代理目标的基础路径(不要写后面的路径了)
ws: true,// 是否启用websockets
changeOrigin: true,//是否开启代理
pathRewrite:{ 'api1':'' }//匹配以api开头的路径替换成空字符串
}
}
}
}
#### 插槽slot
1.作用:让父组件可以让子组件指定位置插入html结构,也是一种组件间通信的方式,适用于父组件===>子组件<br/>
2.分类:默认插槽,具名插槽,作用域插槽<br/>
3.使用方式:<br/>
-.默认插槽:
父组件:
<Catergory>
<div>html结构1</div>
</Catergory>
子组件:
<template>
<div>
<slot>默认插槽内容</slot>
</div>
</template>
二.具名插槽
父组件:
<Catergory>
<template slot="center">
<div>html结构1</div>
</template>
<template slot="footer">
<div>html结构1</div>
</template>
</Catergory>
子组件:
<template>
<div>
<slot name="center">默认插槽内容</slot>
<slot name="footer">默认插槽内容</slot>
</div>
</template>
三.作用域插槽
//理解:数据在组件自身,但根据数据生成的结构需要组件的使用者来决定.
父组件:
<Catergory>
<template slot-scope="data>
<ul>
<li v-for="g in scopeData.games" :key="g">{{ g }}</li>
</ul>
</template>
<template slot="footer">
<ul>
<h4 v-for="g in scopeData.games" :key="g">{{ g }}</h4>
</ul>
</template>
</Catergory>
子组件:
<template>
<div>
<slot :games="games"></slot>
</div>
</template>
<script>
export default {
name:"Category",
data(){
return{
games:['海贼王',"猫和老鼠","大话西游"]
}
}
}
</script>
#### vuex
专门在vue中实现集中式状态,数据管理的一个vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间的通信方式,且适用于任意组件间的通信<br/>
1.//创建文件:src/store/index.js
//引入vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用插件(需要在stroe实例创建前使用,不然会报错)
Vue.use(Vuex)
//准备actios对象----响应组件中用户的动作
const actions = {}
//准备mutatios对象---修改state中的数据
const mutatios = {}
//准备state对象---保存具体的数据
const state = {}
//准备getters---用于将state中的数据进行加工
const getters = {}
//并暴露store
export default new Vuex.store({
actions,
mutations,
state,
getters
})
2.在main.js中创建vm时传入store配置项
//引入store
import store from './store'
...
//创建vm
new Vue({
el:'#app'
render:h=>h(App)
store
})
#### 路由
1.理解:一个路由就是一组映射关系(key-vlaue),多个路由需要路由器(router)进行管理<br/>
2.前端路由:key是路径,vlaue是组件<br/>
##### 基本使用
1.安装vue-router,命令: npm i vue-router<br/>
2.应用插件:Vue.use(VueRouter)<br/>
3.编写router配置项
//引入VueRouter
import VueRouter from 'vue-router'
//引入组件
import About from '../components/about'
import Home from '../components/home'
//创建router实例对象,去管理一组一组的理由规则
const router = new vueRouter({
routes:[
{
path:"/about",
component:About
},
{
path:"/home",
component:Home
},
]
})
//暴露router
export default router
4.实现切换(active-class可配合样式进行高亮显示等)<br/>
<router-link active-class="active" to="/about"></router-link>
5.指定展示位置
<router-view></router-view>
网友评论