vue学习记录第四天

钩子函数的生命周期

根实例,在初始化时会调用很多方法,这些方法被称为钩子函数
生命周期:beforeCreate created beforeMount mounted beforeUpdate updated beforeDestory destoryed

beforeCreate(){},此时只有内部方法

此方法一般用不到

create(){}

获取ajax,初始化操作

beforeMount(){}编译前的操作,也没有什么实际意义

一定要保证有编译的元素el,否则会中断
挂载el,也可以使用

new Vue().mount('#app')

如果有实例template属性,会用模板替换掉外部html,只要有此属性,app中的内容没有任何意义,template中只能有一个根元素。

let vm=new Vue(){
el:"#app",
template:"
{{a}}
", data:{a:1 }}

之前第三天的时候又提到过,DOM中也有一个tempelate标签,是没有任何意义,用来包裹元素的。

mounted(){} 操作DOM

用编译好的el替换掉el,然后调用mounted()
真实dom渲染完了可以操作dom了

beforeUpdate(){}

当数据变化的时候,调用beforeUpdate()

updated(){}

一般用watch来替换,watch能够更准确的知道是谁更新了。

beforedestory(){}销毁前,可以清除定时器,或清除事件绑定

destoried(){}销毁后

watch,computed以及方法全部被销毁

实例上的方法

this.$data vm上的数据
this.$watch 监控
this.$el 当前el元素
this.$set 后加的属性实现响应式的变化
this.$options 获取vm中所有的属性
this.$nextTick(){} 异步方法,可以等待dom完成后获取vm,是当前代码全部执行完毕后,执行
另外dom渲染是异步的,想要数据变化后想获取真实dom中的内容,必须使用nextTick
this.$refs 所有refs的集合,假如有一个标签 ref="myp" 可以直接通过this.$ refs.myp。ref 被用来给DOM元素或子组件注册引用信息。如果dom元素不是通过v-for循环出来的,只能获取一个,通过v-for则可以获取多个,输出为数组

组件

可以将很复杂的页面分割成若干个独立组件,每个组件包含自己的逻辑和样式
减少逻辑复杂度,实现了代码的重用

页面级组件:1、一个页面是一个组件
2、将可复用的部分抽离出来,作为基础组件

优点

  1. 提高开发效率
  2. 方便重复使用
  3. 便于协同开发
  4. 更容易被管理和维护

Vue的组件

一个自定义的标签Vue就会把它看成一个组件
div p span a header section都是W3C规定的,不是自定义的标签,但是Vue可以给它们赋予一定的意义

全局组件

声明一次,可以在任何地方使用
一般使用局部组件,写插件的时候使用全局组件
之前Vue.filter("函数名",函数)全局过滤器

全局组件的基本形式

一个对象可以看成是一个组件

    Vue.component('polarbear',{
      //一个对象可以看成一个组件
      template:'
{{msg}}
', //只能是一个根元素 //相当于用这个模板替换这个标签 //组件名不要带有大写,多个单词用- //只要组件名和定义名字相同是可以的(首字母可以大写) //html采用的短横线隔开命名法 js中转驼峰也是可以的 data(){ //组件中的数据必须是函数类型的,返回一个实例作为数组的实例 return {msg:'大白白熊'} } })

组件名

组件名不要带有大写,有多个单词用-
只要组件名和定义名字相同是可以大写的,但是只有首字母可以大写
html采用的短横线隔开命名法,js的转驼峰法也可以

template属性

DOM中的template是一个没有意义的标签,用来框东西
这里的template会给出一个DOM模板,替换标签中的内容
只能是一个根元素

template:'
{{msg}}
'

data

组件中的函数必须是函数类型的,并且返回一个实例作为数组的实例

DOM

大白熊

虽然DOM中是大白熊,但是polarbear的template属性给出了内容为大白白熊,所以页面中的内容会被替换

局部组件

必须告诉这个组件是属于谁的

三步骤

  1. 创建这个组件
  2. 注册这个组件
  3. 引用这个组件

创建组件

和创建Vue的过程相似,但是要记住组件的data是函数,需要返回一个形式与Vue data形式相同的对象

    let polarbear={
      template:'
大白白熊
', data(){ return {msg:'大白白熊'} } }; let penguin={ template:'
企鹅
' };
  1. 如果组件共用了数据,数据会同时刷新,而组件的特点就是独立性,所以最好不要
  2. 子组件不能直接使用父组件的数据
  3. 组件理论上可以无限嵌套

注册组件

在Vue实例中添加一个components属性

    let vm=new Vue(
    {
      el:"#app",
      data:{
        a:1
      },
      components:{
        polarbear,
        penguin
        //它们的parent是vm
        //不能跨作用域调用vm的data,组件相互独立不能直接跨作用域 vm的实例也是一个组件
        //也拥有生命周期函数
      },
    }
    )
  1. 在哪里注册组件,这些组件的父组件就是谁
  2. 但是组件是不能调用父组件的数据的,polarbear和penguin都不能调用a
  3. 这些组件也有生命周期函数

DOM的写法

除了直接在DOM中写,也可以在Vue实例中添加

template:''

注意以上这种写法是不会显示企鹅的,因为polarbear会替换掉标签之中的所有内容包括penguin

组件之间引用

如果要在一个组件中使用另一个组件

  1. 首先必须要保证使用的组件真实存在
  2. 在需要引用这个组件的实力上通过components注册这个组件
  3. 组件需要在父级的模板中通过标签的
    形式引入
    let littlebear={
      template:"
小白熊
" }; let polarbear={ template:'
白熊
', components:{littlebear} }; let bigbear={ template:'
大白熊
', components:{polarbear} }; let vm=new Vue( { el:"#app", components:{bigbear}, template:"" }

最终显示结果是大白熊 白熊 小白熊
除了标签的简单引用,想要数据之间的引用就需要使用其他的方法了

父传子

父亲定义好数据,通过属性的方式传递给孩子
以父亲给孩子零花钱为例

  1. 首先父亲中要有money这个数据
  2. 孩子通过DOM获取

DOM中数据传递

    
父亲给了{{money}}

这里有标签的相关知识,在一个标签中

  1. key:value形式,前面的key是当前组件的属性,后面value是父级标签的值
  2. 如果不使用冒号的方式,传递的值会变为字符串格式,使用冒号,值会变为属性的形式
    如果上文中
    :m="money"改为m="money"
    那么m是字符串money

props属性

props中的数据可以是数组,也可以是对象
但是不能和data中的名字相同,校验时不能阻断代码的执行,只是进行警告

单向数据流

prop使得父子prop之间形成了单向下行绑定,父级prop的更新会向下流动到子组件中。

prop:['m']

会在当前子组件上声明一个m属性,值是父亲的
m不能直接写m必须写成字符串格式

m可以直接用,但是不能改,只能通过data或者compute计算新的值

computed:{
money(){
return this.m
}}

这时

child:{
          template:'
儿子 {{money}}
', //props:['m'], computed:{ money(){ return this.m } }

显示结果为儿子获得50

props校验功能

可以使用对象的形式进行校验

type

校验属性的类型

type可以师原生构造函数中的一个
String,Number,Boolean,Array,Object,Date,Function,Symbol

如果传递的属性类型不正确,只会warn并不会报错

default

默认值,如果没有传数据过来,自动取默认值

required

当这个属性为true时,此属性必须传递,不传就报warn,不能和default同时使用
不传递的时候显示会是false

validator(val){}

自定义校验器
第一个参数是当前传递的值
返回true则表示通过,false为不通过
但是false也只是warn,不报错

      props:{
        //属性名和data中的名字不能相同,校验时不能阻断代码的执行,只是进行警告
        m:{
          //校验属性的类型,如果不带冒号,得到的是字符串
          type:[String,Boolean,Function,Object,Arrey,Number],
          //对象的形式可以进行校验
          //默认值,如果不传的话,自动取默认值
          default:0,
          //required:true
          //此属性必须传递,不传就报warn,现在{{money}}显示为false,但是不能和default同时使用
          validator(val){
            //第一个参数是当前传递的值
            //返回true表示通过
            //false表示不通过
            //依然只是warn,自定义校验器,用的不是很多
            return val>300
          }
        }
      }

全部程序

  
    
{{money}}

发布订阅模型

发布emit 订阅 on
说白了就是触发和绑定
利用这两个事件,可以创建一对多的关系
实例,创建一个{日常行为:['睡觉','游泳','吃海豹']}

function polarbear(){
  this._events={}
  //下划线表示是私有的
  //{日常行为:['睡觉','游泳','吃海豹']}
}
let pb=new polarbear()

on

为polarbear绑定on,emit事件
因为是所有实例共用的,所以放在原型上

polarbear.prototype.on=function(eventName,callback){
  if(this._events[eventName]){
    //不是第一次
    //不能用点,点是返回字符
 this._events[eventName].push(callback)
  }
  else{
    this._events[eventName]=[callback]
  }
}

为日常行为绑定相关事件

let sleep=(who)=>{console.log(who+"睡觉")}
let swim=(who)=>{console.log(who+"游泳")}
let eat=(who)=>{console.log(who+"吃海豹")}
pb.on('日常行为',sleep);
pb.on('日常行为',swim);
pb.on('日常行为',eat);

emit

原型绑定

polarbear.prototype.emit=function(eventName,...args){
  if(this._events[eventName])
  {
this._events[eventName].forEach(cb=>cb(...args)))
    //cb.apply(this,args)
    //展开数组
    //只运行数组第一项
  }
}

这个过程是将emit后面的值赋给前面的事件
因为参数的数量不确定,使用ES6中的...args,将剩余的参数作为数组args存储

pb.emit('日常行为','我','熊大','熊二');

最终运行结果 我睡觉 我游泳 我吃海豹,如果想要每一个都运行,还是要取args.length去做

子传父

通过事件,子触发父的事件,传递数据
儿子不能改变父亲的值,但是可以告诉他让他改
父亲绑定一些事件,儿子触发这个事件,将参数传递过去,单向数据流,父亲数据刷新,儿子也随之刷新
子传父超复杂,饶了180个弯

  1. 首先既然触发父的事件,那父亲里必须有这个事件
  2. 然后得把这个事件绑定到子组件上
  3. 绑定后还要触发这个事件,让父亲的方法执行
  4. 那触发这个事件还要在子组件上定义一个事件

事件绑定儿子上

    
父亲给{{money}} 儿子得

changemoney是父亲的事件,childmessage属于儿子
相当于child.on('childmessage',changemoney)

父亲事件定义

    methods:{
      changemoney(val){
        this.money=val
      }
    }

儿子上的事件

template:'
'

触发儿子自定义事件,父亲的方法被执行

              getmoney(){
                //触发自己的自定义事件,让父亲的方法执行
                this.$emit('childmessage',800)
              }

将800的值传递给childmessage,通过触发childmessage事件,执行父组件的changemoney,最终money被改变为800
全部程序



  
    
    
  
  
    
父亲给{{money}} 儿子得

.sync的用法 语法糖

.sync修饰符
是一种双向绑定
但是双向绑定会带来一定维护的问题
sync修饰符相当于将emit处的方法名改变为update:m

  

然后再子组件

              getmoney(){

                this.$emit('update:m',800)
              }

模态框实例

这个实例是点击主界面上的按钮弹出警告框,然后点击警告框上的关闭按钮,关闭这个警告窗
需要利用bootstrap的警告框,子组件向父组件传递事件,父组件向子组件传递数据

  1. 父组件中定义flag属性,true的时候显示警告窗,false时不显示
  2. 将flag传递到子组件
  3. 子组件关闭按键按下时触发自定义事件执行父组件的改变flag的方法


  
    
    
    
  
  
    

你可能感兴趣的:(vue学习记录第四天)