首页 > 技术分享 > Vue
收藏

vue组件基础

12/23 20:56
大潇博客 原创文章,转载请标明出处

1、认识vue组件

组件是 vue 最基础、最常用的功能

vue 组件化就是把页面分割成不同模块,每个模块视为一个组件,每个组件包含三部分:内容(模板代码)、功能(js代码)、样式(css 代码,less 等需要构建工具支撑)。

开发组件三步骤:

⑴ 创建组件

⑵ 注册组件(全局注册、局部注册)

⑶ 应用组件

提示:在使用 Vue 组件,建议先理解 ES6 的箭头函数、模块化等基础知识。


2、创建组件

每个 .vue 文件即可视作一个组件,每个组件由 3 部分构成,如下:(注意:每个组件必须包含 template 模板结构,缺失此部分启动 vue 时会报错,而 script 行为和 style 样式是可选的组成部分)

template: 组件的模板结构

script: 组件的 javascript 行为

style: 组件的样式

导出组件:(省去此部分 vue 也能正常运行,但缺失 name 属性后,可能出现不可预期的错误)

<script>

export default{

name: 'Swiper',

props: [],

methods: {}

}

</script>

常用的组件配置对象:

export default {

//返回数据

data(){

return {

//变量

}

},

computed: {

//计算属性

},

methods: {

//方法

},

template: `...模板`,

render(m){ ... }

}


3、组件命名

官方推荐的两种组件命名法:

⑴ PascalCase 命名法,俗称帕斯卡命名或大驼峰命名法,比如:MyTitle

⑵ kebab-case 命令法,俗称短横线命名法,比如:my-title

用大驼峰命名后,使用组件时既可以使用驼峰式,也可使用短横线式,比较灵活,实际卡法中推荐使用。


4、注册组件

注册组件分为局部注册和全局注册。一些组件在开发期间的使用频率很高,推荐进行全局注册。其它大部分场景不建议使用全局注册,因为使用构建工具时,可能会导致工具无法优化打包,影响打包结果,一般情况是组件在哪里用,就在哪里注册。

⑴ 局部注册:在 Vue 实例中,使用 import 引入组件,然后使用 components 注册(速写属性即可)

比如定义一个组件 Title,在 Vue 配置中局部注册:

<template>

<title></title>

</template>

<script>

import Title from '../Title.vue'

export default ({

components: {Title}

});

</script>

⑵ 全局注册:全局注册的组件,整个应用中任何地方都可以使用(包括 Vue 实例中,其它组件中)

编辑 src 目录下的 main.js,添加如下代码进行组件全局注册

import { createApp } from 'vue'

import App from './App.vue'

const app = createApp(App)

// 1. 导入组件

import Swiper from './components/Swiper.vue';

// 2. 调用 app 实例的 component() 方法,在全局注册 my-swiper 组件

app.component('my-swiper', Swiper);

app.mount("#app");

使用全局注册的组件,任意的 .vue 文件中都可直接使用

<template>

<my-swiper></my-swiper>

</template>

注意:组件之间可以相互使用,没有注册的组件不能使用


5、应用组件:

把注册的组件当成一个元素来用,有两种写法,“<组件名/>” 和 “<组件名></组件名>”

比如使用大驼峰命名法注册了一个全局组件:

app.component("MyTitle", title);

使用方法:

<template>

<MyTitle />  //写法一

<MyTitle></MyTitle>  //写法二

<my-title />   //写法三

<my-title></my-title>   //写法四

</template>


6、组件封装原则

为了提高组件的复用性,在封装 vue 组件时需要遵守如下的原则

组件的 DOM 结构、style 样式要尽量复用

组件中要展示的数据,尽量由组件的使用者提供


7、template中的根节点

在 vue2.x 的版本中,<template> 节点内的 DOM 结构仅支持单个根节点:

<template>

<!-- 在vue2.x中,template节点内的所有元素,最外层必须有唯一的根节点进行包裹,否则报错-->

<div>

<h1>这是标题</h1>

<h2>这是副标题</h2>

</div>

</template>

在 vue3.x 的版本中,<template> 中支持定义多个根节点:

<template>

<!-- 这是包含多个根节点的template结构,因为h1标签和h2标签外层没有包裹性质的根元素 -->

<h1>这是标题</h1>

<h2>这是副标题</h2>

</template>


8、组件中可以使用的指令

组件内的属性也可以被提取到Vue实例中,因此在组件内可以通过 {{属性名}} 直接使用

在组件的 template 节点中使用指令,支持常用的 vue 指令语法,来辅助开发者渲染当前的 dom 结构,比如:

<template>

<!-- 使用 {{}} 插值表达式 -->

<p>生成随机数:{{ (Math.random() * 10).toFixed(2) }}</p>

<!-- 使用 v-bind 属性绑定-->

<p :title="new Date().toLocaleTimeString()">生成日期</p>

<!-- 属性 v-on 事件绑定-->

<button @click="showInfo">显示</button>

</template>


9、在浏览器中调试vue

在 Chorm 浏览器中安装 vue 插件,通过插件即可查看组件信息











创建组件

创建一个最最简单的组件:

var title = {

      template: `<h1>我是标题</h1>`

}

创建一个包含数据的组件:

var title = {

      data(){

            return {

                  title: '内容管理系统'

            }

      },

      template: `<h1>{{title}}</h1>`

}

通过上面案例可以看出:

在Vue中创建组件,就是创建一个配置对象,该配置对象和Vue实例的配置几乎一样。

注意:在组件中,如果要声明data数据,不能直接指向对象(比如使用 data:{} 这种格式),必须要指向一个函数,在函数中对外return一个对象,才能够真正返回数据。


 











向组件传递数据:

在Vue中,实例或组件的data属性用来配置变量,但data()是组件内部的,不推荐修改,所以不能用data接收数据

向组件传入数据的方式有很多种,最常用的是组件属性props,父组件通过props向子组件传递要展示的数据,供子组件内部进行使用,类似于函数传参


首先在组件里申明需要接收哪些属性

var MyCom = {

      props: ['title','page','pagesize'],

      template: `<h1>{{title}}</h1>`

}

使用组件时,向其传递属性,有如下几种方式:

1、直接传字符串,比如title="雇员管理系统"

2、使用v-bind绑定变量,比如 v-bind:page="page" 或 :page="page"

3、使用v-bind固定参数类型,比如 :pagesize="10",此时传入数字10,类型为int

4、使用v-bind传入固定字符串+变量,比如 :author="'post by' + info.author",此时传入一个字符串“post by”,还有一个变量 info.author

new Vue({

      components: {

            MyCom

      },

      data: {

            page: 1

      },

      template: `

            <div>

                  <!-- 组件中使用参数(直接写变量名,无需被括号包裹)-->

                  <MyCom title="雇员管理系统" :page="page" :pagesize="10" />

            </div>

      `

}).$mount("#app");


需要注意的是,props有两种格式,一种是数组,其中只写参数名即可,如上所示,另一种是对象格式,如:

var MyCom = {

      props: {

            title: '',

            page: '',

            pagesize: {},

      }

}

既然有对象格式,说明它可以做一些配置,比如数据合法性的校验:

var MyCom = {

      props: {

            //约束类型,指向类型(并非赋值)

            title: String,  //字符串

            size: Number,   //数字

            //约束多个类型,指向数组(并非赋值)

            page: [String, Number, Object],

            //自定义校验规则

            pagesize: {

                  type: Boolean,   //约束类型

                  required: true,   //必传属性,不传值会在终端中提示

                  default: 10         //默认值                  

            },

            //在封装组件时,可以为prop属性指定自定义的验证函数,从而对prop属性的值进行更加精确的控制

            //通过“配置对象”的形式,定义name属性的“验证规则”

            name: {

                  //通过validator函数,对propA属性的值进行校验,“属性的值”可以通过形参value进行接收

                  validator: function(n){

                         //name属性的值,必须匹配下列字符串中的一个

                         //validator函数返回true表示验证通过,false表示验证失败

                         return n==='fine' || n==='ok';

                         //return ['Tom', 'Jack', 'Lucy'].indexOf(n) !== -1;  //是否存在某个值

                         //return false;  //直接返回false

                  }

            }

      }

}

prop属性支持的基础校验类型:

export default{

props: {

propA: String        //字符串类型

propB: Number    //数字类型

propC: Boolean    //布尔值类型

propD: Array        //数组类型

propE: Object       //对象类型

propF: Date          //日期类型

propG: Function   //函数类型

propH: Symbol     //符号类型

}

}

定义类型校验后,若传入的类型不匹配,会在控制台做出提示,并不过抛出错误,编译也能正常进行,会把传入的值实际赋值给对应的属性,比如布尔值true,会被编辑成字符串“true”。

注意:在组件中,props中的属性为只读,不可在组件中更改props中属性的值,这叫做单项数据流(即:组件中定义的属性,组件自己不可以修改)


如果父组件给子组件传递了未声明的props属性,则这些属性会被忽略,无法被子组件使用;如果父组件没有传递子组件中声明的props属性,则这些属性也会被忽略,不会报错


prop的大小写命名问题

组件中如果使用了“came-Case(驼峰命名法)”声明了 props 属性的名称,则有两种方式为其绑定属性的值:

# 子组件

<template>

<h2>{{dateTime}}</h2>

</template>

<script>

export default {

name: 'Article',

props: ['dateTime']

}

</script>


# 父组件

<template>

<Article dateTime="2020-12-20" />

<Article date-time="2020-12-20" />

</template>


 




打赏

阅读排行

大家都在搜

博客维护不易,感谢你的肯定
扫码打赏,建议金额1-10元
  • 15601023311