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

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

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,此时会执行销毁钩子函数。
    用户离开页面的时候,也会调用
//通常用来销毁一些监听事件和定时函数:
destroyed() {
  window.removeEventListener('resize', this.resizeWin)
}
  • 你也可以手动调用 $destoryed进行销毁。

Vue 组件

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

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

全局组件定义的三种方式

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

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

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

定义实例内部私有组件

  • components属性
var vm = new Vue({
  el: '#app1',
  components: {
    login: {
      template: '<h1>app1的私有组件login</h1>'//可将其使用<template></template>方式定义
    }
  }
})
<div id="app1">
  <login></login>
</div>

组件里的data要定义为一个function

  • 组件可以有自己的data
  • 组件的data和实例的data有点不同,实例中的data可以为一个对象,但是组件中的data必须是一个方法,为了保持组件之间的独立性
  • 组件中的data除了必须为一个方法,还必须返回一个对象
  • 组件的data数据,使用方式和实例的方式一样
Vue.component('mycom1',{
  template: '<h1>{{msg}}</h1>',//使用data
  data: function() { 
    return {
      msg: '组件中的data'
    }
  },
  methods: {
    add() {
    }
  }
})

组件切换的方式

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

<!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 来展示对应名称的组件

<!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属性

<!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定义父组件传递过来的名称
<!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',参数列表)调用父组件方法
<!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的缩写
<h2 id="id-h2" ref="h2el"></h2> //DOM
<Login ref="mylogin"></Login> //组件
this.$refs.h2el; //获取DOM
this.$refs.mylogin; //获取组件的引用

Watch , Methods, Computed

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

watch: {
 '$route.path': function(newVal,oldVal) {
  console.log(oldVal+'-->'+newVal)
 }
}

Computed 计算属性

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

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

Watch , Methods, Computed的对比

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


相关文章
|
28天前
|
缓存 JavaScript UED
Vue3中v-model在处理自定义组件双向数据绑定时有哪些注意事项?
在使用`v-model`处理自定义组件双向数据绑定时,要仔细考虑各种因素,确保数据的准确传递和更新,同时提供良好的用户体验和代码可维护性。通过合理的设计和注意事项的遵循,能够更好地发挥`v-model`的优势,实现高效的双向数据绑定效果。
128 64
|
28天前
|
前端开发 JavaScript 测试技术
Vue3中v-model在处理自定义组件双向数据绑定时,如何避免循环引用?
Web 组件化是一种有效的开发方法,可以提高项目的质量、效率和可维护性。在实际项目中,要结合项目的具体情况,合理应用 Web 组件化的理念和技术,实现项目的成功实施和交付。通过不断地探索和实践,将 Web 组件化的优势充分发挥出来,为前端开发领域的发展做出贡献。
32 8
|
28天前
|
JavaScript
在 Vue 3 中,如何使用 v-model 来处理自定义组件的双向数据绑定?
需要注意的是,在实际开发中,根据具体的业务需求和组件设计,可能需要对上述步骤进行适当的调整和优化,以确保双向数据绑定的正确性和稳定性。同时,深入理解 Vue 3 的响应式机制和组件通信原理,将有助于更好地运用 `v-model` 实现自定义组件的双向数据绑定。
|
1月前
|
存储 缓存 JavaScript
在 Vue 中使用 computed 和 watch 时,性能问题探讨
本文探讨了在 Vue.js 中使用 computed 计算属性和 watch 监听器时可能遇到的性能问题,并提供了优化建议,帮助开发者提高应用性能。
|
1月前
|
存储 缓存 JavaScript
Vue 中 computed 和 watch 的差异
Vue 中的 `computed` 和 `watch` 都用于处理数据变化,但使用场景不同。`computed` 用于计算属性,依赖于其他数据自动更新;`watch` 用于监听数据变化,执行异步或复杂操作。
|
1月前
|
JavaScript API 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的
|
7天前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。
|
1月前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱前端的大一学生,专注于JavaScript与Vue,正向全栈进发。博客分享Vue学习心得、命令式与声明式编程对比、列表展示及计数器案例等。关注我,持续更新中!🎉🎉🎉
41 1
vue学习第一章
|
1月前
|
JavaScript 前端开发 索引
vue学习第三章
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中的v-bind指令,包括基本使用、动态绑定class及style等,希望能为你的前端学习之路提供帮助。持续关注,更多精彩内容即将呈现!🎉🎉🎉
30 1
|
1月前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
38 1
vue学习第四章

热门文章

最新文章