Vue学习笔记 在html文件中创建Vue实例,并使用http-vue-loader注册单文件组件

Posted 梆子井欢喜坨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue学习笔记 在html文件中创建Vue实例,并使用http-vue-loader注册单文件组件相关的知识,希望对你有一定的参考价值。

本篇博客基于Vue2.x
官方文档:https://cn.vuejs.org/v2/guide/instance.html

最近和同学合作一个设备信息管理的小项目,而同学找的模板不是前后端分离的
因此只能学习一下在 html文件中如何使用Vue,并学习一些之前没有理清的概念。

1. Vue实例

在Vue的官方教程中,也是从在html中使用Vue起步的, 下面是一个简单的Hello World 例子。

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue"></script>
</head>
<body>
  <div id="app">
    <!-- 用简洁的模板语法来声明式地将数据渲染进 DOM 的系统 -->
    {{ message }}
  </div>

  <script>
  // 每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的:
    var app = new Vue({
      el: '#app',
      data: {
        message: 'Hello Vue!'
      }
    })
  </script>
</body>
</html>

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

当一个 Vue 实例被创建时,它将 data 对象中的所有的 property 加入到 Vue 的响应式系统中。
当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。

// 我们的数据对象
var data = { a: 1 }
// 该对象被加入到一个 Vue 实例中
var vm = new Vue({
  data: data
})
// 获得这个实例上的 property
// 返回源数据中对应的字段
vm.a == data.a // => true
// 设置 property 也会影响到原始数据
vm.a = 2
data.a // => 2
// ……反之亦然
data.a = 3
vm.a // => 3

当这些数据改变时,视图会进行重渲染。
只有当实例被创建时就已经存在于 data 中的 property 才是响应式的。

除了数据 property,Vue 实例还暴露了一些有用的实例 property 与方法。它们都有前缀 $,以便与用户定义的 property 区分开来。

var data = { a: 1 }
var vm = new Vue({
  el: '#example', // 提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。
  data: data
})

vm.$data === data // => true
vm.$el === document.getElementById('example') // => true

// $watch 是一个实例方法
vm.$watch('a', function (newValue, oldValue) {
  // 这个回调将在 `vm.a` 改变后调用
})
 console.log(app.$data);
===========================
 out: {message: "Hello Vue!"}

实例生命周期钩子

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
如mounted钩子
实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。如果根实例挂载到了一个文档内的元素上,当 mounted被调用时 vm.$el 也在文档内。
mounted不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在mounted内部使用vm.$nextTick

mounted: function () {
  this.$nextTick(function () {   // 生命周期钩子的 this 上下文指向调用它的 Vue 实例。
    // Code that will run only after the
    // entire view has been rendered
  })
}

生命周期图示:
在这里插入图片描述

2. 注册组件

组件是可复用的 Vue 实例
每个组件必须只有一个根元素
一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:

data: function () {
  return {
    count: 0
  }
}

有两种组件的注册类型:全局注册和局部注册。

2.1 通过 Vue.component 全局注册:

组件名就是 Vue.component 的第一个参数。
自定义组件名的规范为kebab-case (短横线分隔命名),字母全小写且必须包含一个连字符

Vue.component('my-component-name', {
  // ... options ...
})

使用 PascalCase(首字母大写命名) 定义一个组件时,用两种命名法都可以引用组件

Vue.component('MyComponentName', { /* ... */ })

但是直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的。

全局注册的组件可以用在其被注册之后的任何 (通过 new Vue) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。

2.2 局部注册

全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 javascript 的无谓的增加。

可以通过一个普通的 JavaScript 对象来定义组件:

var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }

然后在 components 选项中定义你想要使用的组件:

new Vue({
  el: '#app',
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})

局部注册的组件在其子组件中不可用

2.3 在模块系统中局部注册单文件组件

如果使用了诸如 Babel 和 webpack 的模块系统。
创建一个 components 目录,并将每个组件放置在其各自的文件中。
在局部注册之前导入每个你想使用的组件。
例如,在一个假设的 ComponentB.js 或 ComponentB.vue 文件中:

import ComponentA from './ComponentA'
import ComponentC from './ComponentC'

export default {
  components: {
    ComponentA,
    ComponentC
  },
  // ...
}

现在 ComponentA 和 ComponentC 都可以在 ComponentB 的模板中使用了。

在 ES2015+ 中,在对象中放一个类似 ComponentA 的变量名其实是 ComponentA: ComponentA 的缩写,即这个变量名同时是:

  • 用在模板中的自定义元素的名称
  • 包含了这个组件选项的变量名

2.4 在html中注册单文件组件

如果是一个页面中的组件复用,使用基本的局部注册就可以满足需求。
但是在这个项目中,需要在多个html文件中复用诸如侧边栏,顶边栏之类的组件。
因此还是考虑用单文件组件的方式进行注册。
在这里插入图片描述
为了在html文件中注册单文件组件,需要使用一个npm包http-vue-loader
github地址:https://github.com/FranckFreiburger/http-vue-loader

Load .vue files directly from your html/js. No node.js environment, no build step.

例如有个单文件组件my-component.vue

<template>
    <div class="hello">Hello {{who}}</div>
</template>

<script>
module.exports = {
    data: function() {
        return {
            who: 'world'
        }
    }
}
</script>

在html文件中进行组件注册

<!doctype html>
<html lang="en">
  <head>
    <script src="https://unpkg.com/vue"></script>
    <script src="https://unpkg.com/http-vue-loader"></script>
  </head>

  <body>
    <div id="my-app">
      <my-component></my-component>
    </div>

    <script type="text/javascript">
      new Vue({
        el: '#my-app',
        components: {
          'my-component': httpVueLoader('my-component.vue')
        }
      });
    </script>
  </body>
</html>

其它使用示例参见github。

2.5 个人学习总结

可以发现http-vue-loader的示例中,单文件子组件中写的是module.exports = {},而不是export default {}

以上一篇博客Vue学习笔记(1) 根据MDN教程,创建一个To-Do List为例
在APP.vue中是这样写的

export default {
  name: 'app',
  components: {
    ToDoItem,
    ToDoForm
  },
 // ...
}

之前没有系统学习JavaScript,没有思考过export default的作用,加上平时都是直接用Vue脚手架,导致忽略了一些问题,在写组件的时候直接copy export default {}不起效,浪费了很多时间。
回忆一下使用vue/cli前进行了什么操作

  1. 安装npm(Node Package Manager),它是基于Node.js的包管理器
  2. 安装vue/cli

事实上,用Vue脚手架前安装Node的主要目的是使用npm这个前端开发的软件包管理器和使用WebPack进行模块化管理。
不使用npm,在页面引入 vue.min.js 也能使用Vue进行前端开发。

下面来解释下module.exports = {}export default {}的区别:
学习参考:
https://segmentfault.com/a/1190000010426778

首先要明白一个前提,CommonJS模块规范和ES6模块规范完全是两种不同的概念。

require: node 和 es6 都支持的引入
export / import : 只有es6 支持的导出引入
module.exports / exports: 只有 node 支持的导出

nodeJS采用commonJs规范,
CommonJS定义的模块分为: 模块标识(module)、模块定义(exports) 、模块引用(require)
在这里插入图片描述
为了让对象暴露于模块之外,只需把它们设置为 exports 对象的附加属性即可

在一个既定的模块内,可以把 exports 想象成 module.exports 的 快捷方式。
exports 本质上就是在模块初始化前为 module.exports 的值进行初始化的一个变量。
这个值是对一个对象(这里是空对象)的引用。
这意味着 exports 与 module.exports 引用了同一个对象,也意味着如果为 exports 赋其它值不会影响到 module.exports。
Node 模块是通过 module.exports 导出的,如果直接将exports变量指向一个值,就切断了exports与module.exports的联系

不同于CommonJS,ES6使用 export 和 import 来导出、导入模块。
ES6中的模块功能主要由两个命令构成:export和import。

  • export命令用于规定模块的对外接口
  • import命令用于输入其他模块提供的功能。
    export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。
    导出的不是一个具体的数值,而是一个对象

export default命令,为模块指定默认输出。

命名的导出默认的导出
export class User {…}export default class User {…}
import {User} from …import User from …

学完Js语法,还是很疑惑为什么在脚手架创建的工程中,单文件组件的导出使用export default
template和style部分好像没有导出。
在这里插入图片描述
这时候查到了一个叫Vue Loader的东西,消除了我的疑惑。
文档:https://vue-loader.vuejs.org/zh/
在这里插入图片描述
Vue Loader

  • 允许为 Vue 组件的每个部分使用其它的 webpack loader,例如在 <style> 的部分使用 Sass 和在 <template> 的部分使用 Pug;
  • 允许在一个 .vue 文件中使用自定义块,并对其运用自定义的 loader 链;
  • 使用 webpack loader 将 <style><template> 中引用的资源当作模块依赖来处理;
  • 为每个组件模拟出 scoped CSS;
  • 在开发过程中使用热重载来保持状态。
    vue 文件的script 会被解析成es6 的模块。export default 定义封装vue的属性,export 以外的部分也是整个模块的一部分。

这个问题还是没有完全搞明白,前端开发的知识还是太欠缺了。

以上是关于Vue学习笔记 在html文件中创建Vue实例,并使用http-vue-loader注册单文件组件的主要内容,如果未能解决你的问题,请参考以下文章

如果他在单独的文件中创建,如何在 chrome 控制台中调用 Vue 实例

在vue中创建多个ueditor实例

在vue中创建多个ueditor实例

如何在同一个文件夹中创建多个 vue 应用

vue学习笔记初识vue——创建vue示例

在 Vue.js 中创建自定义组件