转载自:https://segmentfault.com/a/1190000006435886

解决办法:添加package.config.js配置文件中,添加本文章的红色部分代码

import vue

顺利安装完成并按 changelog 做了修改之后,启动项目也正常,当我兴致勃勃地打开 Browser,驾轻就熟地输入 localhost,并自然而然地按下 Enter,一切水到渠成。

然而,迎接我的竟是一片白板,控制台里赫然映着一串红字。

[Vue warn] : You are using the runtime-only build of Vue where the template option is not available. Either pre-compile the templates into render functions, or use the compiler-included build. (found in root instance)

What? template 选项不能用了,changelog 没提到啊?但 vue-router 的例子中都在用啊,什么鬼?甚至我将代码全部替换成例子中的代码依旧无法运行,但在 vue-router 项目里就能跑,什么鬼啊!

但是,我并不妥协,分别打断点运行,发现两者竟然跑的不是同一段代码,纳尼!

import vue from 'vue'

同样的 import 语句,却有不一样的结果,vue-router 中引的是 vue.js,而在我的项目中引的竟然是 vue.common.js...common...mon...n...

为什么会引 vue.common.js,from 'vue' 不该引的是 vue.js 么?这就要引入另一个知识点:package.json。

package.json 中的 main 属性决定了,当项目被引入时,输出的是哪个文件,而 vue 的 package.json 中的 main 指向的是 dist/vue.common.js

福利时间:推荐一个网站 json.is,它对 package.json 里的每条属性都有详细的解释。

找到了问题产生的原因,那么解决也就轻而易举了。

import vue from 'vue/dist/vue.js'

每次引用 vue 的时候都要写那么长,一点都不优雅,而且为什么 vue-router 的例子可以用啊?

我要一探究竟。确认了 vue-router 中依赖的 vue 的 package.json 文件中的 main 字段指向的也是 dist/vue.common.js。那就只有一个可能了,webpack 对引入做了处理,查看 webpack.config.js

module.exports = {
// 省略...
resolve: {
alias: {
'vue': 'vue/dist/vue.js'
}
},
...

果然啊~他用 webpack 的别名功能把 vue/dist/vue.js 命名成了 vue,防不胜防。

在自己项目的 wepack.config.js 里同样给 vue 起别名,这样就又能愉快地使用 import vue from 'vue' 了。

你是不是以为这样就结束了?不,对待一个问题要刨根问底,不能不求甚解。

为什么 vue 默认导出的是 vue.common.js,它和 vue.js 的区别在哪里,又有什么关系?

这个问题在囧克斯的博客中有提到。

Vue 最早会打包生成三个文件,一个是 runtime only 的文件 vue.common.js,一个是 compiler only 的文件 compiler.js,一个是 runtime + compiler 的文件 vue.js。

也就是说,vue.js = vue.common.js + compiler.js,而如果要使用 template 这个属性的话就一定要用 compiler.js,那么,引入 vue.js 是最恰当的。

路由升级

vue-router 的升级并不困难,参照 Releases Note 上的注释修改应该没有什么大问题,主要的变化有两点:

  1. 路由配置从一系列的方法调用,变成了传递一个配置对象

  2. 原先的 v-link 指令,变成了 router-link Component,路径指向用 to 属性

正当你以为会一路顺风顺水,轻松升级路由完成的时候,现实总会给你当头一棒。

之前博客的 vue-router 中使用了 beforeEach 和 afterEach 方法,根据 Release Note

  • router.beforeEach (replaced by the beforeEach option)

  • router.afterEach (replaced by the afterEach option)

行,那我把它改到配置里

const ROUTER_SETTING = {
routes: [
// 省略...
],
beforeEach: () => { /* some function */ },
afterEach: () => { /* some function */ }
}

But, not work. What's wrong?

难道我哪里写错了?又经过我一番谷哥和查阅文档之后,发现在下一个版本的 Release Note 中有这么一段

beforeEach and afterEach are reverted as router instance methods (options removed). This makes it more convenient for plugins/modules to add hooks after the router instance has been created.

好吧,它又被恢复回路由实例的方法了。那么,改回去

const router = new VueRouter(ROUTER_SETTING);

router
.beforeEach(() => { /* some function */ })
.afterEach(() => { /* some function */ });

OK,这样总好了吧。然而,并没有...console 中报出无法从 undefined 中读取 afterEach,好吧,我猜这应该是 beforeEach 中没有像之前一样返回路由对象,所以不能链式调用。

class VueRouter {
// 省略...
beforeEach (fn: Function) {
this.beforeHooks.push(fn)
} afterEach (fn: Function) {
this.afterHooks.push(fn)
}
// 省略...
}

看一眼源码,果然如此。

那再将之前的代码稍作修改就可以了。

const router = new VueRouter(ROUTER_SETTING);

router.beforeEach(() => { /* some function */ });
router.afterEach(() => { /* some function */ });

不过,不能链式调用似乎没之前的优雅了哪~

最后,提一下 vue-router 2.0 里所有的 hook(就像之前的 beforeEachafterEach,以及每个路由状态中的 beforeEnterbeforeRouteLeave等)都具有相同的参数签名,这在 Release Note 中也有提到。

fn (toRoute, redirect, next) {
// toRoute: {Object} 当前路由对象
// redirect: {Function} 调用跳转至另一路由
// next: {Function} 调用继续当前路由跳转
// 什么都不做,则取消当前跳转
}

路由升级完成后,如果控制台没有什么报错,那么,路由可以相互切换了,那些不依赖数据读取的组件已经可以正常显示了。

那些依赖数据读取的组件哪?

这就要提到组件的生命周期钩子(即 lifecycle hooks)

Lifecycle hooks

生命周期钩子应该算 vue 这次升级中 broken changes 最多的一部分了,对照 1.0 的文档和 release note,作了下面这张表

vue 1.0+ vue 2.0 Description
init beforeCreate 组件实例刚被创建,组件属性计算之前,如 data 属性等
created created 组件实例创建完成,属性已绑定,但 DOM 还未生成,$el 属性还不存在
beforeCompile beforeMount 模板编译/挂载之前
compiled mounted 模板编译/挂载之后
ready mounted 模板编译/挂载之后(不保证组件已在 document 中)
- beforeUpdate 组件更新之前
- updated 组件更新之后
- activated for keep-alive,组件被激活时调用
- deactivated for keep-alive,组件被移除时调用
attached - 不用了还说啥哪...
detached - 那就不说了吧...
beforeDestory beforeDestory 组件销毁前调用
destoryed destoryed 组件销毁后调用

知道了 hooks 升级前后的对应关系,那么升级起来就轻而易举了,改改组件的属性名就可以了。

那么,改完属性名是不是就完成了?然而并没有。

因为,在 vue 1.0+ 中,如果一个组件和路由相关,那么,它就可能不单单有自己组件的 lifecycle hooks,它还会有基于 vue-router 的 lifecycle hooks。

而在 vue 2.0 中,router lifecycle hooks 全部被移除了,因为,这些 hooks 可以通过其他的方式来代替,这样不但简化了配置,还不用在组件中去处理路由相关的业务,降低了耦合。那这些 hooks 该如何替换,我们接下来就来看一下。

  • activate & deactivate:使用组件自身的 lifecycle hook 替代

  • data:通过组件 watch 属性来监听当前路由 $route 的变化

  • canActivate:由路由属性 beforeEnter 来代替

  • canDeactivate:由路由属性 beforeRouteLeave 来代替

  • canReuse:去除

那个这个是不是也直接改改属性名就好了哪?

恩,差不多。不过需要注意的是,如果原先 hooks 中使用了有关路由信息的 transition 参数是肯定不能用了。比如,根据路由参数来进行查询,原先通过 transition.to.params 获取路由参数,现在就要通过刚刚提到的当前路由对象 this.$route.params 来获取。

在升级这里的过程中,还遇到一个问题:当用户输入的 URL 满足路由匹配,但根据路由参数无法获得正确的文章时,我想让路由直接跳转到首页。

在 1.0 版本中,我通过 transition.redirect('/'); 就轻松的回到了首页,由于 2.0 中没有 transition 参数,而 $route 只包含当前路由的信息,并不包换路由切换的操作。那该怎么做哪?再一次谷哥和查阅文档,然而一无所获。

最后在 vue-router 的例子中找到了解决问题的钥匙——$router

$router 返回的是整个项目路由的实例,它是只读的。于是,刚刚那个问题就可以通过 this.$router.replace('/'); 来解决。

这里还有一点,在 1.0 版本中组件配置 route 属性时还可以设置一个叫 waitForData 的属性。这个在 2.0 中,我还没有找到直接的替换方式,不过,我在整个组件上添加 v-if 来处理。从理论和效果的角度上讲,v-if 是可以替代原先的 waitForData 属性,就似乎不那么优雅。

[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.的更多相关文章

  1. You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

    异常 You are using the runtime-only build of Vue where the template compiler is not available. Either ...

  2. vue源码逐行注释分析+40多m的vue源码程序流程图思维导图 (diff部分待后续更新)

    vue源码业余时间差不多看了一年,以前在网上找帖子,发现很多帖子很零散,都是一部分一部分说,断章的很多,所以自己下定决定一行行看,经过自己坚持与努力,现在基本看完了,差ddf那部分,因为考虑到自己要换 ...

  3. You are using the runtime-only build of Vue where the template compiler is not available. Either pre

    在升级脚手架到vue-cli3.0版本的时候出现了这个报错: [Vue warn]: You are using the runtime-only build of Vue where the tem ...

  4. vue.runtime.esm.js:593 [Vue warn]: Invalid prop: custom validator check failed for prop "value".报错解决

    在uni中使用 picker组件,一直报错 vue.runtime.esm.js:593 [Vue warn]: Invalid prop: custom validator check failed ...

  5. // mounted: {}, 原来是 空方法 导致了 vue 的警告 !| [Vue warn]: Error in mounted hook: "TypeError: handlers[i].call is not a function"

    // mounted: {}, 原来是 空方法 导致了 vue 的警告 !| vue.runtime.esm.js?2b0e:587 [Vue warn]: Error in mounted hook ...

  6. vue报错[Vue warn]: Unknown custom element: <router-Link> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

    vue浏览器报错,如下 vue.runtime.esm.js?2b0e:619 [Vue warn]: Unknown custom element: <router-Link> - di ...

  7. vue踩坑记录:[Vue warn]: $attrs is readonly.

    今天在用element-ui的DatePicker日期选择器的时候,发现每当点击一次这个组件,控制台就会报警告`[Vue warn]: $attrs is readonly`,但是也不影响实际操作效果 ...

  8. [Vue warn]: Attribute "id" is ignored on component <div> because the component is a fragment instanc

    今天在使用vue框架搭建环境时,遇到这个错误提示: [Vue warn]: Attribute "id" is ignored on component <div> b ...

  9. [Vue warn]: Cannot find element: #main

    使用vue框架的时候,如果页面提示如下错误,则说明new Vue的时候没有传入 el 的值: [Vue warn]: Cannot find element: #main 我们传入el 既可以,如: ...

随机推荐

  1. 第一次spring冲刺第5天

    今天进行讨论基础功能的核心代码方面,还有简单的讨论继续关于界面的美化, 计算生成的答案功能 public class Core {// char[]h={'+','-','*','/'};int re ...

  2. 团队作业4 Alpha冲刺《嗨!你的快递》

    仓库地址:https://git.coding.net/day_light/ourexpressmaster1.git   张新宇 1第一天日期:2018/6/13 1.1今日任务 进行核心功能数据匹 ...

  3. YFCC 100M数据集分析笔记

    --从YFCC 100M数据集中筛选出Geo信息位于中国的数据集 1.YFCC 100M简介 YFCC 100M数据库是2014年来基于雅虎Flickr的影像数据库.该库由1亿条产生于2004年至20 ...

  4. Delphi中BCD和Currency类型

    用了这些年的Delphi,竟然对Currency及TBCDField一知半解,下文给了很好的讲解,值得一读. 一.       BCD类型 BCD即Binary-Coded Decimal?,在Del ...

  5. php框架的制作原理

    php框架的制作原理 (2012-08-16 14:25:55) 转载▼ 标签: php框架制作 杂谈 分类: php index.php 主入口文件 <?php  define('ISEXIS ...

  6. Hibernate 注解之 @Temporal

    因为数据库中有个 Date类型的数据,在从数据库中获取数据[就是getXxx方法,当然,自动装配的时候可以直接写在字段上,但也只是针对getXxx方法,不会自动赋值]的时候可以利用这个 @Tempor ...

  7. 【Python】Python文件系统功能:os模块

    1.os模块方法分类 (1)目录: chdir() 改变工作目录 chroot() 设定当前进程的根目录 listdir() 列出指定目录下的所有文件名 mkdir() 创建指定目录 makedirs ...

  8. P4329 [COCI2006-2007#1] Bond

    题意翻译 有n 个人去执行n 个任务,每个人执行每个任务有不同的成功率,每个人只能执行一个任务,求所有任务都执行的总的成功率. 输入第一行,一个整数n (1≤n≤20 ),表示人数兼任务数.接下来n ...

  9. Matplotlib风羽自定义

    [前言]对于气象专业的小学生来说,风场是预报重要的参考数据,我们所知的风羽有四种:短线代表风速2m/s,长线代表风速4m/s,空心三角代表风速20m/s,实心三角代表风速50m/s.而matplotl ...

  10. 【刷题】BZOJ 3262 [HNOI2008]GT考试

    Description 阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字. 他的不吉利数学A1A2...Am(0< ...