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

组件名

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

template属性

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

template:'<div>{{msg}}</div>'

data

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

DOM

<div id="app">
<polarbear>大白熊</polarbear>
</div>

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

局部组件

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

三步骤

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

创建组件

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

    let polarbear={
      template:'<div>大白白熊</div>',
      data(){
        return {msg:'大白白熊'}
      }
    };
    let penguin={
      template:'<div>企鹅</div>'
    };
  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></penguin></polarbear>'

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

组件之间引用

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

  1. 首先必须要保证使用的组件真实存在
  2. 在需要引用这个组件的实力上通过components注册这个组件
  3. 组件需要在父级的模板中通过标签的
    形式引入
    let littlebear={
      template:"<div>小白熊</div>"

    };
    let polarbear={
      template:'<div>白熊<littlebear></littlebear></div>',
      components:{littlebear}
    };
    let bigbear={
      template:'<div>大白熊<polarbear></polarbear></div>',
      components:{polarbear}
    };
    let vm=new Vue( 
    {
      el:"#app",
      components:{bigbear},
      template:"<bigbear></bigbear>"
}

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

父传子

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

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

DOM中数据传递

    <div id="app">
      父亲给了{{money}}
      <child :m="money/2"></child>
      <!--m是属于child的属性,1是属于父级的,当前组件的属性=父级的值-->
      <!--用冒号把值变成属性,不加冒号,money就变成字符串了,key:value,这里永远是字符串-->
    </div>

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

  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:'<div>儿子 {{money}}</div>',
          //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
          }
        }
      }

全部程序

  <body>
    <div id="app">
      {{money}}
      <child :m="money/2"></child>
    </div>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  <script>
    let vm=new Vue( //parent组件
    {
      el:"#app",
      data:{
        money:100
      },
      components:{
        child:{
          template:'<div>儿子 {{money}}</div>',
          computed:{
            money(){
              return this.m
            }
          },
      props:{
        m:{
          type:[String,Boolean,Function,Object,Arrey,Number],
          default:0,
          //required:true
          validator(val){
           return val>300
          }
        }
      }
      }
    }
    )
    </script>
  </body>

发布订阅模型

发布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. 那触发这个事件还要在子组件上定义一个事件

事件绑定儿子上

    <div id="app">
      父亲给{{money}}
      儿子得<child :m="money" @childmessage="changemoney"></child>
      </div>

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

父亲事件定义

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

儿子上的事件

template:'<div><button @click="getmoney()">多要钱</button></div>'

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

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

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

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="app">
      父亲给{{money}}
      儿子得<child :m="money" @childmessage="changemoney"></child>
      <!--child.on('childmessage',changemoney),把事件绑定在儿子上-->
      </div>
      <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!--父亲绑定一些事件,儿子触发这个事件,将参数传递过去,单向数据流,父亲数据刷新,儿子就刷新-->
    <!--儿子不能改父亲的值,但是可以告诉他,让他改-->
    <script>
      let vm=new Vue(
      {
        el:"#app",
        data:{money:400},
        components:{
          child:{
            template:'<div><button @click="getmoney()">多要钱</button></div>',
            props:['m'],
            methods:{
              getmoney(){
                //触发自己的自定义事件,让父亲的方法执行
                this.$emit('childmessage',800)
              }
            }
          }
        },
        methods:{
          changemoney(val){
            this.money=val
          }
        }
      }
      )
      </script>
  </body>
</html>

.sync的用法 语法糖

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

  <child :m.sync="money"></child>
<!--相当于<child :m="money" @update:m="val=>{this.money=val}"></child>-->

然后再子组件

              getmoney(){

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

模态框实例

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

  1. 父组件中定义flag属性,true的时候显示警告窗,false时不显示
  2. 将flag传递到子组件
  3. 子组件关闭按键按下时触发自定义事件执行父组件的改变flag的方法
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  </head>
  <body>
    <div id="app">
      <button @click="clickparent">弹</button>
        <modal :show="flag" @close="fn"></modal>
        <!--:show="flag"这是父传子,@close="fn"是子传父-->
      <!--如果show的值为true则显示,如果是false则隐藏 @close对应的函数是点击关闭按钮时触发的函数-->
      <!--<dialog :show="" @close="fn"></dialog>-->
    </div>
    <template id="dialog">
      <div class="container" v-show="show">
        <div class="row">
          <div class="col-md-6 col-md-offset-3">
              <div class="alert alert-danger" style="height:200px" role="alert">
                <button class="pull-right" @click="closealert">关闭</button>
              </div>
          </div>
        </div>
      </div>
    </template>
  </body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      let modal={
        template:'#dialog',
        props:['show'],//接收父组件的属性
        methods:{
        closealert(){
          this.$emit('close')
        }
        }
      }
      let vm=new Vue({
        el:"#app",
        components:{
        modal//名字不能叫dialog,原生已经占用了这个名字
      },
      data:{
        flag:false
      },
      methods:
      {
        clickparent(){
          this.flag=true
        },
        fn(){
          this.flag=false
        }
      }
      })
    </script>
</html>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容

  • # 传智播客vue 学习## 1. 什么是 Vue.js* Vue 开发手机 APP 需要借助于 Weex* Vu...
    再见天才阅读 3,525评论 0 6
  • vue概述 在官方文档中,有一句话对Vue的定位说的很明确:Vue.js 的核心是一个允许采用简洁的模板语法来声明...
    li4065阅读 7,185评论 0 25
  • 1.安装 可以简单地在页面引入Vue.js作为独立版本,Vue即被注册为全局变量,可以在页面使用了。 如果希望搭建...
    Awey阅读 10,989评论 4 129
  • 这篇笔记主要包含 Vue 2 不同于 Vue 1 或者特有的内容,还有我对于 Vue 1.0 印象不深的内容。关于...
    云之外阅读 5,044评论 0 29
  • 我想我已经工作了499.5天 我想,我应该已经工作了499.5天了吧 刚刚好 就在上周,参加了公司最后一批的现场招...
    胖啄木鸟阅读 262评论 0 0