详解vue组件的三大核心概念

应用开发2025-11-05 13:54:3444

【.com原创稿件】前言

本文主要介绍属性、详解心概事件和插槽这三个vue基础概念、大核使用方法及其容易被忽略的详解心概一些重要细节。如果你阅读别人写的大核组件,也可以从这三个部分展开,详解心概它们可以帮助你快速了解一个组件的大核所有功能。

本文的详解心概代码请猛戳github博客,纸上得来终觉浅,大核大家动手多敲敲代码!详解心概

一、大核属性

1.自定义属性props

prop 定义了这个组件有哪些可配置的详解心概属性,组件的大核核心功能也都是它来确定的。写通用组件时,详解心概props 最好用对象的大核写法,这样可以针对每个属性设置类型、详解心概默认值或自定义校验属性的值,这点在组件开发中很重要,然而很多人却忽视,直接使用 props 的数组用法,这样的组件往往是不严谨的。企商汇

// 父组件   <props name=属性             :type=type             :is-visible="false"             :on-change="handlePropChange"             :list=[22,33,44]             title="属性Demo"             class="test1"             :class="[test2]"             :style="{ marginTop: 20px }" //注意:style 的优先级是要高于 style             style="margin-top: 10px">    </props>  // 子组件    props: {     name: String,      type: {     //从父级传入的 type,它的值必须是指定的 success, warning, danger中的一个,如果传入这三个以外的值,都会抛出一条警告        validator: (value) => {          return [success, warning, danger].includes(value)        }      },     onChange: {      //对于接收的数据,可以是各种数据类型,同样也可以传递一个函数        type: Function,        default: () => { }      },      isVisible: {        type: Boolean,        default: false      },      list: {        type: Array,        // 对象或数组默认值必须从一个工厂函数获取        default: () => []      }    } 

从上面的例子中,可以得出props 可以显示定义一个或一个以上的数据,对于接收的数据,可以是各种数据类型,同样也可以传递一个函数。

2.inheritAttrs

这是2.4.0 新增的一个API,默认情况下父作用域的不被认作 props 的特性绑定将会“回退”且作为普通的 HTML 特性应用在子组件的根元素上。可通过设置 inheritAttrs 为 false,WordPress模板这些默认行为将会被去掉。注意:这个选项不影响 class 和 style 绑定。 上个例子中,title属性没有在子组件中props中声明,就会默认挂在子组件的根元素上,如下图所示: 

3. data与props区别

相同点

两者选项里都可以存放各种类型的数据,当行为操作改变时,所有行为操作所用到和模板所渲染的数据同时都会发生同步变化。

不同点

data 被称之为动态数据,在各自实例中,在任何情况下,我们都可以随意改变它的数据类型和数据结构,不会被任何环境所影响。

props 被称之为静态数据,在各自实例中,一旦在初始化被定义好类型时,基于 Vue 是单向数据流,在数据传递时始终不能改变它的数据类型,而且不允许在子组件中直接操作传递过来的props数据,而是需要通过别的手段,改变传递源中的数据。至于如何改变,我们接下去详细介绍。b2b信息网

4.单向数据流

这个概念出现在组件通信。props的数据都是通过父组件或者更高层级的组件数据或者字面量的方式进行传递的,不允许直接操作改变各自实例中的props数据,而是需要通过别的手段,改变传递源中的数据。那如果有时候我们想修改传递过来的prop,有哪些办法呢?

方法1:过渡到 data 选项中

在子组件的 data 中拷贝一份 prop,data 是可以修改的 。

export default {    props: {      type: String    },   data () {      return {        currentType: this.type      }    }  } 

在 data 选项里通过 currentType接收 props中type数据,相当于对 currentType= type进行一个赋值操作,不仅拿到了 currentType的数据,而且也可以改变 currentType数据。

方法2:利用计算属性        

export default {           props: {            type: String          },         computed: {            normalizedType: function () {               return this.type.toUpperCase();             }           }  } 

以上两种方法虽可以在子组件间接修改props的值,但如果子组件想修改数据并且同步更新到父组件,却无济于事。在一些情况下,我们可能会需要对一个 prop 进行『双向绑定』,此时就推荐以下这两种方法:

方法3:使用.sync   // 父组件 <template>   <div class="hello">     <div>       <p>父组件msg:{{ msg }}</p>       <p>父组件数组:{{ arr }}</p>     </div>     <button @click="show = true">打开model框</button>     <br />     <demo :show.sync="show" :msg.sync="msg" :arr="arr"></demo>   </div> </template> <script> import Demo from "./demo.vue"; export default {   name: "Hello",   components: {     Demo   },   data() {     return {       show: false,       msg: "模拟一个model框",       arr: [1, 2, 3]     };   } }; </script> // 子组件 <template>   <div v-if="show" class="border">     <div>子组件msg:{{ msg }}</div>     <div>子组件数组:{{ arr }}</div>     <button @click="closeModel">关闭model框</button>     <button @click="$emit(update:msg, 浪里行舟)">       改变文字     </button>     <button @click="arr.push(前端工匠)">改变数组</button>    </div> </template> <script> export default {   props: {     msg: {       type: String     },     show: {       type: Boolean     },     arr: {       type: Array //在子组件中改变传递过来数组将会影响到父组件的状态     }   },   methods: {     closeModel() {       this.$emit("update:show", false);     }   } }; ![props.gif](https://upload-images.jianshu.io/upload_images/3174701-389fadc8b85b4661.gif?imageMogr2/auto-orient/strip) 

父组件向子组件 props 里传递了 msg 和 show 两个值,都用了.sync 修饰符,进行双向绑定。

方法4:将父组件中的数据包装成对象传递给子组件

这是因为在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态。比如上例中在子组件中修改父组件传递过来的数组arr,从而改变父组件的状态。

5.向子组件中传递数据时加和不加 v-bind?

对于字面量语法和动态语法,初学者可能在父组件模板中向子组件中传递数据时到底加和不加 v-bind 会感觉迷惑。 

v-bind:msg = msg 

这是通过 v-bind 进行传递数据并且传递的数据并不是一个字面量,双引号里的解析的是一个表达式,同样也可以是实例上定义的数据和方法(其实就是引用一个变量)。 

msg=浪里行舟 

这种在没有 v-bind 的模式下只能传递一个字面量,这个字面量只限于 String 类量,字符串类型。那如果想通过字面量进行数据传递时,**如果想传递非String类型,必须props名前要加上v-bind**,内部通过实例寻找,如果实例方没有此属性和方法,则默认为对应的数据类型。

:msg=11111 //Number  :msg=true //Bootlean  :msg=()=>{console.log(1)} //Function :msg={a:1} //Object ``` 

二、事件

1.事件驱动与数据驱动

用原生JavaScript事件驱动通常是这样的流程:

先通过特定的选择器查找到需要操作的节点 -> 给节点添加相应的事件监听 然后用户执行某事件(点击,输入,后退等等) -> 调用 JavaScript 来修改节点

这种模式对业务来说是没有什么问题,但是从开发成本和效率来说会比较不理想,特别是在业务系统越来越庞大的时候。另一方面,找节点和修改节点这件事,效率本身就很低,因此出现了数据驱动模式。

Vue的一个核心思想是数据驱动。所谓数据驱动,是指视图是由数据驱动生成的,我们对视图的修改,不会直接操作 DOM,而是通过修改数据,其流程如下:

用户执行某个操作 -> 反馈到 VM 处理(可以导致 Model 变动) -> VM 层改变,通过绑定关系直接更新页面对应位置的数据

可以简单地理解:数据驱动不是操作节点的,而是通过虚拟的抽象数据层来直接更新页面。主要就是因为这一点,数据驱动框架才得以有较快的运行速度(因为不需要去折腾节点),并且可以应用到大型项目。

2.修饰符事件

Vue事件分为普通事件和修饰符事件,这里我们主要介绍修饰符事件。

Vue 提供了大量的修饰符封装了这些过滤和判断,让开发者少写代码,把时间都投入到业务、逻辑上,只需要通过一个修饰符去调用。我们先来思考这样问题:怎样给这个自定义组件 custom-component 绑定一个原生的 click 事件? 

<custom-component>组件内容</custom-component>  

如果你的回答是``,那就错了。这里的 @click 是自定义事件 click,并不是原生事件 click。绑定原生的 click 是这样的: 

<custom-component @click.native="xxx">组件内容</custom-component>  

实际开发过程中离不开事件修饰符,常见事件修饰符有以下这些:

- 表单修饰符

1).lazy

在默认情况下,`v-model` 在每次 `input` 事件触发后将输入框的值与数据进行同步 。你可以添加 `lazy` 修饰符,从而转变为使用 `change`事件进行同步。适用于输入完所有内容后,光标离开才更新视图的场景。

2).trim

如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符: 

<input v-model.trim="msg">  

这个修饰符可以过滤掉输入完密码不小心多敲了一下空格的场景。需要注意的是,**它只能过滤首尾的空格**!首尾,中间的是不会过滤的。

3).number

如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符: 

<input v-model.number="value" type="text" /> ``` ![number.gif](https://upload-images.jianshu.io/upload_images/3174701-0bd73cd43bf64ce1.gif?imageMogr2/auto-orient/strip)  

从上面例子,可以得到如果你先输入数字,那它就会限制你输入的只能是数字。如果你先输入字符串,那它就相当于没有加.number

- 事件修饰符 

<!-- 阻止单击事件继续传播 --> <a v-on:click.stop="doThis"></a> <!-- 提交事件不再重载页面 --> <form v-on:submit.prevent="onSubmit"></form> <!-- 修饰符可以串联 --> <a v-on:click.stop.prevent="doThat"></a>  

三、插槽

插槽分为普通插槽和作用域插槽,其实两者很类似,只不过作用域插槽可以接受子组件传递过来的参数。

1.作用域插槽

我们不妨通过一个todolist的例子来了解作用域插槽。如果当item选中后,文字变为黄色(如下图所示),该如何实现呢? 

![slot.gif](https://upload-images.jianshu.io/upload_images/3174701-b5ebab9122420e40.gif?imageMogr2/auto-orient/strip)  // 父组件 <template>   <div class="toList">     <input v-model="info" type="text" /> <button @click="addItem">添加</button>     <ul>       <TodoItem v-for="(item, index) in listData" :key="index">         <template v-slot:item="itemProps"> // 这是个具名插槽         // 其中itemProps的值就是子组件传递过来的对象           <span             :style="{               fontSize: 20px,               color: itemProps.checked ? yellow : blue             }"             >{{ item }}</span           >         </template>       </TodoItem>     </ul>   </div> </template> <script> import TodoItem from "./TodoItem"; export default {   components: {     TodoItem   },   data() {     return {       info: "",       listData: []     };   },   methods: {     addItem() {       this.listData.push(this.info);       this.info = "";     }   } }; </script> // 子组件 <template>   <div>     <li class="item">       <input v-model="checked" type="checkbox" />       <slot name="item" :checked="checked"></slot> // 将checked的值传递给父组件     </li>   </div> </template> <script> export default {   data() {     return {       checked: false     };   } }; </script> 

值得注意:v-bind:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名。

2.新语法

在 2.6.0 中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即 `v-slot` 指令)。它取代了 `slot` 和 `slot-scope` 。

我们通过一个例子介绍下默认插槽、具名插槽和作用域插槽的新语法: 

// 父组件  <template>    <div class="helloSlot">      <h2>2.6 新语法</h2>      <SlotDemo>        <p>默认插槽:default slot</p>        <template v-slot:title>          <p>具名插槽:title slot1</p>          <p>具名插槽:title slot2</p>        </template>        <template v-slot:item="props">          <p>作用域插槽:item slot-scope {{ props }}</p>        </template>      </SlotDemo>    </div>  </template>  <script>  import Slot from "./slot";  export default {    components: {      SlotDemo: Slot    }  };  </script>  // 子组件  <template>    <div>      <slot />      <slot name="title" />      <slot name="item" :propData="propData" />    </div>  </template>  <script>  export default {    data() {      return {        propData: {          value: "浪里行舟"        }      };    }  };  </script>   ![slot](https://upload-images.jianshu.io/upload_images/3174701-1e0368524f073643.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)  

参考文章

珠峰架构课(强烈推荐) Vue开发实战 Vue.js 组件精讲 Vue.js 官方文档 Vue 组件通信全揭秘 vue修饰符--可能是东半球最详细的文档(滑稽)

浪里行舟:硕士研究生,专注于前端。个人公众号:「前端工匠」,致力于打造适合初中级工程师能够快速吸收的一系列优质文章!

【原创稿件,合作站点转载请注明原文作者和出处为.com】

本文地址:http://www.bhae.cn/news/22b21499763.html
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

全站热门

Ubuntu是一个流行的Linux操作系统,基于Debian发行版和GNOME桌面环境,和其他Linux发行版相比,Ubuntu非常易用,和Windows相容性很好,非常适合Windows用户的迁移,预装了大量常用软件,中文版的功能也较全,支持拼音输入法,预装了Firefox、Open Office、多媒体播放、图像处理等大多数常用软件,一般会自动安装网卡、音效卡等设备的驱动,对于不打游戏不用网银的用户来说,基本上能用的功能都有了,在Windows操作系统下不用分区即可安装使用,就如同安装一个应用软件那么容易,整个Ubuntu操作系统在Windows下就如同一个大文件一样,很容易卸载掉。下面我就介绍一下Ubuntu操作系统安装使用的方法,供Ubuntu新手参考,希望能起到Linux扫盲的作用。     下载Ubuntu   Ubuntu有三个版本,分别是桌面版(Desktop Edition),服务器版(Server Edition),上网本版(Netbook Remix),普通桌面电脑使用桌面版即可,下载地址请点这里,32位CPU请选择32bit version,上网本则可下载Netbook Remix,目前Ubuntu已经占据三分之一的上网本市场,仅次于Windows XP系统。Google的Chrome操作系统强有力的对手就是Ubuntu Netbook Remix。   目前最新的版本是9.04版,下载后的文件名是ubuntu-9.04-desktop-i386.iso,大小是698M,通过迅雷下载非常快,大约半个小时左右可以下载完毕。   安装Ubuntu   在Windows下可以不用重新分区,直接像安装一个应用程序那样安装Ubuntu,安装方法是,先使用一个虚拟光驱(例如微软的Windows虚拟光驱)装载ubuntu-9.04-desktop-i386.iso文件,然后运行根目录下的wubi.exe,运行前要将本地磁盘的名字都修改为英文名,否则会出现错误信息“UnicodeEncodeError: ascii codec cant encode characters in position 0-3: ordinal not in range(128)”而无法运行。       运行之后,会出现如下界面,选择“Install inside Windows”即可在Windows下直接安装而无需分区。    接着出现下面的安装界面,选择一个磁盘,然后将语言选择为“Chinese(Simplified)简体中文”,Installation size为Ubuntu环境的总共磁盘大小,然后是登录用户名和密码,设置好了以后就点安装继续。    后面的安装操作很简单,不需要手动干预就可以直接安装好整个操作系统,大部分的硬件驱动都可以自动安装好。提示安装完毕后,重启系统,就可以使用Ubuntu了。   自动登录Ubuntu   Ubuntu默认是每次登录都是要输入用户名和密码的,这是基于安全方面的考虑,不过对于桌面版,大家都习惯自己的电脑能自动登录,类似Windows XP系统那样,通过一些设置可以实现Ubuntu自动登录。设置的方法是:点击“系统”—“系统管理”—“登录窗口” (需要输入管理员密码),然后在“安全”选项页—勾选(启用自动登录),然后在下拉列表里选择自己的用户名。之后Ubuntu就能够自动登录了。   开机自动运行程序   类似Windows的启动菜单,在Linux也可以实现开机自动运行一些命令,比较简单的方法是修改 /etc/rc.local 文件,将需要执行的命令添加进去。     桌面设置   Ubuntu的桌面,默认有两个任务栏,一个在上面,一个在下面,通常习惯Windows的用户喜欢将上面的移到下面,Ubuntu的面板无法拖动,在上面点右键后,可以让其显示在屏幕下端。   桌面背景设置和Windows很类似,在“桌面”上点右键,点更改桌面背景,就可以进行修改设置。   修改root密码   Ubuntu默认的用户并不是root,我们可以通过操作来使用root这个超级管理员帐号,以获得更大的权限。先打开终端,然后执行下面的语句   sudo passwd root   就可以修改超级管理员root的密码,之后就可以使用su命令切换到root用户来执行某些更高权限的操作。   Hosts修改   在Windows下,我们上Twitter等网站都需要修改hosts文件,在Linux下也有hosts文件,文件位于/etc/hosts,使用root用户可以编辑修改这个文件,主机名和IP的格式与Windows的完全相同,例如:   127.0.0.1 localhost   在Ubuntu下安装软件   Ubuntu下的软件安装有几种方式,常用的是deb包的安装方式,deb是debian系列的Linux包管理方式,ubuntu属于debian的派生,也默认支持这种软件安装方式,当下载到一个deb格式的软件后,直接在界面上就可以安装。   另一种常见的安装方式是源代码编译安装,很多软件会提供了源代码给最终用户,用户需要自行编译安装,先使用tar将源代码解压缩到一个目录下,然后进入这个目录,执行以下三条命令:   ./configure     make   sudo make install   执行完成后,即可完成软件的编译和安装。   还有一种方式是apt-get的安装方法,APT是Debian及其衍生发行版的软件包管理器,APT可以自动下载,配置,安装二进制或者源代码格式的软件包,因此简化了Unix系统上管理软件的过程。常用的安装命令是:   sudo apt-get install 软件名   sudo apt-get remove 软件名   Firefox浏览器的更新   Ubuntu安装完成后会自动安装一个Firefox浏览器,遗憾的是这个Firefox版本通常较低,例如Ubuntu 9.04会安装Firefox 3.0,不过我们可以想办法下载最新的Firefox覆盖掉老版本Firefox,具体方法是,先上Firefox官方网站下载最新的Linux版本Firefox,然后将其解压缩到某一个目录下,例如firefox目录,进入终端,到这个目录的父目录,执行下面的语句:   sudo cp -r firefox /usr/lib/firefox-3.5.2   sudo mv /usr/bin/firefox /usr/bin/firefox.old   sudo ln -s /usr/lib/firefox-3.5.2/firefox /usr/bin/firefox-3.5.2   sudo ln -s /usr/bin/firefox-3.5.2 /usr/bin/firefox   之后就可以将Firefox成功替换为最新的Firefox 3.52版本,未来的Firefox更新也可以使用这种方法。     Firefox的Flash问题   经过我的实际测试,Ubuntu自动安装的Flash插件swfdec存在很多问题,在Firefox中,很多网页的Flash无法显示,包括Google音乐和开心网等,因此建议使用下面两条语句将其卸载。   sudo apt-get remove swfdec-mozilla   sudo apt-get remove swfdec-gnome   之后可安装官方的Adobe Flash Player的Linux版,下载地址是: http://get.adobe.com/flashplayer/   安装完成后,还要解决中文乱码问题,解决方法是执行下面语句:   sudo cp /etc/fonts/conf.d/49-sansserif.conf /etc/fonts/conf.d/49-sansserif.conf.bak   sudo rm /etc/fonts/conf.d/49-sansserif.conf   之后,Firefox的Flash就完全正常了,在Firefox中访问开心网等Flash网站,显示都正常。   安装常用软件   介绍完了安装的方法和Firefox,下面就可以去各个网站下载一些常用的Linux软件来安装了,下面是我整理的一些常用的Linux软件列表:   Linux QQ:访问这个地址,下载deb文件安装,可以在Linux下玩腾讯QQ。   防火墙 firestarter: 使用 sudo apt-get install firestarter 安装。   杀毒软件 AntiVir: 虽然Linux下的病毒很少,但对于新手还是有必要安装一个杀毒软件,访问这个地址可以下载免费版的AntiVir杀毒软件,这个软件我曾经在《五个最佳的防病毒软件》中介绍过。   rpm 转 deb 工具: 使用 sudo apt-get install alien 安装   JAVA环境安装: JRE的安装 sudo apt-get install sun-java6-jre ,JDK的安装 sudo apt-get install sun-java6-jdk       eclipse安装: 先到这个地址下载最新的eclipse,然后使用tar xvfz eclipse-php-galileo-linux-gtk.tar.gz -C /opt 解压缩后就可以使用。    Picasa 3 for Linux安装: 访问这个地址,下载后直接安装。   Google Earth安装: 在这里下载最新版本的Google Earth,下载下来是个BIN文件,在图形界面上右击 GoogleEarthLinux.bin,在“权限”选项卡中勾选“允许以程序执行文件”,如下图。    之后在终端上执行 ./GoogleEarthLinux.bin 即可安装。    安装LAMP环境   Ubuntu的桌面版也可以安装LAMP(Linux + Apache + MySQL + PHP)环境,这里我介绍一个最简单的方法,就是使用XAMPP,这个项目我曾经在《常见的WAMP集成环境》中介绍过,XAMPP不但支持Windows,还支持Linux,在其网站下载之后,运行下面两条命令:   tar xvfz xampp-linux-1.7.2.tar.gz -C /opt   /opt/lampp/lampp start   就可以启动LAMP环境,XAMPP是功能全面的集成环境,软件包中包含Apache、MySQL、SQLite、PHP、Perl、FileZilla FTP Server、Tomcat等等,很适合开发环境使用。   安装程序添加程序菜单和桌面       有些程序是直接解压缩安装的,因此不会添加“应用程序”的菜单项,我们可以手动将其添加菜单项,具体方法是,打开“系统”—“首选项”—“主菜单”,新增即可。   添加桌面快捷方式是,在桌面上点右键,创建启动器。这个“启动器”就是Windows里面的“快捷方式”。   将“应用程序”的菜单项创建到桌面快捷方式的方法是,在“应用程序”的菜单项上单击鼠标右键,选择“将此启动器添加到桌面”或“将此启动器添加到面板”,就可以了。

从制作装机U盘到装系统,一篇教程搞定(轻松学习制作装机U盘,快速安装系统)

2017电信卡信号质量调查

笔记本i76700(i76700处理器带来卓越性能体验)

美图手机T8评价(美图T8手机评测报告,带你领略拍照新境界)

以NDS改GBA的实现方法及效果分析(利用NDS设备实现GBA游戏的全新体验)

U盘电脑Windows7系统教程(一步步教你使用U盘安装Windows7系统)

三星yhj70音质如何?(一款值得期待的音质体验)

友情链接

滇ICP备2023000592号-9