Vue 实例

栏目: JavaScript · 发布时间: 5年前

内容简介:在刚接触Vue的时候,就知道Vue是一个优势的JavaScript框架,其主要是用来处理

在刚接触Vue的时候,就知道 实例 在Vue中是一个重要的概念,在学习之后也整理了一篇有关于 Vue实例和生命周期的学习笔记 。经过一段时间的学习之后,重新再温习了一遍有关于Vue的实例,整理一下,提供给有需要的同学作为参考资料。

Vue 的基本原理

Vue是一个优势的JavaScript框架,其主要是用来处理 视图层 (我的理解就是UI层)。当用户操作 View Model (即JavaScript,在Vue中指的是Vue实例,一个观察者)使其依照一定的逻辑取得需要改变的数据( Model ),配合在HTML中Vue提供的模板语法来改变配置,重新渲染后使画面产生相应的变化( View )。用一张图来描述这个过程:

Vue 实例

比如我们在浏览器中渲染出来的页面有个 区域 和“删除”按钮,当用户点击“删除”按钮之后,会移除这个区域。用户交互之后反馈给用户的是,界面(视图)中的区域被移除。看上去非常的简单,其实在Vue中,主要经历了以下几个过程:

  • (1) 用户在界面中点击“Remove”按钮进行交互
  • (2) 通过模板中的绑定触发Vue实例中注册的 remove() 事件
  • (3) remove() 事件通过 Ajax 向服务器请求数据
  • (4) 服务器取得的数据后重新传给Vue实例
  • (5) Vue实例修改绑定的ViewModel
  • (6) ViewModel改变后触模板重新渲染
  • (7) 改变后的视图反馈给用户(用户看到重新渲染后的视图)

咱们可以用下图来描述这个交互的整个过程:

Vue 实例

事实上Vue的原理要比这复杂的多,只不过用上图来阐述对于初学者而言在概念上有一定的辅助作用。但其也遵循一个原则: 视图的状态由数据描述,并且通过数据来驱动视图变化

Vue 实例

深入的概念还无法理解的情况之下,我们暂时只需要先记住,在Vue中视图和数据之间的关系是一个非常简单的关系,即 双向数据绑定

Vue采用发布者 —— 订阅者模式实现双向数据绑定,首先Vue将会获得需要监听的对象的所有属性,通过 Object.defineProperty 方法完成对象属性的劫持,将其转化为 gettersetter ,当属性被访问或修改时,立即将变化能知给订阅者,并由订阅者完成相应的逻辑操作。

我们可以用下图来描述双向数据绑定主要流程:

Vue 实例

  • Observer :主要处理属性监听逻辑,将监听属性转化为 getset 属性,当属性被访问时,调用 dep.depend() 方法,而属性被修改时,则调用了 dep.notify() 方法
  • Dep :担任发布者的角色,维护访问者列表,负责订阅者的添加和通知工作,上面所提到的 depend()notify() 方法在这里实现
  • Watcher :担任订阅者角色,即 Dep.target ,可以订阅多个 Dep ,在每次收到发布者消息通知时触发 update() 方法执行更新逻辑

创建Vue实例

接下来,我们来创建一个Vue实例,就是前面提到的 ViewModel 部分。Vue实例是Vue中很重要的一部分,创建他很简单:

let app = new Vue({

})

创建Vue实例很简单,通过 new Vue({}) 即可。事实上,Vue实例就是一个JavaScript对象,而且常常将这个对象赋值给一个 app 变量。

Vue的第一个参数是 options ,它会传给Vue实例这个对象。 options 这个参数主要包括:

  • el :Vue实例需要挂载的一个DOM元素,一般是 index.html 文件中的 div#app 元素
  • data :需要一个输出取得结果的数据
  • methods :方法
  • Vue实例生命周期的钩子函数

比如下面这个示例:

let app = new Vue({
    el: '#app',
    data () {
        return {
            message: 'W3cplus.com'
        }
    },
    methods: {
        getRemoteMessage () {
            Promise.resolve('获取远程数据:大漠')
                .then((res) => {
                    this.message = res
                })
        }
    }
})

除了上面这种方式,Vue实例的挂载还有另外一种方式:

// main.js
new Vue({
    render: h => h(App),
}).$mount('#app')

而给Vue实例传递参数,可以像下面这样的方式:

<!-- App.vue -->
<script>
    export default {
        name: 'app',
        data () {
            return {
                message: 'W3cplus.com'
            }
        },
        methods: {
            getRemoteMessage () {
                Promise.resolve('获取远程数据:大漠')
                    .then((res) => {
                        this.message = res
                    })
            }
        }
    }
</script>

上面的示例主要做了三件事情:

  • 将Vue实例挂载在页面中 idapp 的一个 div 元素上
  • data 中初始化了一个 message ,并且在 <template> 中以 {{message}} 方式将 data 中的 message 显示在页面上
  • 定义了一个 getRemoteMessage() 方法,该方法会以非同步的方式取得 message
  • <template> 中的一个 button 绑定了定义好的 getRemoteMessage() 方法
  • 当用户点击界面中的按钮,将会获取远程的一个数据,并且更改 <template>message 的值

效果如下:

Vue 实例

创建一个Vue实例就是这么的简单。

最开始我们也提到了,Vue实例是Vue中重要的部分之一,甚至可以说, 任何一个Vue的应用程序都是从Vue实例开始的,大创建实例后,可以通过操作实例中的参数来改变页面的配置

以上示例代码可以查阅 app-vue-instance 项目的 step1 分支。

Vue实例的生命周期

Vue实例中还有另一个重要的内容,那就是Vue实例的生命周期,在Vue实例中会在各个生命周期中提供相应的钩子函数(Hooks事件),这些钩子函数让开发者可以在Vue实例阶段做相应的处理。Vue官方为Vue实例的生命周期提供了一张非常详细的图:

Vue 实例

上图展示了Vue实例整个生命周期,其中红框白底就是生命周期中具备的钩子函数:

  • beforeCreate :Vue实例初始化的时候会立即调用,其发生在未创立Vue实例之前,这个时候在Vue实例中的设置都还未配置完成,比如 data
  • created :Vue实例创建完成,此时Vue实例中的配置除了 $el 外全部配置,而 $el 只有在Vue实例挂载到相应的HTML元素时才会生效
  • beforeMount :在Vue实例挂载到目标元素之前被调用,这时的 $el 会是还未被Vue实例中的定义渲染的初始设定的模板
  • mounted :Vue实例上的设置已经安装上模板,这里的 $el 是已经由实例中的定义渲染成真成的页面
  • beforeUpdate :当Vue实例中的 data 发生变化后或是执行 vm.$forceUpdate() 调用,这时的页面还未被重新沉浸而改变页面
  • updated :在重新渲染页面后被调用,这时的页面已经被重新渲染成改变后的页面
  • beforeDestroy :Vue实例被销毁前调用,这个时候Vue实例还是拥有完整的功能
  • destroyed :Vue实例被销毁,这个时候Vue实例中的任何定义都已被解除绑定,此时对Vue实例做的任何操作都会失效

接下来看一个小示例,把分支切换到 step2 ,来看看Vue实例中操作各个钩子函数,然后打印出 data$el ,看看在各个钩子函数中它们是如何变化的。

<!-- App.vue -->
<template>
    <div id="app">
        <img alt="Vue logo" src="./assets/logo.png">
        <h2>{{ message }}</h2>
        <div>
            <button @click="getRemoteMessage">获取远程数据</button>
        </div>
    </div>
</template>

<script>
    export default {
        name: 'app',
        data () {
            return {
                message: 'W3cplus.com'
            }
        },
        methods: {
            getRemoteMessage () {
                Promise.resolve('获取远程数据:大漠')
                    .then((res) => {
                        this.message = res
                    })
            }
        }
    }
</script>

根据上图,将Vue实例生命周期中的钩子函数分成四组:

  • beforeCreate created :创建Vue实例
  • beforeMount mounted :挂载目标元素
  • beforeUpdate updated :改变后重新渲染
  • beforeDestroy destroyed :销毁Vue实例

beforeCreatecreated

先来看 beforeCreatecreated 两个钩子函数,在Vue实例中添加这两个钩子函数,打印出相应的 data$el

beforeCreate () {
    console.log(`>>> ==== 钩子函数 beforeCreate ==== >>>`)
    console.log(`this.message: ${this.message}`)
    console.log(`this.$el: ${this.$el}`)
    console.log(`>>> ==== End ==== >>>`)
},
created () {
    console.log(`>>> ==== 钩子函数 created ==== >>>`)
    console.log(`this.message: ${this.message}`)
    console.log(`this.$el: ${this.$el}`)
    console.log(`>>> ==== End ==== >>>`)
}

结果如下:

Vue 实例

由于 beforeCreate 阶段,Vue实例还没有创建,所以 message$el 都是 undefined ;而到了 created 阶段时,Vue实例已经创建了,所以 message 变成了 W3cplus.com ,但 $el 因为还没有挂载到目标元素,所以依旧是 unddefined

也就是说, beforeCreate 钩子中是不能对Vue实例中的任何东西做操作

beforeMountmounted

和前面的方式一样,在Vue实例中添加钩子函数 beforeMountmounted

beforeMount () {
    console.log(`>>> |_==_| 钩子函数 beforeMount |_==_| >>>`)
    console.log(`this.message: ${this.message}`)
    console.log(`this.$el: ${this.$el}`)
    console.log(`>> |_==_| this.$el.outerHTML 开始 |_==_| >>`)
    console.log(this.$el.outerHTML)
    console.log(`>> |_==_| this.$el.outerHTML 结束 |_==_|`)
    console.log(`>>> |_==_| End |_==_| >>>`)
},
mounted () {
    console.log(`>>> |_==_| 钩子函数 mounted |_==_| >>>`)
    console.log(`this.message: ${this.message}`)
    console.log(`this.$el: ${this.$el}`)
    console.log(`>> |_==_| this.$el.outerHTML 开始 |_==_| >>`)
    console.log(this.$el.outerHTML)
    console.log(`>> |_==_| this.$el.outerHTML 结束 |_==_| >>`)
    console.log(`>>> |_==_| End |_==_| >>>`)
}

结果如下:

Vue 实例

在Vue实例的流程图中提到,开始执行 beforeMount 钩子函数时,此时 $el 还没有生成HTML到页面上,因此在执行 this.$el.outerHTML 时会报警,如上图所示。而在执行 mounted 钩子函数时,Vue实例已经绑定到元素上,所以这里看到的是渲染后的结果。

也就是说, beforeMount 前同样不能操作DOM元素

beforeUpdateupdated

同样的,把 beforeUpdateupdated 钩子函数加入到Vue实例中:

beforeUpdate () {
    console.log(`>>> (^_^) 钩子函数 beforeUpdate (^_^) >>>`)
    console.log(`this.message: ${this.message}`)
    console.log(`this.$el: ${this.$el}`)
    console.log(this.$el.outerHTML)
    console.log(`>>> (^_^) End (^_^) >>>`)
},
updated () {
    console.log(`>>> (^_^) 钩子函数 updated (^_^) >>>`)
    console.log(`this.message: ${this.message}`)
    console.log(`this.$el: ${this.$el}`)
    console.log(this.$el.outerHTML)
    console.log(`>>> (^_^) End (^_^) >>>`)
}

当你点击页面上的按钮时,打印出来的结果如下:

Vue 实例

beforeDestroydestroyed

beforeDestroy () {
    console.log(`(^_^) 钩子函数 beforeDestroy (^_^)`)
    console.log(`this.message: ${this.message}`)
    console.log(`this.$el:${this.$el}`)
    console.log(this.$el.outerHTML)
    console.log(`(^_^) End (^_^)`)
},
destroyed () {
    console.log(`(^_^) 钩子函数 destroyed (^_^)`)
    console.log(`this.message: ${this.message}`)
    console.log(`this.$el:${this.$el}`)
    console.log(this.$el.outerHTML)
    console.log(`(^_^) End (^_^)`)
}

第一次执行 app.__vue__.$destroy() 会打印出相应的信息,再执行一次将会报错,如下图所示:

Vue 实例

正如上面所示,执行 beforeDestroy 后,即将执行销毁Vue实例,如果想要释放一些资源,可以在这里操作;当执行 destroyed 时,Vue实例将会销毁。比如上面的示例,执行 app.__vue__.$destroy() 后,再点击页面上的按钮,不会有任何的反应,这是因为我们的Vue实例已销毁。

小结

本文从Vue的基本原理着手,学习了Vue的一些基本原理以及相关的概念,然后学习Vue实例的创建以及Vue实例生命周期中的钩子函数,并通过简单的实例,演示了Vue实例中不同钩子函数时实例的状态。这样对于学习Vue实例以及生命周期就不仅仅是停在概念上的,而是知道每个不同周期中对应钩子函数中具体的行为。这样一来,在实际使用Vue的时候,更能清楚的什么事情该在什么样的钩子函数中执行,才能起到相应的效果。特别是对于DOM的操作,掌握这些尤其重要。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Pro JavaScript Techniques

Pro JavaScript Techniques

John Resig / Apress / 2006-12-13 / USD 44.99

Pro JavaScript Techniques is the ultimate JavaScript book for the modern web developer. It provides everything you need to know about modern JavaScript, and shows what JavaScript can do for your web s......一起来看看 《Pro JavaScript Techniques》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

MD5 加密
MD5 加密

MD5 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具