vue的生命周期及组件之间的传值

9 篇文章 0 订阅

一、实例生命周期钩子

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

不同的钩子函数在实例生命周期的不同阶段被调用,如有beforeCreate、created、beforeMount、mounted、beforeUpdate、updated 、beforeDestroy和 destroyed。生命周期钩子的 this 上下文指向调用它的 Vue 实例。

  • beforeCreate:( 组件实例刚被创建,组件属性计算之前,$el data没有初始化)
  • created:(组件实例创建完成,属性已绑定,data 数据初始化,但是 DOM 未生成,$el 属性不存在 )
  • beforeMount:(模板编译/挂载之前,完成了 $el 和 data 初始化,但是这里的 el 还是 {{message}})
  • mounted:(模板编译/挂载之后,el的位置变成message的值)这里有个this.el的位置变成message的值)这里有个this.nextTick方法,适用于想操控真实DOM(因为有时mounted 会出现渲染未完成就执行方法)
  • beforeUpdate:(组件更新前)
  • updated:(组件更新后)
  • beforeDestroy:(组件销毁前)
  • destroyed:(组件销毁后)

案例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>life circle</title>
</head>
<body>
  <div id="app"></div>
  <script src="./lib/vue.js"></script>
  <script>
    var app = new Vue({
      el: '#app',
      created() {
        console.group('created!!');
        console.log(this.$el);
        console.groupEnd();
      },
      beforeCreate() {
        console.log('before create!!');
      },
      beforeMount() {
        console.log('before mount!!');
      },
      mounted() {
        console.group('mounted!!');
        console.log(this.$el);
        console.groupEnd();
      },
      beforeDestroy() {
        console.log('beforeDestroy!!')
      },
      destroyed() {
        console.log('destroyed!!')
      }
    })
  </script>
</body>
</html>

生命周期图示:
vue生命周期图
vue生命周期官方文档

二、组件之间的传值

1、组件基础:

组件是可复用的 Vue 实例,且带有一个名字。我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用。

这里有一个 Vue 组件的示例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>组件基础</title>
</head>
<body>
  <div id="app">
    <counter></counter>
  </div>
  <script src="./lib/vue.js"></script>
  <script>
    // 局部组件
    const Counter = {
      template: `<div>
          <button @click="countPlusHandle">计数器-{{count}}</button>
        </div>`,
      data() {
        return {
          count: 1,
        }
      },
      methods: {
        countPlusHandle() {
          this.count += 1;
        }
      },
      created() {
        console.log('init');
      }
    }
    //全局组件
    Vue.component('aaa', {
      template: `<h5>这是一个组件</h5>`
    })
    var app = new Vue({
      el: '#app',
      components: {
        Counter,
        HelloWorld: {
          template: `<h5>Hello World!</h5>`
        }
      }
    })
  </script>
</body>
</html>
  • template:表示组件在页面中渲染的时候使用的html模板内容;每一个组件只能有一个根节点 。
  • data:表示组件中使用的数据,组件中的数据必须是一个function,其返回值为data的值。
  • 可以在组件内部继续使用vue的其他方法比如:lifeCircle,filter,computed 在一个vue实例中。
  • 每一个组件都是独立存在的,它们都有自己一套固定的生命周期函数和data以及其他vue的可操作属性和方法。
  • 在vue中使用组件时需要先引入,通过在实例中使用components节点进行设置(注册)在vue中如果使用驼峰命名,在上面写html代码时,需要使用‘-’把单词做分割。

2、组件分为局部组件和全局组件
局部组件:
在vue中使用组件需要先引入,通过在实例中使用components节点进行注册
全局组件:
全局组件定义好之后可以直接使用 不需要在components中做注册
参数一: 组件的名字
参数二 :一个对象 用来设置组件的属性

3、组件之间的传值
组件实例的作用域是孤立的。这意味着不能在子组件的模块中直接引用父组件的数据,必须使用特定的方法才能实现组件之间的数据传递。

1.父组件通过props属性向子组件传递数据
关键词:添加属性 props
案例:父组件的step的值传给子组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"> 
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <counter :step="2"></counter>
    </div>
    <script src="./lib/vue.js"></script>
    <script>
        Vue.component('counter',{
           template:`<button @click="plusHandle">当前计数值: {{count}}</button>` ,
           data(){
               return {
                   count:0
               }
           },
           methods: {
               plusHandle(){
                   this.count+=this.step
               }
           },
           props:['step']
        })
        var app=new Vue({
            el:'#app',
        })
    </script>
</body>
</html>

2.子组件通过事件派发向父组件传递数据
关键词:$emit 定义方法
案例:子组件的count的值传给父组件

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>子组件向父组件传值</title>
</head>
<body>
    <div id="app">
        <h5>当前计数器的值为:{{c}}</h5>
        <counter @plusadd="plusAddHandle" :step="2"></counter>
    </div>
    <script src="./lib/vue.js"></script>
    <script>
        Vue.component('counter',{
           template:`<button @click="plusHandle">当前计数值: {{count}}</button>` ,
           data(){
               return {
                   count:0,
               }
           },
           methods: {
               plusHandle(){
                   this.count+=this.step;
                   this.$emit('plusadd',this.count);
               }
           },
           props:['step']
        })
        var app=new Vue({
            el:'#app',
            data:{
                c:0,
            },
            methods: {
                plusAddHandle(params){
                    this.c=params;
                }
            }
        })
    </script>
</body>
</html>

3.非父子组件之间的数据传递
关键词:$emit $on 空的vue对象
为了解决非父子组件之间的传值问题,引入事件总线
在vue中使用一个空白的Vue对象作为一个EventBus,用来做事件的监听和派发

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>动态组件</title>
</head>
<body>
  <div id="app">
    <navbar @pagchange="changePageHandle"></navbar>
    <component :is="currentPage"></component>
  </div>
  <script src="./lib/vue.js"></script>
  <script> 
    const Nav = {
      template:  `
      <div class="nav">
        <ul>
          <li><a :class="this.selIndex==0? 'cur': ''" @click="navClick(0, 'Home')">首页</a></li>
          <li><a :class="this.selIndex==1? 'cur': ''" @click="navClick(1, 'List')">商品列表页</a></li>
          <li><a :class="this.selIndex==2? 'cur': ''" @click="navClick(2, 'Cart')">购物车【{{cartCount}}】</a></li>
          <li><a :class="this.selIndex==3? 'cur': ''" @click="navClick(3, 'Us')">关于我们</a></li>
        </ul>
      </div>  `,
      data() {
        return {
          selIndex: 0,
          cartCount: 0
        }
      },
      methods: {
        navClick(index, page) {
          this.$emit('pagchange', page); // 子组件传值到父组件
          this.selIndex = index
        }
      },
      created() {
        this.$eventBus.$on('addToCartEvent', (id) => {
          this.cartCount += 1;
        })
      }
    }
    const Home = {
      template: `
      <div>
        <h1>我是首页</h1>
      </div> `
    }
    const List = {
      template: `
      <div>
        <div v-for="item in products" class="product">
          <h3>{{item.name}}</h3>
          <p>{{item.price}}<button @click="addToShopCart(item.id)">加入购物车</button></p>
        </div>
      </div>  `,
      data() {
        return {
          products: [{
            id: 1,
            name: 'iphone18',
            price: 19999,
          }, {
            id: 2,
            name: 'vivo 32',
            price: 5200
          }]
        }
      },
      methods: {
        addToShopCart(id) {
          this.$eventBus.$emit('addToCartEvent', id); // 使用$eventBus对象派发一个事件
        }
      }
    }
    const Cart = {
      template: `
      <div>
        <h1>我是购物车</h1>
      </div>  `
    }
    const Us = {
      template: `
      <div>
        <h1>关于我们</h1>
      </div> `
    }
    var $eventBus = new Vue(); // 使用一个空白的VUE实例作为中间媒介
    Vue.prototype.$eventBus = $eventBus; // 此种定义的属性可以在实例中进行访问
    var app = new Vue({
      el: '#app',
      components: {
        navbar: Nav,
        Home,
        List,
        Cart,
        Us
      },
      data: {
        currentPage: 'Home'
      },
      methods: {
        changePageHandle(page) {
          this.currentPage = page;
        }
      }
    })
  </script>
</body>
</html>

css:

 <style>
        html, body {
          margin: 0;
          padding: 0;
          width: 100%;
          height: 100%;
        }
        .nav {
          background-color: deeppink;
          padding: 1.5rem 1rem;
          height: 60px;
        }
        .nav ul {
          margin: 0;
          padding: 0;
        }
        .nav ul li {
          float: left;
          margin: 1.5rem;
          list-style: none;;
        }
        .nav a {
          color: #fff;
          cursor: pointer;
        }
        .nav a.cur {
          color: greenyellow;
        }
        .product {
          border-bottom: 1px solid #ccc;
          padding: 0.2rem 0.5rem;
        }
      </style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值