创建vue实例vm(vue30创建实例)

第二节:Vue实例化

1.创建一个Vue实例

通过vue函数创建一个新的vue实例

一个 Vue 应用由一个通过new Vue创建的 根 Vue 实例 ,以及可嵌套的、可复用的组件树组成的。

我们先看看Vue基本的使用,至于组件我们后面详细的在来探讨

divid="app"!-- {{ 插值表达式,可以赋值 取值 三元 }} --{{ msg }}/divscriptsrc="./node_modules\vue\dist\vue.js"/scriptscript// 引入vue后 会白给你一个Vue构造函数letvm=newVue({// 配置对象el:'#app',// 告诉vue能管理那个部分,使用的是querySelectordata:{// data中的数据会被vm所代理msg:'hello world',// 可以通过vm.msg取到对应的内容 ,也可以赋值      }})/script

2.声明式渲染

Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:

2.1. 关于{{}} 插值表达式

插值表达式,表达式,赋值运算,计算,三元表达式,但是尽量少在这里写逻辑计算

插值:

!-- HTML ---divid="app"{{ message }}/div!-- JS ---scriptnewVue({el:'#app',data:{messgae:'hello Vue!'}})/script

我们已经成功创建了第一个 Vue 应用!看起来这跟渲染一个字符串模板非常类似,但是 Vue 在背后做了大量工作。现在数据和 DOM 已经被建立了关联,所有东西都是响应式的。我们要怎么确认呢?

如果需要确定现在的数据是否已经和DOM建立了关联,形成响应式.

可以将js中的new Vue复制给一个全局变量vm.此时vm就是Vue实例化对象,未来可能会用它来搞很多事情,但是最常用到它的时候,是通过this关键字来使用它

varvm=newVue({el:'#app',data:{messgae:'hello Vue!'}})

然后在浏览器的js控制台中修改vm.message值,同时页面也会发生改变

在控制台中输入

vm.messge="你好,Vue"

2.2.使用 JavaScript 表达式

迄今为止,在我们的肆卖模板中,我们一直都只绑定简单的属性键值。但实际上,对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。

{{ number + 1 }}{{ ok ? 'YES' : 'NO' }}{{ message.split('').reverse().join('') }}divv-bind:id="'list-' + id"/div

这些表达式会在所属 Vue 实例的数据作用域下作为 JavaScript 被解析。

示例:

divid="app"!-- 数字操作 --p{{ number + 2 }}/p!-- 三目运算 --p{{ ok ? 'YES' : 'NO' }}/p!-- 字符串翻转 --p{{ message.split('').reverse().join('')  }}/p/divscriptconstvm=newVue({el:"#app",data:{message:'Hello World',number:10,ok:true,}})/script

显示结果:

1.png

但是有个限制就是,每个绑定双大括号(Mustache语法)里面都只能包含 单个表达式

2.3. 关于data数据

vue关注的是数据变化,不需要在像裂桥逗以前一样关注DOM的变化

比如我想在2秒之后让页面发生消或变化,我们只需要在2秒后更改数据就可以了

varvm=newVue({el:'#app',data:{msg:'hello world'}})setTimeout(function(){vm.$data.msg="bye world"},2000)

关于实例介绍:

示例中vm是Vue的实例对象,

实例对象上有$data属性,其值就是选项对象中data属性值

选项对象就是在实例化Vue时传入的对象

data属性值是一个对象,因此$data也就是这个对象

当通过$data修改msg的值时,也就等于改data中的值, 对应是引用类型

因此示例的结果就是:

2秒后data数据中msg的值改变了, 又因为Vue是始终在关注着msg这个数据,一旦数据发生变化,就会触发Vue的响应式, 继而改变视图显示

2.4 再次理解MVVM模式

在上一节讲Vue的mvvm模式的时候就有提到,

Vue实例对象就是vm,data数据就是model,  页面显示的结果就是view

再来看一下mvvm的图

mvvm.jpg

这张图在配合刚才的示例, 我们就能很好的理解,当数据Model发生变化以后, Vue就可以通过Data Bindings了解到,然后使用新的数据去改变页面显示

至于Vue如何通过DOM Listeners监听页面的改变,来改变数据,这个我们之后讲到在说

3.实例上的方法

除了数据属性,Vue 选项对象中还暴露了一些有用的属性与方法。在通过实例对象使用选项对象的属性时,属性前面都需要带上前缀$,以便与用户定义的属性区分开来。例如:

vardata={a:1}varvm=newVue({el:'#example',data:data})vm.$data===data// = truevm.$el===document.getElementById('example')// = true

3.1. 实例上常用的属性和方法

vm.$attrs// 用户获取父组件传递给子组件的属性,(除props,class,style外)vm.$data// vm 上的数据vm.$watch// 监听vm.$el// 当前el元素vm.$set// 后加的属性实现响应式vm.$options// vm 配置 上的 所有属性vm.$nextTick(()={})// 异步方法,等待渲染dom完成后来获取vmvm.$refs// 获取dom元素或者组件实例的引用

其实我们可以创建一个Vue实例,然后在控制台上打印这个实例对象,你会看到很多的属性和方法

constvm=newVue({el:"#app",})

在控制台输入vm

显示结果:

实例属性.png

这里面很多属性,我们暂时不用去关心他,因为随着学习的深入,慢慢都会学习到的.

4.实例化多个vue

我们可以在页面上同时实例化多个Vue, 不同的实例接管页面上不同的区域.

看下如下的示例:

##  h1实例化多个Vue对象/h1divid="app-one"h2{{ title }}/h2p{{ greet }}/p/divdivid="app-two"h2{{ title }}/h2p{{ greet }}/pbuttonv-on:click="changeTitle"点击改变app-one的h2的内容/button/divscript//  Vue实例varone=newVue({el:'#app-one',data:{title:" vue-app-one的内容"},computed:{greet:function(){return"Hello App One"}}})//  Vue实例vartwo=newVue({el:'#app-two',data:{title:" vue-app-two的内容"},methods:{changeTitle:function(){one.title="app-one的内容发生改变了"}},computed:{greet:function(){return"Hello App two"}}})/script

Vue事件和方法还没有讲到, 先做一个了解即可:

示例分析:

两个实例one和two接管了不同的DOM元素,

点击按钮是在two实例接管的DOM元素中,

所以,当你点击时,只会触发two实例中的方法, 也只会改变two实例中的数据

那么问题来了?

能否在two实例中修改one实例中的数据呢,?

答案当然是可以的啦, 因为变量one是全局变量,

在two实例化中,就可以通过one变量得到第一个Vue实例化对象,

然后就可以通过实例化对象修改数据,这个可以自己尝试写写.

5. Vue 操作DOM元素

虽然Vue是数据驱动的,但是有的时候我们就需要自己手动的获取到DOM元素,对DOM元素进行操作,那么该如何处理呢,

操作DOM元素:

在需要操作的DOM元素中使用ref属性,

ref属性的值是自己随便定义的名字

通过Vue实例的$refs属性获取操作dom元素

divid="app"divref="wuwei"无为/div/divscriptvarvm=newVue({// 根实例el:'#app',data:{},mounted(){//dom元素中有多个一样的ref,dom如果不是通过v-for循环出来的,只能获取一个// 如果是循环出来的,可以获取多个,获取的是一个数组console.log(this.$refs.wuwei)}});/script

关于示例中$refs属性的解释:

因为可以在多个DOM元素上使用ref.

所以$refs属性获取的是所有具有ref属性的DOM元素的集.

因此要想操作确定的DOM元素就需要在通过当初的ref值获取.

简而言之: 就是ref在dom元素上通过this.$refs.自定义名字是获取dom元素

当获取到DOM元素后,然后就可以采用原生的JavaScript对DOM进行操作

注意:

Vue 接管的DOM元素之外的元素使用ref是获取不了的,值是undefined

vue生命周期详解

vue源码中最终执行生命周期函数都是调用 callHook 方法, callHook 函数的逻辑很简单友山,根据传入的生命周期类型 hook ,去拿到 vm.$options[hook] 对应的回调函数数组,然后遍历执行,执行的时候把 vm 作为函数执行的上下文。

1. new Vue(options) :创建一个vm实例;

2. mergeOptions(resolveConstructorOptions(vm.constructor), options, vm) :合并Vue构造函数里options和传入的options或合并父子的options。比如:在mergeOptions函数中会调用mergeHook方法合并生命周期的钩子函数,mergeHook方法原理是只有父时返回父,只有子时返回数组类型的子。父、子都存在时,将子添加在父的后面返回组合而成的数组。这也是父子均有钩子函数的时候,先执行父的后执行缺埋子的的原因;

3. initLifecycle(vm)、initEvents(vm)、initRender(vm) :在创建的vm实例上初始化生命周期、事件、渲染相关的属性;

4. callHook(vm, 'beforeCreate') :调用beforeCreate生命周期钩子函数;

5. initInjections(vm)、initState(vm)、initProvide(vm) :初始化数据:inject、state、provide。initState 的作用是初始化 props、data、methods、watch、computed 等属性;

6. callHook(vm, 'created') :调用created生命周期钩子函数;

7. vm.$mount(vm.$options.el) : $mount 方法在多个文件中都有定义,如"src/platform/web/entry-runtime-with-compiler.js"、"src/platform/web/runtime/index.js"、"src/platform/weex/runtime/index.js"。因为 $mount 方法的实现是和平台、构建方式相关的。以"entry-runtime-with-compiler.js"为例,关键步骤是查看 vm.$options 中是否有伏告蚂render方法,如果没有则会根据el和template属性确定最终的template字符串,再调用 compileToFunctions 方法将template字符串转为render方法,最后,调用原先原型上的$mount方法,即开始执行"lifecycle.js"中 mountComponent 方法;

8. callHook(vm, 'beforeMount') :调用beforeMount生命周期钩子函数;

9. vm._render() = vm._update() = vm.__patch__() :先执行vm._render方法,即调用createElement生成虚拟DOM,即VNode ,每个VNode有children ,children 每个元素也是⼀个 VNode,这样就形成了⼀个 VNode Tree;再调用vm._update方法进行首次渲染,vm._update方法核心是调用vm. patch 方法,这个方法跟vm.$mount一样跟平台相关;vm. patch 方法则是根据生成的VNode Tree递归createElm方法创建真实Dom Tree挂载到Dom上;

10. callHook(vm, 'mount') :调用mount生命周期钩子函数:VNode patch 到 Dom 之后会执行 'invokeInsertHook'函数,把 insertedVnodeQueue 中保存的mount钩子函数执行一遍,insertedVnodeQueue队列中的钩子函数是在根据VNode Tree递归createElm方法创建真实Dom Tree过程生成的钩子函数顺序队列,因此mounted钩子函数的执行顺序是先子后父;

11. data changes :数据更新,nextTick中执行 flushSchedulerQueue 方法,该方法会执行watcher队列中的watcher;

12. callHook(vm, 'beforeUpdate') :执行watcher时会执行watcher的before方法,即调用beforeUpdate生命周期钩子函数;

13. Virtual DOM re-render and patch :重新render生成新的Virtual DOM,并且patch到DOM上;

14. callHook(vm, 'updated') :调用updated生命周期钩子函数;

15. vm.$destroy() :启动卸销毁过程;

16. callHook(vm, 'beforeDestroy') :调用beforeDestroy生命周期钩子函数;

17. Teardown watchers, childcomponents and event listeners :执行一系列销毁动作,在 $destroy 的执行过程中,它又会执行 vm.__patch__(vm._vnode, null) 触发它子组件的销毁钩子函数,这样一层层的递归调用,所以 destroyed 钩子函数执行顺序是先子后父,和 mounted 过程一样。

18. callHook(vm, 'destroyed ') :调用destroyed 生命周期钩子函数。

创建vue实例vm(vue30创建实例)  第1张

Vue实例理解

Vue实例是通过Vue函数来创建的。可以传入一个选项对象。一个Vue应用通过创建一个根Vue实例,以及可以嵌套和可复用的组件树组成。可以看出,Vue应用实际上是由组件树组成。

Vue实例被创建时,它将data对象中的所有property加入到Vue响应系统中。当这些property属性值发生改变含散时,视图更新为新的值。

定义一个对象,赋值给data对象,修改定义的对象的原始数据,也会改变property的值。

数据改变,视图会重渲染,只有当实例被创建时就以及存在于data中的property才是逗老颤响应的。因此, 也就解释了为什么需要在property时定义初始值 ,这样当发生数据改变会山败更新。

Vue实例自身暴露了一些有用的实例property与方法,它们都有前缀 el(表示挂载的元素),vm. watch()等。

以上内容为新媒号(sinv.com.cn)为大家提供!新媒号,坚持更新大家所需的前端知识。希望您喜欢!

版权申明:新媒号所有作品(图文、音视频)均由用户自行上传分享,仅供网友学习交流,不声明或保证其内容的正确性,如发现本站有涉嫌抄袭侵权/违法违规的内容。请发送邮件至 k2#88.com(替换@) 举报,一经查实,本站将立刻删除。

(0)
上一篇 2023-09-23
下一篇 2023-09-23

相关推荐

发表回复

登录后才能评论