03、手把手教Vue--组件

PS:转载请注明出处
作者: TigerChain
地址: https://www.jianshu.com/p/8de7f3ba234a
本文出自 TigerChain 简书 手把手教 Vue 系列

本节大纲

教程简介

  • 1、阅读对象
    本篇教程适合新手阅读,老手直接略过
  • 2、教程难度
    初级,本人水平有限,文章内容难免会出现问题,如果有问题欢迎指出,谢谢
  • 3、Demo 地址:https://github.com/tigerchain/vue-lesson 请看 02、vue组件 组件这一节

正文

一、什么是组件

Vue 玩的就是组件,如果看过我 React 文章的朋友对组件肯定不会陌生。其实我们的应用界面就是由一个个组件构成的。

举个栗子,我们就以手淘首页部分界面为例子来说

淘宝组件

从图中我们可以直观的看到,这些框出来的就可以开发成一个个组件,然后把这些组件合并在一起就完成首页了「淘宝不一定是这样的做的,这里只是为了让大家直观的感受一下什么是组件」

二、Vue 中组件的形式

在 Vue 中有四种组件形式,分别是全局组件、局部组件、嵌套组件和单个组件,下面我们一一来看

1、全局组件

1、全局组件含义和使用方法

全局组件,顾名思义,就是本页「所有 vue 实例中」都可以使用的组件

注册全局组件方法如下

Vue.component('组件名称',{
  模版和方法等
})

我们可以使用 Vue.extend() 函数「也可以不用,直接使用 Vue.component()」来创建一个 Vue 的构造器「注意它不是 Vue 实例」

2、直接撸码感受一下全局组件「引入 vue.js 这里就不说了,直接上核心代码」

<body>
  <h2>vue-component</h2>
  <hr>
  <div id="container">
    <h3>爱吃什么水果? app 实例</h3>
      <ol>
        <todolist
        ></todolist>
      </ol>
  </div>

  <div id="container2">
    <h3>爱吃什么水果? app2 实例</h3>
      <ol>
        <todolist
        ></todolist>
      </ol>
  </div>

  <div>
    <h3>爱吃什么水果?</h3>
    组件没有在任何实例中,所以不显示 <font color="red">「组件一定要挂载到某个 Vue 实例中,否则不会生效」</font>
      <ol>
        <todolist
        ></todolist>
      </ol>
  </div>

  <script type="text/javascript">
    // 定义一个组件构造器,不是实例
    var todolist = Vue.extend({
      template:'<div><li v-for="(item,index) in datas" @click="showName(index)">{{item.text}}</li></div>',
      data() {
        return {
          datas:[
           { id: 0, text: '苹果' },
           { id: 1, text: '香蕉' },
           { id: 2, text: '只要是水果我都爱吃' }
         ]
        }
      },
      // 组件的方法
      methods:{
        showName(index){
          alert(this.datas[index].text)
        }
      }
    })

    // 全局组件注册
    Vue.component('todolist',todolist)
    // 定义一个 Vue 实例
    var app = new Vue({
      el:"#container",
      // data:{}
    })
    // 定义另一个 Vue 实例
    var app2 = new Vue({
      el:'#container2'
    })
  </script>
</body>

从上面的代码中我们可以看出来,我们使用 Vue.extend() 函数创建了一个 Vue 构造器,并且使用全局注册组件方式注册了组件,还声明了三个 div ,两个 Vue 实例,我们来看看运行结果吧

Vue 全局组件

从结果上我们可以看出:

  • 1、 前两个 Div 都把 todolist 组件渲染出来了,这就说明了 todolist 是一个全局组件,在所有的 Vue 实例中都可以使用,但是在第三个 div 中却没有渲染出来,因为组件必须挂载到 Vue 实例中「很明显组件没有挂载到第三个 div」中。
  • 2、组件可以看成一个 Vue 实例,里面可以写 methods ,可以写 template 模版,并且可以定义数据「但是这里 data 一定要写成函数,并且在 return 中写数据」,当然以后 props 等都可以写

2、局部组件

1、局部组件和使用方法

我们使用 Vue 对象的 components 属性来实现局部组件注册,顾名思义局部组件就是只能在本对象中使用的组件,模版如下:

new Vue({
  el: '#myapp',
  ...
  // 把组件注册到本 Vue 实例下
  components: {'组件别名': 组件名}
  
})

2、代码中体验局部组件

  • 1、我们接着上面的代码直接修改,修改的地方很简单,如下所示:
全局组件改造成局部组件
  • 2、运行查看结果:
Vue 局部组件

可以看到,只有 app 实例下正确的加载了 todolist 组件,别的没有加载「这就是局部组件」

  • 3、注意

我们如果在 app2 中使用局组件 todolist 是不会显示的,我们的 demo 强行使用,是为了演示效果,其实浏览器已经报错了,如下:

其它 vue 实例使用局部组件报错

大概意思就是找不到 todolist 组件,你是否正确注册的意思

3、嵌套组件「组合组件」

1、嵌套组件「组合组件」的含义和使用方法

我们可以在一个组件中嵌套另一个组件,也就是在组件中定义 components 并且传入子组件即可,一般使用方法如下:

// 定义一个组件
var customcomponent = Vue.extend({
    template: '<div>。。。。</div>',
    data():{},
    ....
})

var parentcomponent = Vue.extend({
    // 模版中就可以使用子组件了
    template: '<div>你类组件的一些模版 <custom-component></custom-component></div>',
    data():{},
    ....
    // 把子组件注册到父类组件中
    components: {
        'custom-component':custom component
    }
})

基本使用方法就是如此,当然我们可以加入 methods 等属性和方法

2、撸码看效果

我们在上面的代码的基础上修改如下三个地方:

嵌套组件

分为三个步骤:

  • 1、定义组件
  • 2、注册组件
  • 3、使用组件

运行查看结果:

嵌套组件显示结果

我们可以看到,子组件在 todolist 组件中显示出来了,这样嵌套组件就完成了

4、单个组件

我们通上以上方式就可以实现组件化 Vue ,但是如果在大型项目中这样使用会让人感觉到 T 疼,全部组件写在一个页面中,难维护,难查阅。那么有就第 4 种方式--单个组件,什么是单个组件,也就是定义一个后缀为 .vue 的文件,然后把模版、js、style 都写在这个文件中,这就是单个组件,我们开始吧

1、创建一个单个组件的项目

如果看过第一节的朋友应该知道,我们通过 vue-cli 能快速创建一个 vue 项目,并且里面单个组件等全部都为你生成了,下面我们通过自己手动来模拟一个类似于 vue-cli 创建出来的项目这么一个过程,直接上代码

  • 1、新建一个文件夹--myvuedemo
// 命令行输入,无论是 windows 还是 mac 
mkdir myvuedemo
cd myvuedemo 
  • 2、使用 yarn 初始化项目「当然也可以使用 npm ,yarn 和 npm 的安装以前在 React 教程中说过,不清楚的可以自行百度一下」
yarn init 

一路回车即可,目录如下:

myvuedemo目录

我们可以看到使用 yarn init 初始代项目,就多了一个 package.json 文件

  • 3、在 myvuedemo 目录下新建 src 和 dist 目录,并且新建 index.html 文件
创建相关目录
  • 4、安装依赖

在前面我们都是使用引信 vue.js 的方式来使用 vue 的,现在我们安装依赖的方式来使用 vue ,所以我们要安装一些依赖,在 myvuedemo 目录下使用如下命令

yarn add vue

安装 webpack 和 webpack-dev-server,由于我们在开发环境中需要,所以在开发环境下安装依赖「生产环境中是不需要的」

yarn add webpack webpack-dev-server --dev

我们查看 package.json 文件,就会看到依赖安装上了,如下所示:

安装部分依赖
  • 5、在 index.html 输入以下内容
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
<div id="container"></div>

<script src="./dist/bundle.js"></script>
</body>
</html>

我们定义了一个 id 为 container 的 div 并且,引入了打包后的 bundle.js

  • 6、在 src 中新建 main.js
import Vue from 'vue' ;

new Vue({
  el: '#container',
  render:h => h('div','HelloWorld')
})

以上代码就是把 helloWorld 渲染到 id 为 container 的 div 中

  • 7、在根目录下新建 webpack.config.js 并配置
var path = require('path')

module.exports = {
  // 入口文件
  entry: './src/main.js',
  // 输出
  output: {
    path:path.resolve(__dirname,'./dist'),
    publicPath: '/dist/',
    // 名字叫 bundle.js
    filename: 'bundle.js'
  },

  // 导入的时候就可以不添加后缀后了
  resolve:{
    extensions: ['.js', '.vue']
  },

  devServer: {//webpack-dev-server配置
    historyApiFallback: true,//不跳转
    noInfo: true,
    inline: true,//实时刷新
    hot:true
  }
}

好了基本上完成了,下面我们来测试一下

  • 8、查看结果

在目录所在的命令行中输入以下命令

webpack-dev-server --port 8888 --open --hot

输入上述命令就会自动打开浏览器,并且显示出 HelloWorld 来,我们一个简单的基于 webpack 的 vue demo 就是跑起来了

webpack 的 vue demo 结果

这好像跟组件没有半毛钱关系呀,不要急,我们接着来「就不休息了」

  • 9、我们在 src 中新建一个 first.vue
<template lang="html">
  <div class="">
    我是一个单个组件
  </div>
</template>

<script>
export default {
}
</script>

<style lang="css" scoped>
</style>

以上是一个标准的 vue 组件,并且把这个组件暴露出来,这就是一个单组件

  • 10 、在 main.js 引入 first.vue 组件,修改 main.js
import Vue from 'vue' ;
import first from './first'

new Vue({
  el: '#container',
  render:h => h(first)
})

我们来运行一下,看结果

babel-loader 错误

挂了,从图可以看出说我们缺少 babel-loader「就是用来转化 es6 语法的」,我们安装一下 babel-loader 并配置 webpack

安装 babel-loader「babel 依赖于 babel-core 我们一同安装」

yarn add babel-loader babel-core --dev

配置 webpack.config.js「配置在 module 的 rules 下面」

{
   test:/\.js$/,
   exclude: /node_modules/,
   loader: 'babel-loader'
 }

再运行结果

vue-loader 错误

靠,又挂了,不过这次说的是 vue-loader 的问题,什么是 vue-loader 呢?先说一下 loader 吧,webpack 里面的 loader 的作用就是资源转化,由于 webpack 默认支持 js ,如果你想转化 vue 为 js 模版,那么就要使用 vue-loader ,如果你想把 css 转化成原生的 css 那么就要使用 style-loader 等

vue-loader 是一个加载器,能把以上的类似于 first.vue 组件转化成 JavaScript 模块。这里不过多的介绍 vue-loader。可自行百度,或者我抽出一篇把 webpack 大概说一下

  • 11、安装 vue-loader

我们安装 vue-loader

yarn add vue-loader --dev

运行查看结果:

vue-template-compiler错误

疯了,还报错,但是 vue-loader 错误没有了,这是一个新的错误,说找不到 vue-template-compiler「它就是一个把 vue2.0 模版预编译为渲染函数,避免开销」

好吧,没有办法,我们安装一下

yarn add vue-template-compiler --dev

再次运行查看结果:

单个组件显示

不容易呀,终于显示出来了,不过不要激动,还有一些问题,我们看 chrome 的 cosole 中显示下面错误

css-loader 错误

说的是找不到 css-loader,为什么呢?由于我们使用 vue 的单个组件里面使用了 style 标签,识别不到,就要使用 css-loader,我们安装一下

yarn add css-loader --dev

我们知道安装完 loader 一定要配置一下 webpack , 在 webpack.config.js 中的 module 下的 rules 下添加

{
    test: /\.css$/,
    loader: 'style-loader!css-loader'
},

继续运行查看结果:

添加 css-loader 结果

[图片上传失败...(image-e5a47d-1523543487961)]

完美,调试窗口也没有报错,这样我们就一步一步搭建了一个 类似于 vue-cli 创建 vue 项目「当然没有 vue-cli 那样的完善」

  • 12、我们再建一个组件来丰富一下此 demo 吧

我们定义一个名为 login.vue 的组件

<template lang="html">
<div >
  <h4>我是登录组件,包含在 first.vue 组件中</h4>
  用户名:<input type="text" name="" value="" placeholder="用户名" v-model="username"> <br/>
  密&nbsp;&nbsp;&nbsp;码:<input type="password" name="" value="" placeholder="密码" v-model="userpass"><br/>
  <div >
      <button type="button" name="button" class="loginbutton" @click="login()">登录</button>
      <button type="button" name="button" class="resetbutton" @click="reset()">重置</button>
  </div>
  {{show message}
</div>
</template>

<script>
export default {
  name: 'login',
  data() {
    return {
      // 用户名
      username:'',
      // 密码
      userpass: '',
      // 显示信息
      show message:'
    }
  },
  methods: {
    login() {
      if(this.username.length==0 || this.userpass.length==0){
        this.showmessage = '用户名或密码不能为空!'
        return
      }
      this.showmessage = "欢迎 "+this.username+" 登录"
      this.username = ''
      this.userpass = ''
    },
    reset() {
      this.username = ''
      this.userpass = ''
      this.showmessage = ''
    }
  }
}
</script>

<style lang="css" scoped>
  .loginbutton{
    background: red;
  }
  .resetbutton{
    background-color: green;
  }
</style>

修改 first.vue 组件「引入 login.vue 组件并且使用」

引入 login.vue 组件

运行查看结果

引入 login.vue 组件结果

从以上结果可以看到,我们不仅在 first.vue 中引入了 login.vue 组件,而且 login.vue 组件的方法和事件完美运行

三、总结

本节我们着重介绍了 vue 最重要的特性之一 --- 组件,并用知道了 vue 中的组件有四种形式

  • 1、全局组件--在所有的 vue 实例中都可以使用
  • 2、局部组件--只能在指定的 vue 实例中使用
  • 3、嵌套组件--一个组件中可以嵌套另一个组件
  • 4、单个组件--通过手写类 vue-cli 实现一个 vue demo 并且通过编写单个组件进行组件之间的组合

PS: 我们在开发中,尽量使用单个组件的方式进行开发,这样不仅好维护并且方便阅读,更便于团队之间的协作

到此为止,我们把 vue 的组件就介绍完了,赶紧撸起袖子写一写吧

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容