【Vue】(3)生命周期钩子函数 | 组件定义的方式 | 组件切换方式 | 父子组件之间传值 | watch/methods/computed

2023-10-07 18:56:34 浏览数 (1)

Vue实例的生命周期

生命周期:从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称生命周期 生命hz周期钩子:生命周期事件的别名而已

组件创建期间的4个钩子函数
  • beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data和methods属性
  • created:实例已经在内存中创建好,此时data和methods也已经创建好。但,此时还没有开始编译模板
  • beforeMount:此时已经完成了模板编译,但是还没有挂载到页面中
  • mounted:此时,已将将编译好的模板,挂载到页面指定的容器中显示。它是实例创建期间的最后一个生命周期函数,当执行完mounted就表示实例已经被完全创建好了。此时,如果没有其他操作的话,这个实例就在内存中。此时,组件脱离了创建阶段,进入运行阶段。所以,如果要操作页面上的DOM 节点,最早可以在mounted中进行。
组件运行阶段的钩子函数
  • beforeUpdate:状态更新之前执行此函数,此时data中的状态值是最新的但是页面上显示的数据还是旧的,因此此时还没有开始重新渲染DOM节点
  • updated:实例更新完毕之后调用此函数,此时data中的状态值和页面上显示的数据,都已经完成了更新,页面也已经被重新渲染好了 这两个事件,会根据data数据的改变,有选择的触发0次或多次。
组件销毁阶段的钩子函数

beforeDestory:实例销毁之前调用。在这一步,实例(包括:过滤器、指令、Data、methods等)仍然完全可用

destoryed:Vue实例销毁之后调用。调用后,Vue实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

例如: v-if 绑定了一个Data的值是true, 通过调用方法,设置为false,此时会执行销毁钩子函数。

用户离开页面的时候,也会调用

代码语言:javascript复制
//通常用来销毁一些监听事件和定时函数:
destroyed() {
  window.removeEventListener('resize', this.resizeWin)
}

你也可以手动调用 $destoryed进行销毁。

Vue 组件

组件ed 出现,是为了拆分Vue实例的代码量,能够让我们以不同的组件,来划分不同的功能模块,将来需要什么样的功能,就可以去调用对应的组件即可。

  • 模块化:从代码逻辑的角度进行划分,方便代码的分层开发,保证每个功能模块的职能单一;
  • 组件化:从UI界面的角度进行划分,方便UI组件的重用;
全局组件定义的三种方式

(1)使用Vue.extend来创建全局的Vue组件

代码语言:javascript复制
var com1 = Vue.extend({
	template: '<h3>使用Vue.extend创建的组件</h3>' //指定组件要展示的html结构
})
//使用Vue.component('组件名称',创建出来的组件模板对象)
//如果使用 Vue.component定义全局组件的时候,组件名称使用了 驼峰命名,则在引用组件的时候,需要把大写的驼峰改成小写的字母,同时,两个单词之间,使用 '-'连接;
//如果不使用 驼峰,则直接拿名称来使用即可;
Vue.component('myCom1',com1);
Vue.component('mycom1',com1);//不使用驼峰
代码语言:javascript复制
<div id="app">
<!--如果要使用组件,直接把组件名称以html标签的形式,引入到页面中,名称以小写加'-'连接命名--> 
  <my-com1></my-com1>
  <!--<mycom1></mycom1>不使用驼峰的方式--> 
</div>

合并使用: Vue.component 第一个参数:组件名称,将来在引用组件的时候,就是一个标签形式来引入它的;第二个参数:Vue.extend创建的组件,其中template就是组件要展示的HTML内容

代码语言:javascript复制
Vue.component('mycom1',Vue.extend({
	template: '<h3>使用Vue.extend创建的组件</h3>'
}))
  • (2)字面量对象
代码语言:javascript复制
Vue.component('mycom2',{
  //注意:不论哪种方式创建出来的组件,组件的template属性指向的模板内容,必须有且只有唯一一个根元素
	template: '<div><h3>使用Vue.component创建的组件</h3><span>123</spann></div>'
})
代码语言:javascript复制
<mycom2></mycom2>
  • (3)template元素
代码语言:javascript复制
Vue.component('mycom3',{
	template: '#tmp1'
})
代码语言:javascript复制
<div id="app">
	<mycom3></mycom3>
</div>
//在被控制的 #app 外面,使用 template 元素,定义组件的html模板结构
<template id="tmp1">
	<div>
    <h1>
      通过template元素,在外部定义的组件结构
    </h1>
  </div>
</template>
定义实例内部私有组件

components属性

代码语言:javascript复制
var vm = new Vue({
	el: '#app1',
	components: {
		login: {
			template: '<h1>app1的私有组件login</h1>'//可将其使用<template></template>方式定义
		}
	}
})
代码语言:javascript复制
<div id="app1">
  <login></login>
</div>
组件里的data要定义为一个function
  • 组件可以有自己的data
  • 组件的data和实例的data有点不同,实例中的data可以为一个对象,但是组件中的data必须是一个方法,为了保持组件之间的独立性
  • 组件中的data除了必须为一个方法,还必须返回一个对象
  • 组件的data数据,使用方式和实例的方式一样
代码语言:javascript复制
Vue.component('mycom1',{
  template: '<h1>{{msg}}</h1>',//使用data
  data: function() { 
    return {
      msg: '组件中的data'
    }
  },
  methods: {
    add() {
      
    }
  }
})

组件切换的方式

(1)指令方式 v-if, v-else

代码语言:javascript复制
<!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>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
    <script src="../lib/vue.js"></script>
</head>
<body>
    <div id="app">
        <a @click.prevent="flag=true">登录</a>
        <a @click.prevent="flag=false">注册</a>
        <login v-if="flag"></login>
        <register v-else="flag"></register>
    </div>
    <script>
        Vue.component('login',{
            template: '<h3>登录组件</h3>'
        })
        Vue.component('register',{
            template: '<h3>注册组件</h3>'
        })
        var vm = new Vue({
            el: '#app',
            data: {
                flag: true
            }
        })
    </script>
</body>
</html>

(2)使用vue 提供 component 来展示对应名称的组件

代码语言:javascript复制
<!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>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
    <script src="../lib/vue.js"></script>
</head>
<body>
    <div id="app">
        <a @click.prevent="flag='login'">登录</a>
        <a @click.prevent="flag='register'">注册</a>
        <!-- vue 提供 component 来展示对应名称的组件 -->
        <!-- component 是一个占位符, :is 属性,可以用来指定要展示的组件的名称 -->
        <component :is="comName"></component>
    </div>
    <script>
        Vue.component('login',{
            template: '<h3>登录组件</h3>'
        })
        Vue.component('register',{
            template: '<h3>注册组件</h3>'
        })
        var vm = new Vue({
            el: '#app',
            data: {
                comName: 'login'
            }
        })
    </script>
</body>
</html>

组件切换动画 < transition >及其mode属性

代码语言:javascript复制
<!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>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
    <script src="../lib/vue.js"></script>
    <style>
        .v-enter,
        .v-leave-to {
            opacity: 0;
            transform: translateX(150px);
        }
        .v-enter-active,
        .v-leave-active {
            transition: all .5s ease;
        }
    </style>
</head>
<body>
    <div id="app">
        <a @click.prevent="flag='login'">登录</a>
        <a @click.prevent="flag='register'">注册</a>
        <!-- 通过 mode 属性设置组件切换时候的模式 -->
        <transition mode="out-in">
            <component :is="flag"></component>
        </transition>
    </div>
    <script>
        Vue.component('login',{
            template: '<h3>登录组件</h3>'
        })
        Vue.component('register',{
            template: '<h3>注册组件</h3>'
        })
        var vm = new Vue({
            el: '#app',
            data: {
                flag: 'login'
            }
        })
    </script>
</body>
</html>

Vue 把一个完整的动画,使用钩子函数,拆分为两部分。

父子组件之间的传值

(1)父组件向子组件传值

  • 父组件中使用v-bind属性绑定
  • 子组件中使用props定义父组件传递过来的名称
代码语言:javascript复制
<!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>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
    <script src="../lib/vue.js"></script>
</head>
<body>
    <div id="app">
        <!-- 父组件,可以在引用子组件的时候,通过属性绑定的(v-bind:)形式,把需要传递给子组件的数据,以属性绑定的形式,传递到子组件内部,供子组件使用 -->
        <com1 v-bind:parentmsg="msg"></com1>
    </div>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                msg: '父组件数据'
            },
            methods: {},
            components: {
                com1: {
                    // 注意:组件中所有props中的数据,都是通过父组件传递给子组件的
                    //props中的数据,都是只读的,重新赋值会报错。建议放在data属性中
                    props: ['parentmsg'],//把父组件传递过来的parentmsg属性,先在props数组中定义,才能使用这个数据
                    template: '<h1>这是子组件 --- {{ parentmsg }} </h1>'
                }
            }
        })
    </script>
</body>
</html>

(2)父组件把方法传递给子组件:通过事件调用方式

  • 事件绑定机制
  • 子组件方法中使用this.$emit('name',参数列表)调用父组件方法
代码语言:javascript复制
<!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>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
    <script src="../lib/vue.js"></script>
</head>
<body>
    <div id="app">
        <!-- 父组件向子组件传递方法,使用的是事件绑定机制:v-on,
            当我们自定义了一个事件属性后,
            那么子组件就能够通过某些方式来调用传递金曲的这个方法了 -->
        <com2 v-on:func="show"></com2>
    </div>
    <template id="tmpl">
        <div>
            <h1>这是个子组件</h1>
            <input type="button" value="触发父组件传递过来的func方法" @click="myclick">
        </div>
    </template>
    <script>
        // 定义一个字面量类型
        var com2 = {
            template: '#tmpl', //通过制定一个 ID,表示说要去加载这个制定ID的template元素中的内容,当作组件的HTML结构
            data() {
              return {
                msg: {name:'imagincode'}
              }
            },
            methods: {
                myclick() {
                    //当点击子组件的按钮时候,如何拿到父组件传递过来的func方法,并调用这个方法?
                    //emit : 触发、调用
                    this.$emit('func',this.msg)//给父组件传递参数
                }
            },
        }
        var vm = new Vue({
            el: '#app',
            data: {
                msg: '父组件数据',
                datamsgFromChild: null
            },
            methods: {
                show(data) {
                    console.log('调用父组件的show方法' data)
                    this.datamsgFromChild = data;//父组件拿到子组件传递过来的值
                }
            },
            components: {
              com2
            }
        })
    </script>
</body>
</html>

refs 获取DOM元素和组件

ref是reference的缩写

代码语言:javascript复制
<h2 id="id-h2" ref="h2el"></h2> //DOM
<Login ref="mylogin"></Login> //组件
this.$refs.h2el; //获取DOM
this.$refs.mylogin; //获取组件的引用

Watch , Methods, Computed

使用Watch监听路由地址的改变

代码语言:javascript复制
watch: {
 '$route.path': function(newVal,oldVal) {
  console.log(oldVal '-->' newVal)
 }
}

Computed 计算属性

在computed中,可以定义一些属性,这些属性,叫做【计算属性】,计算属性的本质,就是一个方法。只不过,在使用这些计算属性的时候,是把它们的名称,直接当做属性来使用,并不会把计算属性当做方法去调用

代码语言:javascript复制
data: {
  firstname: '',
  lastname: ''
},
computed: {
	'fullname': function() {
		return this.firstname   '-'   this.lastname
	}
}
  • 计算属性,在引用的时候,一定不要加()去调用,直接把它当做普通属性来使用
  • 计算属性内部所用到的任何data中的数据发生了变化,就会重新计算这个属性的值
  • 计算属性的求值结果会被缓存起来,方便下次直接使用。如果计算属性方法中,所依赖的任何数据,都没有发生过变化,则不会重新对计算属性求值。

Watch , Methods, Computed的对比

  • computed属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用。
  • methods方法表示一个具体的操作,主要用于书写业务逻辑。
  • watch是一个对象,键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作。可以看做是computedmethods的结合体。

0 人点赞