从一个奇怪的错误出发理解 Vue 基本概念-程序员宅基地

技术标签: 程序员  前端  vue.js  javascript  

path: path.resolve(__dirname, dist),

publicPath: ‘’,

filename: ‘index.js’

},

resolve: {

extensions: [‘.js’, ‘.vue’]

},

module: {

loaders: [

{

test: /.vue$/,

loader: ‘vue-loader’

},

{

test: /.js$/,

loader: ‘babel-loader’,

query: {

presets: [‘es2015’]

},

exclude: /node_modules/

}

]

},

plugins: [

new HtmlWebpackPlugin({

filename: ‘index.html’,

template: path.resolve(__dirname, ‘index.html’),

inject: true

})

]

}

运行 npm run dev 并访问 http://localhost:8080/ 后,从浏览器的控制台得到如下警告信息:

[Vue warn]: Failed to mount component: template or render function not defined. (found in root instance)

令人百思不得其解的是,如果不使用 webpack 打包,而是直接在 HTML 文件中使用 script 标签引入 Vue.js,在 JavaScript 中手写 MyComponent 的组件选项模板,完成的页面却可以正确显示,为什么这里会提示“模板或渲染函数未定义”呢?

这其实与 Vue 的两种不同的构建有关,在上述使用 webpack 打包的项目需要使用独立构建的 Vue 库,而在 node_modules/vue/package.json 文件中,已经通过 main 属性指定了通过 import Vue from ‘vue’ 或 require(‘vue’) 所引入的文件是 dist/vue.runtime.common.js,即运行时构建的 Vue 库。直接在 HTML 文件中使用 script 标签引入的是独立构建的 Vue 库,因此没有问题。

从 Vue 官方教程的 Standalone vs. Runtime-only Build 我们了解到 Vue 有两种不同的构建——独立构建和运行时构建。运行时构建删除了模板编译的功能,因此无法支持带 template 属性的 Vue 实例选项。但如果你不深入地去理解 Vue 的基本概念以及编译、挂载相关的过程,你可能仍然会很迷糊,为什么在这个项目中会有问题?

说到 Vue 的概念,不得不说起 Vue 实例,这是一个使用 Vue 构造函数创建的 JavaScript 对象,创建 Vue 实例时,传递给 Vue 构造函数的参数是一个包含若干属性和方法的对象,被称为 Vue 实例选项对象,用于声明所创建的 Vue 实例对象所要挂载的目标元素、data 数据、计算属性、模板/渲染函数、实例方法以及各种生命周期钩子回调函数等选项。创建的 Vue 实例既然是一个 JavaScript 对象,那么也必然拥有属性和方法,下图是 Vue 实例所包含的属性与方法的示例:

可以看出,Vue 实例的属性、方法与 Vue 选项对象的属性、方法差别很大,然而两者之间还是有关联的,比如,Vue 实例的 $el 属性是 Vue 选项对象中的 el 属性作为选择子所对应的 DOM 元素,Vue 实例的 d a t a 属性是 V u e 选项对象中的 d a t a 属性(或工厂函数)经响应式处理后的对象, data 属性是 Vue 选项对象中的 data 属性(或工厂函数)经响应式处理后的对象, data属性是Vue选项对象中的data属性(或工厂函数)经响应式处理后的对象,options 属性则是经 Vue 构造函数处理过的 Vue 选项对象。

我们通过这两个对象间关系的分析,可以加深一下对 Vue 的一些基本概念的理解——模板/渲染函数、挂载点、独立构建/运行时构建、Event Bus。

首先是模板/渲染函数。Vue 官方教程的第四部分是模板语法,介绍了插值和指令,可以通过插值语法和 Vue 指令声明式地编写 Vue 模板,在教程的高级篇中,介绍了渲染函数,并说明了两者之间的关系。Vue 构造函数会将 Vue 模板编译成用于实现数据驱动的 DOM 渲染的渲染函数,开发者也可以直接手写渲染函数来发挥 JavaScript 的完全编程能力。

展开 Vue 实例的 $options 属性,可以进一步看到除了 el 和 components 之外,多了若干个其他属性和方法,其中就包含编译生成的render 渲染函数。

既然 Vue 构造函数在创建 Vue 实例时会将 template 编译成 render 渲染函数,但我们在调用 new Vue 时的 Vue 选项对象中并没有包含 template 属性,那么 template 模板是从哪儿来的呢?

这涉及到 Vue 选项对象中的 el 属性、template属性和 render 渲染函数的关系问题,当 Vue 选项对象中有 render 渲染函数时,Vue 构造函数将直接使用渲染函数渲染 DOM 树,当选项对象中没有 render 渲染函数时,Vue 构造函数首先通过将 template 模板编译生成渲染函数,然后再渲染 DOM 树,而当 Vue 选项对象中既没有 render 渲染函数,也没有 template 模板时,会通过 el 属性获取挂载元素的 outerHTML 来作为模板,并编译生成渲染函数。

换言之,在进行 DOM 树的渲染时,render 渲染函数的优先级最高,template 次之且需编译成渲染函数,而挂载点 el 属性对应的元素若存在,则在前两者均不存在时,其 outerHTML 才会用于编译与渲染。

下面我们通过创建三个不同的 Vue 实例来验证一下:

html 页面 body 内容:

{ {msg}}
{ {msg}}
{ {msg}}

分别创建 Vue 实例的代码:

new Vue({

el: ‘.app1’,

data: {

msg: ‘Hello, Vue.js.’

},

template: ‘

Hello, world.
’,

render: (h) => h(‘div’, {}, ‘Hi, there.’)

})

new Vue({

el: ‘.app2’,

data: {

msg: ‘Hello, Vue.js.’

},

template: ‘

Hello, world

})

new Vue({

el: ‘.app3’,

data: {

msg: ‘Hello, Vue.js.’

}

})

结果如下:

通过上述说明,可以很容易地理解 Vue 的独立构建和运行时构建这两个概念,所谓独立构建是指能够将 template 模板或者从 el 挂载元素提取的模板编译成渲染函数的 Vue 库,而运行时构建则是指不能进行模板编译的 Vue 库。

使用运行时库主要是为了减少体积,同时强制预编译所有模板,实现前端优化,Vue 的 npm 包也将 package.json 中的 main 指向了运行时构建 dist/vue.runtime.common.js,在按模块化方式引用或打包时默认使用运行时构建。

什么场合使用独立构建,什么场合使用运行时构建,针对这个问题,只需要考虑清楚在项目中是否使用了模板编译功能。

在包含单文件组件的项目中,使用 webpack 打包时已经将单文件组件中的模板预先编译成了渲染函数,因此一般情况下使用运行时构建的 Vue 库就可以了,但如果在使用 new Vue 创建 Vue 的根实例时,模板是从 el 挂载元素提取的,则需要使用独立构建的 Vue 库。

在使用 script 标签引入 Vue.js 的项目中,任意实例选项或组件选项中包含了 template 模板属性或从 el 挂载元素提取的模板时,均需要使用独立构建的 Vue 库。

要解决本文最开始的问题,需要在 webpack 配置中的 resolve 属性对象中添加如下 alias 设置:

module.exports = {

// … other options

resolve: {

extensions: [‘.js’, ‘.vue’],

alias: {

‘vue$’: ‘vue/dist/vue.common.js’

}

},

// … other options

}

这里的 vue$ 表示精确匹配,由于 index.js 中还有一处大小写错误 import Vue from ‘Vue’,因此需要将 from 后面的 ‘Vue’ 修改为小写的 ‘vue’ 之后页面才能正确显示。

下面再考虑一个问题:构建Vue 实例时,Vue 选项中 el 属性、template属性和 render 渲染函数是否三者必有其一?

答案是不一定,可以使用不包含 el 属性、template属性和 render 渲染函数的实例选项创建 Vue 实例,事实上,如果在 Vue 实例选项中既没有设置 el 挂载点属性也没有显式调用 $mount 方法,是不会触发对 render 渲染函数(无论是手工编写还是编译生成)的检查的。

比较常见的是应用场景是为实现多组件间通信而创建的 Event Bus。

创建 Event Bus:

import Vue from ‘vue’

export const EventBus = new Vue()

关于使用上面这种方式创建 Event Bus 可能会出现 undefined 的问题,如果出现了,那么,请修改为下面这样:

import Vue from ‘vue’

const EventBus = new Vue()

export default EventBus

然后就可以根据需要给 Event Bus 添加事件响应:

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)


核心竞争力,怎么才能提高呢?

成年人想要改变生活,逆转状态?那就开始学习吧~

万事开头难,但是程序员这一条路坚持几年后发展空间还是非常大的,一切重在坚持。

为了帮助大家更好更高效的准备面试,特别整理了《前端工程师面试手册》电子稿文件。

前端面试题汇总

JavaScript

性能

linux

前端资料汇总

完整版PDF资料免费分享,只需你点赞支持,动动手指点击此处就可免费领取了

前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。

.png)

linux

前端资料汇总

完整版PDF资料免费分享,只需你点赞支持,动动手指点击此处就可免费领取了

前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/2401_84152308/article/details/138019570

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法