Vue「三」—— vue 侦听器、vue 计算属性、vue-cli、vue 组件

本文为 Vue 系列笔记第三篇。参考:>> 黑马程序员 Vue 全套视频教程

系列文章阅读 📑📑

>> Vue「一」—— 前端工程化 、webpack 的基本使用及常用配置

>> Vue「二」—— vue 基本使用 、vue 指令 、vue 过滤器

>> Vue「三」—— vue 侦听器、vue 计算属性、vue-cli、vue 组件

>> Vue「四」—— 组件生命周期、数据共享

>> Vue「五」—— 动态组件、插槽、自定义指令

>> Vue「六」—— 前端路由、vue-router

一、watch 侦听器


1. 侦听器基本语法

watch 侦听器 允许开发者监视数据的变化,从而针对数据的变化做特定的操作。也就是 当数据发生变化时,及时做出响应处理

下面是采取方法格式来定义侦听器,这种方法比较简便常用。此外,如果遇到某些特殊需求时,也可采取对象格式来定义侦听器(后文介绍)。

    <div id="app">
        <input type="text" v-model="username">
    </div>
    <script>
        const vm = new Vue({
            el: "#app",
            data: {
                username: ''
            },
            // 侦听器定义在 watch 节点下
            watch: {
                username(newVal, oldVal) {
                    console.log('👍👍👍', newVal, oldVal);
                }
            }
        })
    </script>

文本框中连续输入 123 ,打印效果如下:
在这里插入图片描述

>> 几个注意点

  1. 所有的侦听器,都应该定义在 watch 节点下。
  2. 侦听器本质上是一个函数,要监听哪个数据的变化,只需把对应数据名作为方法名即可。
  3. 注意新值在前面,旧值在后面。
  4. 此外,这种方法默认不会被自动调用,也就是刚打开页面时不会触发侦听器。

>> 应用场景:使用 watch 检测用户名是否可用

需求:监听 username 值的变化,并使用 axios 发起 Ajax 请求,从服务器获取数据来判断,检测当前输入的用户名是否可用

import axios from 'axios'
export default {
  name: 'MyWatch',
  data() {
    return {
      username: ''
    }
  },
  watch: {
    async username(newVal, oldVal) {
      const { data: res } = await axios.get(`https://www.escook.cn/api/finduser/${newVal}`)
      console.log(res)
    }
  }
}

2. 对象格式的侦听器


此前侦听器的写法是方法格式的写法,也就是直接将对应数据名作为方法名来写函数。这种方法是最常用的,因为它比较简便。

你也可以利用对象格式来定义 watch 侦听器,如下:

	watch: {
	    username: {
	        // handler 是固定写法,表示当 username 的值变化时,自动调用 handler 处理函数
	        handler(newVal, oldVal) {
	            // 。。。
	        }
	    }
	}

这种语法下,需要将侦听器的响应处理写在 handler(){} 方法内。
 

3. immediate 选项


默认情况下,组件在初次加载完毕后不会调用 watch 侦听器。如果想让 watch 侦听器 立即被调用,则需要使用 immediate 选项

     watch: {
        username: {
            handler(newVal, oldVal) {
                console.log(newVal);
            },
            // 默认 false, 控制侦听器是否自动触发
            imediate: true
        }
    }

4. deep 选项


如果 watch 侦听的是一个对象,如果对象中的 属性值发生了变化,则 无法被监听 到。此时需要使用 deep 选项

    watch: {
        info: {
            handler(newVal, oldVal) {
                console.log(newVal.username);
            },
            // 开启深度监听,只要对象中任何属性变化,都会触发
            // deep 默认值为 false
            deep: true
        }
    }

注意:这里的 newVal 是 info 对象,而不是变化的属性值。
 

5. 监听对象单个属性的变化


如果只想监听对象中 单个属性 的变化,则可以按照如下的方式定义 watch 侦听器。

    watch: {
        'info.username': {
            handler(newVal, oldVal) {
                console.log(newVal);
            }
        }
    }

 

二、计算属性


计算属性指的是通过一系列运算之后,最终得到一个属性值。这个动态计算出来的属性值可以被模板结构或 methods 方法使用。

所有的计算属性都要定义在 computed 节点之下,计算属性在定义时要定义成方法格式。如下所示:

    <!-- <div class="box" :style="{ backgroundColor: `rgb(${r}, ${g}, ${b})` }">
        {{ `rgb(${r}, ${g}, ${b})` }}
    </div> -->
    <div class="box" :style="{ backgroundColor: rgb }">
        {{ rgb }}
    </div>
    var vm = new Vue({
        el: '#app',
        data: {
            r: 0, g: 0, b: 0
        },
        computed: {
            rgb() {
                return `rgb(${this.r},${this.g},${this.b})`;
            }
        }
    });

两点好处:

  1. 计算属性提高了代码的复用。
  2. 当所依赖数据发生变化(data 中数据变化)时,它会自动重新运算。

三、vue-cli


1. 单页面应用程序

单页面应用程序 (Single Page Application)简称 SPA,指的是一个 Web 网站只有唯一的一个 HTML 页面,所有的功能与交互都在这唯一的一个页面内完成。

在这里插入图片描述
如上图所示,整个项目都是通过唯一一个 HTML 页面 index.html 来呈现的,这就叫做单页面应用程序。

2. 什么是 vue-cli


vue-cli 是 Vue.js 开发的标准工具。它简化了程序员基于 webpack 创建工程化 Vue 项目的过程。

vue-cli 官网 是这样介绍的:Vue CLI 致力于将 Vue 生态中的工具基础标准化。它确保了各种构建工具能够基于智能的默认配置即可平稳衔接,这样你可以专注在撰写应用上,而不必花好几天去纠结配置的问题。

3. vue-cli 的安装


vue-cli 是 npm 上的一个 全局包,可以通过 npm 进行安装:

	npm install -g @vue/cli

4. vue-cli 的使用


  1. 在终端下运行如下的命令,创建指定名称的项目
	 vue create 项目名称
  1. 手动选择要安装的模式,建议初学时选择第三项,可以自定义很多功能。
    在这里插入图片描述
  2. 手动选择要安装哪些功能,建议如下配置(空格:选中/ 取消):
    在这里插入图片描述
  3. 选择 vue 的版本,目前先选择 2.x。
    在这里插入图片描述
  4. 选择 css 预处理器,目前只学过 Less,因此选择 Less 即可。
    在这里插入图片描述
  5. 选择第三方插件配置文件如何放置,默认选择第一项,各种文件配置信息独立放置。
    在这里插入图片描述
  6. 是否将此前是选择作为预设,方便以后不用每次都重复同样配置。
  7. 项目成功创建完成。
    在这里插入图片描述

>> 分析一下 vue 项目下的 src 目录的构成
在这里插入图片描述

assets 文件夹:存放项目中用到的静态资源文件,例如:css 样式表、图片资源。

components 文件夹:存放封装的、可复用的组件。

main.js:项目的入口文件。整个项目的运行,要先执行 main.js。

App.vue: 项目的根组件。

5. vue 项目的运行流程


在工程化的项目中,vue 要做的事情很单纯:通过 main.js App.vue 渲染到 index.html 的指定区域中。

  1. App.vue 用来编写待渲染的 模板结构
  2. index.html 中需要预留一个 el 区域
  3. main.js 把 App.vue 渲染到了 index.html 所预留的区域

 

四、vue 组件


1. vue 中的组件化开发

组件化开发 指的是:根据封装的思想,把页面上 可重用的 UI 结构 封装为组件,从而方便项目的开发和维护。

vue 是一个 支持组件化开发 的前端框架。vue 中规定:组件的后缀名是 .vue。之前接触到的 App.vue 文件本质上就是一个 vue 的组件。

 

2. vue 组件的三个组成部分


每个 .vue 组件都由 3 部分构成,分别是:

  • template:组件的模板结构
  • script:组件的 JavaScript 行为
  • style:组件的样式

 
>> template

vue 规定:每个组件对应的 模板结构,需要定义到 <template> 节点中。如下:

<!--组件的 UI 结构模板-->
<template>
  <!--此处定义当前组件的 DOM 结构-->
</template>

❗❗ 注意:

  1. template 是 vue 提供的容器标签,只起到 包裹 性质的作用,它不会被渲染为真正的 DOM 元素
  2. template 中只能包含 唯一的根节点

 
>> script

vue 规定:开发者可以在 <script> 节点中封装组件的 JavaScript 业务逻辑 。如下:

<script>
// 默认导出,固定写法
export default {
  data() {
    return {
      // return 中定义数据
    };
  },
  // 组件中的方法
  methods: {},
  // 组件中的侦听器
  watch: {},
  // 组件中的计算属性
  computed: {},
  // 组件中的过滤器
  filters: {},
};
</script>

❗❗ 注意:

  1. 组件相关的 data、methods 等等都需要放在 export default {} 所导出的对象中。
  2. .vue 组件中的 data 必须是一个函数,不能直接指向一个数据对象。否则会导致多个组件实例共用同一份数据的问题。

 
>> style

组件内的 <style> 节点是可选的,开发者可以在 <style> 节点中 编写样式 美化当前组件的 UI 结构。如下:

<!--组件的样式-->
<style>
	/* 定义样式 */
</style>

>> style 中支持 less 语法,可以这么做:

<style> 标签上添加 lang="less" 属性,即可使用 less 语法编写组件的样式:

<style lang="less">
	/* 定义 less 语法的样式 */
</style>

 

3. 组件之间的父子关系


在这里插入图片描述

>> 使用组件的三个步骤

在 App.vue 文件中进行如下操作,即可将 Left 和 Right 组件嵌套在 App 组件中:

  1. 使用 import 语法导入需要的组件
  2. 使用 components 节点 注册组件
  3. 标签形式 使用刚才注册的组件

在这里插入图片描述
其中,各组件关系如下:
在这里插入图片描述
 

4. 私有子组件与全局组件


>> 通过 components 注册的是 私有子组件

例如,在组件 A 的 components 节点下,注册了组件 F。则组件 F 只能用在组件 A 中;不能被用在组件 C 中。

可以看出,如果有一个组件频繁的被用到,就变得很麻烦,需要每次引入。这时,我们可以使用下面所要介绍的 全局组件

 
>> 注册 全局组件

在 vue 项目的 main.js 入口文件中,通过 Vue.component() 方法,可以注册全局组件。这样以后每次使用时,不再需要重复注册,一劳永逸。

例如,这里打算将 Count.vue 设为全局组件,可以在 main.js 入口文件中这样设置:
在这里插入图片描述
此后,在其他组件中使用到这个全局组件 Count.vue 时,只需写标签 <MyCount></MyCount> 即可。

 

5. 组件的 props


props 是组件的 自定义属性,在封装通用组件的时候,合理地使用 props 可以极大的提高组件的复用性。

在 Count.vue 组件中设置自定义属性 init

	export default {
	  // props 是"自定义属性",允许使用者通过自定义属性,为当前组件指定初始值
	  // 自定义属性可以定义多个,可以取任意合法名称
	  props: ['init'],	
	
	  data() {
	    return {
	      // 数据
	    }
	  },
	}

当使用到 MyCount 组件(上面的 Count.vue)时,就可以这样定义自定义属性:

    <MyCount init="6"></MyCount>

❗❗ 注意:上面的 init 被赋值了一个字符串 "6",而不是数字 6。这时,如果你想要的赋值是数字型,可以结合 v-bind 来使用,写成如下形式:

    <MyCount :init="6"></MyCount>

 
>> 此外,再强调几点 props 使用事项


1. props 是只读的

vue 规定:组件中封装的 自定义属性是只读的,程序员不能直接修改 props 的值,否则会直接报错。

	<button @click="init += 1">+1</button>

如上代码,点击按钮使得自定义属性 init 完成自增时,发现网页给出报错:
在这里插入图片描述
要想修改 props 的值,可以 把 props 的值转存到 data 中,因为 data 中的数据都是可读可写的。

	data() {
	   return {
	     // 把 props 中的 init 值,转存到 count 上
	     count: this.init,
	   };
	 },

2. props 的其他可选项

在声明自定义属性时,还可以将其指定为 对象形式 而非数组形式,同时指定如下可选项:

  • default:定义属性的默认值
  • type:定义属性的值类型
  • required:将属性设置为必填项,强制用户必须传递属性的值
  props: {
    init: {
      // 如果外界使用 Count 组件的时候,没有传递 init 属性,则默认值生效
      default: 0,
      // init 的值类型必须是 Number 数字
      type: Number,
      // 必填项校验
      required: true
    }
  },

 

6. 组件之间的样式冲突问题


默认情况下,写在 .vue 组件中的 样式会全局生效,因此很容易造成多个组件之间的样式冲突问题。

导致组件之间样式冲突的根本原因是:

  1. 单页面应用程序中,所有组件的 DOM 结构,都是基于唯一的 index.html 页面进行呈现的
  2. 每个组件中的样式,都会影响整个 index.html 页面中的 DOM 元素

>> 如何解决样式冲突问题呢?

为了提高开发效率和开发体验,vue 为 style 节点 提供了 scoped 属性,从而防止组件之间的样式冲突问题。

<style lang="less" scoped>
	h3 {
	  color: red;
	}
</style>

而它的原理就是,scoped 属性自动为每个组件分配了唯一的 “ 自定义属性 ”。该组件中的 DOM 标签和 style 样式都应用了这个自定义属性,这样就解决了样式冲突的问题。
在这里插入图片描述
 
>> /deep/ 样式穿透

如果给当前组件的 style 节点添加了 scoped 属性,则当前组件的样式 对其子组件是不生效的。如果想让某些样式对子组件生效,可以使用 /deep/ 深度选择器

<style>
	/* 当使用第三方组件库的时候,如果有修改第三方组件默认样式的需求,需要用到 /deep/ */
	/deep/ h5 {
	  color: pink;
	}
</style>

👍👍 应用场景:通过父组件直接修改子组件样式。一般在引入第三方库时,需要修改第三方库中元素样式时使用,从而避免了查找第三方库源码修改的困难。


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

imByte

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值