世界快资讯:Vue入门浅析

2023-05-15 17:33:23 来源: 博客园

title: vue入门浅析author: Sun-Winddate: May 14,2022

写这篇博文的目的在于为初学vue的同学对vue有一些更进一步的了解读这篇博文前,您应该至少安装了vue环境,能在本地运行一个简单的demo本文将浅析vue项目工程的结构,以及用npm运行项目的过程中发生的一些事件注明:该文本应在2022.5.14发表,由于博主有其他安排耽搁后面忘了,现在补上。

项目的文件结构主文件结构

一般的vue工程项目核心部分都在src里存放 vue 项目的源代码。其文件夹下的各个文件(文件夹)分别为:


(资料图片)

assets​:资源文件,比如存放 css,图片等资源component​:组件文件夹,用来存放 vue 的公共组件(注册于全局,在整个项目中通过关键词便可直接输出)。router​:用来存放 ​index.js​,这个 js 用来配置路由tool​:用来存放工具类 js,将 js 代码封装好放入这个文件夹可以全局调用(比如常见的​ api.js​,​http.js​ 是对 http 方法和 api 方法的封装)views​:用来放主体页面,虽然和组件文件夹都是 vue 文件,但 views 下的 vue 文件是可以用来充当路由 view 的。main.js​:是项目的入口文件,作用是初始化 vue 实例,并引入所需要的插件。app.vue​:是项目的主组件,所有页面都是在该组件下进行切换的.​其他文件结构public:用于存放静态文件public/index.html:是一个模板文件,作用是生成项目的入口文件,webpack打包的js,css也会自动注入到该页面中。我们浏览器访问项目的时候就会默认打开生成好的index.htmlpackage.json: 模块基本信息项目开发所需要模块,版本,项目名称vue.config.js:包含vue项目的其他配置,包括端口等信息node_modules:项目的依赖模块dist:打包文件npm run serve/dev浅析

我们在本地运行vue项目,常见的指令就是npm run serve/dev;与其说是指令,不如说是脚本我们通常会在package.json中配置 script 字段作为 NPM 的执行脚本。以个人开发项目为例,Vue.js 源码构建的脚本如下:

"scripts": {    "serve": "vue-cli-service serve",    "build": "vue-cli-service build",    "lint": "vue-cli-service lint",    "stylelint": "stylelint src/css/*.* --fix",    "htmlhint": "htmlhint **.html",    "eslint": "eslint src/**/*.js src/**/*.vue",    "eslint-fix-js": "eslint src/**/*.js --fix",    "eslint-fix-vue": "eslint src/**/*.vue --fix"  },

所以当我们在终端运行npm run serve时,实际上运行的是vue-cli-service serve通过这个脚本去构建整个vue项目

构建的过程中发生了什么public/index.html

之前我们提到过,这个文件作为项目的入口文件,首先加载这个html文件下面这些代码是个例子

        

我们注意到一个特别的div块,它的id为app

src/main.js

这里的app其实与src/main.js文件有关

import Vue from "vue";new Vue({  el: "#app",  render: h => h(app)});

我们都知道,new 关键字在 Javascript 语言中代表实例化是一个对象,而 Vue 实际上是一个类,类在 Javascript 中是用 Function 来实现的,在vue.js源码中是这样定义的

function Vue (options) {  if (process.env.NODE_ENV !== "production" &&    !(this instanceof Vue)  ) {    warn("Vue is a constructor and should be called with the `new` keyword")  }  this._init(options)}

可以看到vue只能通过关键字初始化,this._init函数这里就不再具体介绍Vue 初始化主要就干了几件事情,合并配置,初始化生命周期,初始化事件中心,初始化渲染,初始化 data、props、computed、watcher 等等。

在初始化的最后,检测到如果有 el 属性,则调用 vm.$mount 方法挂载 vm,挂载的目标就是把模板渲染成最终的DOM在compiler版本的$mount实现中,它对 el 做了限制,Vue 不能挂载在 body、html这样的根节点上。接下来的是很关键的逻辑 —— 如果没有定义 render 方法,则会把 el 或者 template字符串转换成 render 方法。

这里我们要牢记,在 Vue 2.0 版本中,所有 Vue 的组件的渲染最终都需要 render方法,无论我们是用单文件 .vue 方式开发组件,还是写了 el 或者 template 属性,最终都会转换成 render 方法,那么这个过程是 Vue 的一个在线编译的过程。

最后,调用原先原型上的 $mount 方法挂载。

结合之前public/index.html中的例子

实际上是编写了如下render函数

render: function (createElement) {  return createElement("div", {     attrs: {        id: "app"      },  })}

vm._render 最终是通过执行 createElement 方法并返回的是 vnode,它是一个虚拟 Node

Virtual DOM介绍

浏览器真正的DOM通常是非常庞大的,因为浏览器产生DOM的标准本身就比较复杂,当我们频繁地进行DOM更新,就会产生一系列的性能问题而 Virtual DOM 就是用一个原生的 JS 对象去描述一个 DOM 节点,所以它比创建一个 DOM 的代价要小很多。在 Vue.js 中,Virtual DOM 是用 VNode 这么一个 Class 去描述在 Vue.js 中,VNode 的 create 是通过之前提到的 createElement 方法创建的。

生命周期

这也是一张比较经典的图了在开发过程中,我们会频繁地跟vue的生命周期打交道

beforeCreate 和 created 函数都是在实例化 Vue 的阶段在vue.js源码中 beforeCreate 和 created 的钩子调用是在 initState 的前后,initState 的作用是初始化 props、data、methods、watch、computed 等属性

在执行 vm._render() 函数渲染 VNode 之前,执行了 beforeMount 钩子函数,在执行完 vm._update() 把 VNode patch 到真实 DOM 后,执行 mouted 钩子。beforeUpdate 和 updated 的钩子函数执行时机都应该是在数据更新的时候,比如双向绑定等等

export function mountComponent (  vm: Component,  el: ?Element,  hydrating?: boolean): Component {  // ...  // we set this to vm._watcher inside the watcher"s constructor  // since the watcher"s initial patch may call $forceUpdate (e.g. inside child  // component"s mounted hook), which relies on vm._watcher being already defined  new Watcher(vm, updateComponent, noop, {    before () {      if (vm._isMounted) {        callHook(vm, "beforeUpdate")      }    }  }, true /* isRenderWatcher */)  // ...}

可以看到这里有一个vm._isMounted的判断,也就是说组件在mounted后才会去执行这个钩子函数同时这里实例化了一个watcher去监听vm上的数据变化重新渲染

beforeDestroy 和 destroyed 钩子函数的执行时机在组件销毁的阶段注意mounted和destroyed的执行过程都是先子后父从下图可以看到初始化vue到最终渲染的整个过程

注册组件

在开发一个组件的过程中往往会用到其他的组件组件注册的语法如下

Vue.component("my-component", {  // 选项})

import HelloWorld from "./components/HelloWorld"export default {  components: {    HelloWorld  }}

注册组件实际上是一个合并的过程,合并option再创建vnode。

由于博主在这一部分学识尚浅,暂不做过多的描述

下载插件

开发的过程中很可能需要一些其他的插件如Element等使用一般来说通过Vue.use()来下载插件,并且会阻止多次注册相同的插件

export function initUse (Vue: GlobalAPI) { Vue.use = function (plugin: Function | Object) {  const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))  if (installedPlugins.indexOf(plugin) > -1) {   return this  }  const args = toArray(arguments, 1)  args.unshift(this)  if (typeof plugin.install === "function") {   plugin.install.apply(plugin, args)  } else if (typeof plugin === "function") {   plugin.apply(null, args)  }  installedPlugins.push(plugin)  return this }}

这是use方法的源码,可以看到其参数只能是object或者function,然后判断其是否被注册过然后再调用该插件的install方法

可以看到 Vue 提供的插件注册机制很简单,每个插件都需要实现一个静态的 install 方法,当我们执行 Vue.use 注册插件的时候,就会执行这个 install 方法,并且在这个 install 方法的第一个参数我们可以拿到 Vue 对象,这样的好处就是作为插件的编写方不需要再额外去import Vue 了。

路由

路由的主要作用是根据不同的路径映射到不同的视图,一般我们用官方插件vue-router来解决路由的问题

Object.defineProperty(Vue.prototype, "$router", {    get () { return this._routerRoot._router }  })  Object.defineProperty(Vue.prototype, "$route", {    get () { return this._routerRoot._route }  })

在vue-router的类定义中有在vue原型上定义的 $router 和 $route 两个属性的get方法,这也是为什么可以在组件实例上访问 this.$router和this.$route

在new一个vueRouter后会返回它的实例,在beforecreate()中有这样一段代码

beforeCreate() {  if (isDef(this.$options.router)) {    // ...    this._router = this.$options.router    this._router.init(this)    // ...  }}  

所以在执行该钩子函数时,如果有传入router实例,则会执行router.init方法匹配是利用matcher匹配,并且会生成用户的路由表(具体细节暂时不表)当我们点击router-link的时候,会通过一系列函数找到完整的url,执行pushState方法

export function pushState (url?: string, replace?: boolean) {  saveScrollPosition()  const history = window.history  try {    if (replace) {      history.replaceState({ key: _key }, "", url)    } else {      _key = genKey()      history.pushState({ key: _key }, "", url)    }  } catch (e) {    window.location[replace ? "replace" : "assign"](url)  }}

该方法会更新浏览器的url地址,并且把当前url压入历史栈中有一个专门的监听器会监听历史栈的变化情况

setupListeners () {  const router = this.router  const expectScroll = router.options.scrollBehavior  const supportsScroll = supportsPushState && expectScroll  if (supportsScroll) {    setupScroll()  }  window.addEventListener(supportsPushState ? "popstate" : "hashchange", () => {    const current = this.current    if (!ensureSlash()) {      return    }    this.transitionTo(getHash(), route => {      if (supportsScroll) {        handleScroll(this.router, route, current, true)      }      if (!supportsPushState) {        replaceHash(route.fullPath)      }    })  })}

当点击浏览器的返回按钮时,会触发popstate事件,通过同样的方法拿到当前要跳转的url并进行路径转换

在router-view中

data.routerView = true// ...while (parent && parent._routerRoot !== parent) {  if (parent.$vnode && parent.$vnode.data.routerView) {    depth++  }  if (parent._inactive) {    inactive = true  }  parent = parent.$parent}const matched = route.matched[depth]// ...const component = cache[name] = matched.components[name]

这个循环就是从当前的的父节点向上找,一直找到根节点(vue实例),遍历完成后,就根据当前遍历的深度和路径找到对应的组件并进行渲染在router-view的最后有根据 component 渲染出对应的组件 vonde:

return h(component, data, children)
hash模式:单页应用标配,hash发生变化的url都会被浏览器记录下来history模式:可以进行切换和修改(历史状态),使得路由配置更自由其他vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。该状态管理模式包含以下几个部分:

state:驱动数据的应用源view:以声明方法将state映射到视图actions:响应在view上用户的输入导致的状态变化以下是一个简单的数据流模式

需要注意以下两点

Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

参考书籍《vue.js技术揭秘》

关键词:

精选 导读

世界快资讯:Vue入门浅析

title:vue入门浅析author:Sun-Winddate:May14,2022写这篇博文的目的在于为初学vue的同学对vue有一些更进一

发布时间: 2023-05-15 17:33
要闻   2023-05-15

热点!从“靠钢吃饭”到“弃钢突围”:一家钢企的数字变身

新华社天津5月12日电(记者郭方达)尚未进入厂区,灰色外墙上一幅巨大的鲲形彩绘率先映入眼中。多彩墙体结

发布时间: 2023-05-15 16:54
要闻   2023-05-15

左洛复盐酸舍曲林说明书_舍曲林说明书-天天通讯

1、有证据表明,舍曲林在过量服用时仍有很大的安全范围。2、曾有舍曲林单独过量服用高达13 5g的报道。3、曾

发布时间: 2023-05-15 16:21
要闻   2023-05-15

“互换通”启动 金融开放稳步推进

“互换通”启动金融开放稳步推进

发布时间: 2023-05-15 16:06
要闻   2023-05-15

烟台市莱山区第八小学开展地震应急疏散演练活动

为进一步增强师生安全意识,提高全校师生紧急避险、自救自护和应变的能力,掌握地震来临时最有效的逃生方法

发布时间: 2023-05-15 15:14
要闻   2023-05-15

热点 推荐

世界快资讯:Vue入门浅析

title:vue入门浅析author:Sun-Winddate:May14,2022写这篇博文的目的在于为初学vue的同学对vue有一些更进一

发布时间: 2023-05-15 17:33
要闻   2023-05-15

万里印刷(08385.HK)一季度净亏损1069.9万港元

格隆汇5月15日丨万里印刷(08385 HK)公布,截至2023年3月31日止第一季度,公司收益为4221 7万港元,同比减少

发布时间: 2023-05-15 17:31
IT   2023-05-15

天津创业型人才落户准迁证获取方式

➤➤天津创业型人才落户准迁证获取方式获取方式一览业务办理进度查询提交成功后个人中心的“业务网办进度”

发布时间: 2023-05-15 17:09
国内   2023-05-15

世界快看:兰州市博物馆参观攻略(门票预约+开放时间+交通指

兰州市博物馆参观攻略博物馆地处市中心繁华地段的庆阳路240号,依明代白衣寺旧址而建。现有包括中轴线上的

发布时间: 2023-05-15 17:03
科技   2023-05-15

东风本田征战TCR China 揭幕战斩获亚军上演赛道“名场面”

赛道竞逐,风云再起。5月12日-14日,2023年CTCC中国汽车场地职业联赛超级杯·TCR中国系列赛震撼来袭,首站

发布时间: 2023-05-15 17:02
汽车   2023-05-15

热点!从“靠钢吃饭”到“弃钢突围”:一家钢企的数字变身

新华社天津5月12日电(记者郭方达)尚未进入厂区,灰色外墙上一幅巨大的鲲形彩绘率先映入眼中。多彩墙体结

发布时间: 2023-05-15 16:54
要闻   2023-05-15

感恩母亲 体验“孕妈妈”艰辛-新动态

母爱,是每个人成长道路上不可或缺的亲情。她最关心我们,对我们无私奉献,不求回报。5月14日,在母亲节这

发布时间: 2023-05-15 17:05
IT   2023-05-15

联想ThinkPad春季新品发布会预热,30周年限定礼盒“惊喜出舱”

IT之家5月15日消息,联想ThinkPad官博发布预热,新品发布会即将在5月18日举行。官博发布的视频介绍的是Thin

发布时间: 2023-05-15 16:46
国内   2023-05-15

敏华控股(01999)将于7月20日派发末期股息每股10港仙_全球热头条

敏华控股(01999)公布,公司将于2023年7月20日派发末期股息每股10港仙。

发布时间: 2023-05-15 16:59
科技   2023-05-15

左洛复盐酸舍曲林说明书_舍曲林说明书-天天通讯

1、有证据表明,舍曲林在过量服用时仍有很大的安全范围。2、曾有舍曲林单独过量服用高达13 5g的报道。3、曾

发布时间: 2023-05-15 16:21
要闻   2023-05-15

四川调研督导道路交通安全和运输执法领域突出问题专项整治工

四川新闻网-首屏新闻成都5月15日讯(记者胡旭阳)为扎实推进道路交通安全和运输执法领域突出问题专项整治工

发布时间: 2023-05-15 16:21
IT   2023-05-15

石墨文档回应崩了:故障正在全力排查抢修中

针对服务器宕机一事,在线协同办公平台石墨文档回应称,因技术原因,目前部分石墨文档暂时无法编辑,故障正

发布时间: 2023-05-15 16:21
国内   2023-05-15

拼多多货在路上可以申请退款吗?拼多多退款多久可以到账?

拼多多是大家经常使用并且非常熟悉的一家电商平台,用户可以在上面买到各种商品,并享受不同类型的优惠,其中拼团优惠是拼多多比较突出的一

发布时间: 2023-05-15 16:28
推荐   2023-05-15

V8混动 兰博基尼Urus PHEV谍照曝光

[本站海外谍照]日前,外媒在兰博基尼工厂附近拍摄到了UrusPHEV测试车。按照计划这款车将会在2024年正式发布

发布时间: 2023-05-15 16:09
汽车   2023-05-15

年产250台 AC Cobra GT Roadster首发 天天速读

[本站新车首发]曾经为世界车迷贡献了传世经典跑车ACCobra的英国AC汽车公司近日正式推出该车的复刻版本――A

发布时间: 2023-05-15 16:23
汽车   2023-05-15

环球即时看!阿斯顿·马丁新DB系列将于5月24日首发

[本站资讯]近日,我们从阿斯顿・马丁官方获取了三张全新一代DBGT的预告图,新车将于5月24日首发。阿斯顿・

发布时间: 2023-05-15 16:02
汽车   2023-05-15

拼多多退店要等30天吗? 退店的条件是什么?

拼多多平台的店铺数量越来越多了, 竞争非常激烈,在这种情况下,很多人选择将自己的店铺转让出去或者是关闭掉,那么,拼多多退店要等30天

发布时间: 2023-05-15 16:25
推荐   2023-05-15

当前热点-画蛋糕图片大全大图涂色_画蛋糕图片

你们好,最近小活发现有诸多的小伙伴们对于画蛋糕图片大全大图涂色,画蛋糕图片这个问题都颇为感兴趣的,今

发布时间: 2023-05-15 16:00
科技   2023-05-15

七天无理由退货有运费险吗?七天之内退货运费谁出?

线上购物是现在比较热门的一种购物方式,一方面线上购物发货比较快,甚至第二天就能到货,另一方面线上购物商品价格会更加优惠、便宜。此外

发布时间: 2023-05-15 16:21
社会   2023-05-15

买车可以用支付宝支付吗?全款买车都是怎么支付的?

买车的时候,选择好汽车等待商家提交订单即可支付了, 买车可以用银行卡也可以用现金,那么,买车可以用支付宝支付吗?全款买车都是怎么支

发布时间: 2023-05-15 16:18
社会   2023-05-15