Vue2基础入门

497 阅读8分钟

1.vue是什么

Vue是一个用于 构建用户界面 的 渐进式 框架

1.构建用户界面:基于数据动态渲染页面

2.渐进式:循序渐进的学习

3.框架:一套完整的项目解决方案,提升开发效率(理解记忆规则)

2.快速上手

安装插件:vue-devtools

  1. 直接访问谷歌商店, 搜索并安装
  2. 打开极简插件官网, 下载后, 拖拽至扩展程序中安装

3.el与data

el的两种写法

<!-- 直接绑定 -->
<script>
  const app = new Vue({
    el:'#app' //第一种写法,直接绑定
    data: {
  	  msg:'hello world'
    }
  })
</script>

<!-- 使用mount函数 -->
<script>
  const app = new Vue({
    data: {
      msg:'hello world'
    }
  })
  app.$mount('#app')
</script>

data两种写法

<!-- 对象式 -->
<script>
  const app = new Vue({
    el:'#app' 
    data: {
      msg:'hello world'
    }
  })
</script>

<!-- 函数式 -->
<script>
  const app = new Vue({
    el:'#app' 
    data:function(){
      return {
        msg:'hello world'
      }
    }
  })
</script>

4.MVVM模型

MVVM 是 Vue 实现数据驱动视图和双向数据绑定的核心原理。MVVM 指的是 Model、View 和 ViewModel,它把每个 HTML 页面都拆分成了这三个部分,如图所示:

MVVM示意图.png

Model:表示当前页面渲染时所依赖的数据源

View:表示当前页面所渲染的 DOM 结构

ViewModel:表示 vue 的实例,它是 MVVM 的核心

ViewModel 作为 MVVM 的核心,是它把当前页面的数据源(Model)和页面的结构(View)连接在了一起

MVVM工作原理.png

当数据源发生变化时,会被 ViewModel 监听到,VM 会根据最新的数据源自动更新页面的结构

当表单元素的值发生变化时,也会被 VM 监听到,VM 会把变化过后最新的值自动同步到 Model 数据源中

5.vue的相关指令

5.1作用:

①Vue 会根据不同的指令实现不同的功能

②可以把指令看做一个特殊的 HTML 属性, 都是以 v- 开头

5.2相关指令

作用示例注意事项
v-html设置元素的 innerHTML<div v-html="表达式"></div>
v-if 和 v-show控制元素显示隐藏<div v-if="表达式"></div> <div v-show="表达式"></div>v-show 是控制 display: none 来实现显示隐藏的, 适合频繁切换显示隐藏的场景。
v-if 是创建/删除 DOM 元素来实现显示隐藏的, 适合初始状态就确定显示隐藏的场景
v-else 和 v-else-ifv-if 的多分支结构v-else 必须紧贴着 v-if 或 v-else-if, 中间不能间隔其他元素, 注释除外
v-on(简写@click)绑定事件内联语句=》<button v-on:事件名="内联语句" />绑定事件处理函数
<button v-on:事件名="事件处理函数" />
需要在 methods 中声明事件处理函数
new Vue({
el: '#app',
data: {},
v-bind简写 :属性名动态设置 HTML 属性(src href title ...)<img v-bind:属性名="表达式" />
v-for循环渲染标签元素的v-for="(每一项, 索引) in 数组"v-for 写在哪个标签上就代表循环渲染哪个标签
v-model主要用于表单元素的双向数据绑定语法:v-model="vue 变量"效果:数据变化, 视图会自动更新
用户输入内容, 数据自动更新
key属性唯一标识, 用于让 Vue 来区分数据项, 自动进行排列顺序的如果没设置 key 则默认按照就地更新策略, 尽可能复用标签, 从而不删除当前元素字符串或数字
类型必须是唯一的, 不能重复
推荐使用 id 作为 key

6.指令修饰符

简介:通过"."指明一些指令后缀,不同后缀封装了不同的处理操作

6.1 按键修饰符

@keyup.enter

6.2 v-model修饰符

v-model.trim 去除首尾空格

v-model.number 转数字

6.3 事件修饰符

Vue中的事件修饰符:

1.prevent:阻止默认行为(常用)

阻止a标签的跳转

方法1:@事件名.prevent=》阻止默认行为
方法2:event.preventDefault()

2.stop:阻止事件冒泡(常用)

方法1:@事件名.stop=》阻止冒泡
方法2:event.stopPropagation()

3.once:事件只触发一次(常用)

4.capture:使用事件的捕获模式

5.self:只有event.target是当前操作的元素时才触发事件

6.passive:事件的默认行为立即执行,无需等待事件回调执行完成

7.v-bind对于样式操作的增强

5.1 class类名

:class="{类名1:布尔值,类名2:布尔值}" 适用场景:一个类名,来回切换

:class="[类名1,类名2,类名3]" 适用场景:批量添加或删除类

5.2 style行内样式

:style="{css属性名1:css属性值,css属性名2:css属性值}" :style="{width:100px}"

8.v-model应用于其他表单元素

常见的表单元素都可以用v-model绑定关联_->快速获取或设置表单元素

输入框 input:text value

文本框 textarea value

复选框 input:checkbox ①绑定的是数组,向数组中添加value

②绑定的是布尔值,改变的是checked

单选框 input:radio value

下拉菜单 select value

9.computed计算属性

9.1 概念:基于现有的数据,计算出来的新属性,依赖的数据变化,自动重新计算

9.2 语法:

①声明在computed配置项中,一个计算属性对应一个函数

②使用起来和普通属性一样使用{{计算属性名}}

computed: {
  计算属性名 () {
	//基于现有数据,编写求值逻辑
    return 结果
  }
},

计算属性默认简写,只能访问,不能修改。如果要修改,需要使用完整写法

  • 完整写法:计算属性是一个对象,对象中拥有两个方法(get / set),get 相当于以前的简写函数
  • 当计算属性被赋值时,计算属性的set会执行
computed: {
  计算属性名: {
    get() {
      //一段代码逻辑(计算逻辑)
      return 结果
  	},
  	set(修改的值) {
      //一段代码逻辑(修改逻辑)
  	}
  }
}

计算属性与普通方法的区别在于:computed具有缓存特性、自动依赖追踪,适用于衍生数据的计算;而methods没有缓存和自动追踪依赖,适用于执行函数操作和处理事件

10.watch侦听器

watch 侦听器用于监视数据变化,执行一些业务逻辑异步操作

  • 简写
    • 监听器名需要和数据名完全相同,当数据变化时自动执行该函数
    • 简单类型数据,直接监视
    • 数据是一个对象的属性,可以把函数名定义成:对象.属性
watch: {
  数据属性名(newValue, oldValue) {
  	//一些业务逻辑 或 异步操作
  },
  '对象.属性名'(newValue, oldValue) {
  	//一些业务逻辑 或 异步操作
  }
}

完整写法(添加额外配置项)

  • deep: true 对复杂类型深度监视
  • immediate: true 初始化立刻执行一次handler方法
watch: {
  数据属性名: { 
    deep: true, // 深度监视(针对复杂类型)
    immediate: true, // 是否立刻执行一次handler
    handler (newValue, oldValue) {
  	  console.log(newValue, oldValue)
    }
  }
}

11.vue的生命周期

vue里面的生命周期函数有哪些?Vue父子组件生命周期顺序?

它是指vue的实例对象从创建到销毁的过程,有四个周期八个钩子函数。一般在created函数中发送ajax请求获取

数据,在mounted中获取挂载完毕的真实dom,destroy中销毁定时器,延时器或绑定的一些事件。

初始化、挂载、更新、销毁。beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed

创建的时候有4个: beforeCreate created beforeMount mounted

更新的时候 是 beforeUpdate updated

销毁的时候 是 beforeDestroy destroyed

如果组件有缓存,就是加上了keep-alive以后,会多两个生命周期函数, activeted deactiveted

在父子组件里面的生命周期:

先执行父组件的3个钩子函数 -- 然后执行完子组件的创建时期的4个钩子函数 --- 最后再执行父组件的mounted钩

子函数 (Parent beforeCreate -> Parent Created -> Parent BeforeMount -> Child BeforeCreate -> Child

Created -> Child BeforeMount -> Child Mounted -> Parent Mounted)

vue2生命周期.png

12.工程化开发和脚手架

1.开发vue的两种方式

  • 核心包传统开发模式:基于html / css / js 文件,直接引入核心包,开发 Vue。
  • 工程化开发模式:基于构建工具(例如:webpack)的环境中开发Vue。

工程化开发.png

工程化开发模式优点:

提高编码效率,比如使用JS新语法、Less/Sass、Typescript等通过webpack都可以编译成浏览器识别的ES3/ES5/CSS等

工程化开发模式问题:

  • webpack配置不简单
  • 雷同的基础配置
  • 缺乏统一的标准

为了解决以上问题,所以我们需要一个工具,生成标准化的配置

2.脚手架Vue CLI

基本介绍:

Vue CLI 是Vue官方提供的一个全局命令工具

可以帮助我们快速创建一个开发Vue项目的标准化基础架子。【集成了webpack配置】

好处:

  1. 开箱即用,零配置
  2. 内置babel等工具
  3. 标准化的webpack配置

使用步骤:

  1. 全局安装(只需安装一次即可) yarn global add @vue/cli 或者 npm i @vue/cli -g
  2. 查看vue/cli版本: vue --version
  3. 创建项目架子:vue create project-name(项目名不能使用中文)
  4. 启动项目:yarn serve 或者 npm run serve(命令不固定,找package.json)

13.项目目录介绍和运行流程

1.项目目录

项目目录.png

虽然脚手架中的文件有很多,目前咱们只需人事三个文件即可

  1. main.js 入口文件
  2. App.vue App根组件
  3. index.html 模板文件

2.运行流程

运行流程.png

3.关于不同版本的Vue

  • vue.js与vue.runtime.xxx.js的区别:

(1)vue.js是完整版的Vue,包含:核心功能+模板解析器。

​ (2)vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。

  • 因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收到的

    createElement函数去指定具体内容。

4.vue.config.js配置文件

使用vue inspect > output.js 可以查看Vue脚手架的默认配置。

使用vue.config.js可以对脚手架进行个性化定制,详情见:cli.vuejs.org/zh

14.组件化

1.好处

便于维护,利于复用。

把页面拆分成一个个组件来开发

2.组件是什么

定义:.vue结尾的文件就是一个组件

组成:template,script,style

template 有且只能有一个根元素

script

style lang设置less预处理器,记得装包 npm i less less-loader -g

3.组件的使用

分为局部注册和全局注册

组件的使用.png

4.组件三大组成部分的注意点

结构:有且只能有一个根元素

样式:默认全局样式,加上scoped局部样式

逻辑:data是一个函数,保证数据独立

15.scoped的原理

1.给当前组件的所有标签添加自定义属性data-v-hash,当前组件的hash值与其他组件的hash不相等2.

2.css样式是属性交集选择器,改变当前组件的样式其他组件不受影响

16.vue路由模式=>hash和history

区别:

路由有两种模式:hash和history

1、hash有#号 ,history没有#号

2、hash不会刷新页面,不会向服务器发送请求【刷新没有任何影响】。history会刷新页面,向这个地址发送请求。

【刷新页面】===因为会向服务器请求这个地址

3、hash上线不需要任何操作没有任何影响,但是history会出现页面找不到,因为会向服务器发送请求,所以需要服务器帮助解决。

原理:hash:hashchange history:popState replaceState

跳转方式2种:声明式导航和编程式导航跳转。

​ 声明式导航跳转是route-link,to里面的是地址

​ 编程式跳转用this.$router.push('跳转的路径')

传参方式有2种:query传参(有?号)和params传参(没有?号)。

​ query用$route.query.参数名 接收参数,

​ params是用$route.params.参数名 来接收参数

导航守卫钩子函数:beforeEach,afterEach

nginx配置:

history刷新页面找不到.png

17.vuex的几个概念?

Vuex 的核心概念包括:State(状态)、Mutation(变化)、Action(动作)、Getter(获取器)、Module(模块)

State

State 提供唯一的公共数据源,所有共享的数据都要统一放到 Store 中的 State 中存储。在 state 对象中可以添加我们要共享的数据

mutations

state 数据的修改只能通过 mutations,并且 mutations 必须是同步的。mutations 是一个对象,对象中存放修改 state 的方法

actions

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态
  • Action 可以包含任意异步操作

getters

获取器用于从状态中派生出新的状态。它可以将现有的状态进行计算和转换,并提供一个类似于计算属性的方式来访问这些派生状态

modules

Module(模块): 模块可以将整个状态树分割成更小的模块,每个模块都有自己的状态(state)、变化(mutation)、动作(action) 和获取器(getter)。这样可以将复杂的应用程序拆分成可维护和可测试的模块。通过模块化的方式,可以更好地组织和维护大型的状态管理

18.vuex在组件里面怎么使用

在vuex里面 先要定义修改数据的mutations,以及发请求的actions,在actions函数里面去 commit提交mutations

在业务组件里面,直接通过dispatch分发我们的actions

19.组件通信

定义:就是指组件与组件之间的数据传递

注意点:组件的数据是独立的,无法直接访问其他组件的数据。

想用其他组件的数据->组件通信

1.props/$emit父子组件通信

父传子=》首先在父组件中子组件定义自定义属性,在子组件里通过props接收父组件传递的数据。

子传父=》子组件用$emit来触发自定义事件,并且可以传递参数给父组件。父组件通过监听子组件的自定义事件来获取传递的数据

2.ref与parent/parent/children适用父子组件通信

3.EventBus(emit/emit/on)兄弟组件传值

【main.js=>原型对象上 vue.prototype.Bus=newvue()兄:this.Bus=new vue() 兄:this.Bus.emit() 弟:this.$Bus.on】

在全局使用eventBus挂载属性,通过eventBus挂载属性,通过emit/on,来传值

4.provide/inject适用后代组件通信

provide/inject

5.attrs/attrs/listeners适用于隔代组件通信

6.Vuex适用于父子、隔代、兄弟组件通信

Vuex 的核心概念包括:State(状态)、Mutation(变化)、Action(动作)、Getter(获取器)、Module(模块)

20.插槽

默认插槽

默认插槽的主要作用是让组件内部的一些结构支持自定义

  • 组件内需要定制的结构部分,改用<slot></slot>占位
  • 使用组件时, 在组件标签内部传入自定义结构来替换 slot
<!-- 在Card组件中 -->
<template>
  <div class="card">
    <div class="card-header">标题</div>
    <div class="card-body">
      <!-- 这里是默认插槽的位置 -->
      <slot></slot>
    </div>
  </div>
</template>

<!-- 使用Card组件 -->
<Card>
  <!-- 此处会替换slot -->
  <p>这是卡片的主要内容</p>
  <p>可以是文本、图片等各种元素</p>
</Card>

插槽后备内容(默认值):

  • 封装组件时,可以为预留的 <slot> 插槽提供后备内容(默认内容)
  • 外部使用组件时,不传内容,则 slot 会显示后备内容;外部使用组件时,传入内容,则 slot 整体会被替换
<!-- 在Card组件中 -->
<template>
  <div class="card">
    <div class="card-header">标题</div>
    <div class="card-body">
      <slot><p>这是插槽后备内容</p></slot>
    </div>
  </div>
</template>

具名插槽

具名插槽,顾名思义就是具有名字的插槽,可以将一个组件中的多处结构进行定制

具名插槽语法:

  • 多个 slot 使用 name 属性区分名字(子组件中)
<div class="dialog-header">
  <slot name="head"></slot>
</div>
<div class="dialog-content">
  <slot name="content"></slot>
</div>
<div class="dialog-footer">
  <slot name="footer"></slot>
</div>

  • template 配合 v-slot:插槽名 来分发对应标签(父组件中)
<MyDialog>
  <!-- v-slot 只能用在template上(官网有一种特殊情况) -->
  <template v-slot:head>
    大标题
  </template>
  <template v-slot:content>
    内容文本
  </template>
  <template v-slot:footer>
    <button>按钮</button>
  </template>
</MyDialog>

v-slot:插槽名可以简化成 #插槽名,此外插槽默认名为 default

作用域插槽

定义slot插槽的同时是可以传值的。插槽上可以绑定数据,将来使用组件时可以使用

作用域插槽:将数据从子组件通过插槽传递给父组件

  • 在子组件的slot上绑定数据
  • 在父组件中使用template配合v-slot取值

为了让 user 在父级的插槽内容中可用,我们可以将 user 作为 <slot> 元素的一个属性绑定上去:

<span>
  <!-- :user 相当于往插槽上加了一个属性, 最终以对象包裹属性的形式传递过去{ user: user} -->
  <slot v-bind:user="user">
    {{ user.lastName }}
  </slot>
</span>

绑定在 <slot> 元素上的属性被称为插槽 prop。现在在父级作用域中,我们可以使用带值的 v-slot 来定义我们提供的插槽 prop 的名字:

<current-user>
  <!-- <template #default="slotProps"> -->
  <!-- 如果不用 # 也可以不指定名字, 直接写为 v-slot="变量名",不过使用多个插槽时不能这么做 -->
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>
</current-user>

在这个例子中,我们选择将包含所有插槽 prop 的对象命名为 slotProps,也可以使用任意命名。此外,插槽也是可以解构的

21.vue2响应式的原理

vue响应式也叫作数据双向绑定,大致原理阐述:

vue响应式的原理是通过数据劫持+发布者-订阅者模式的方式来实现的,首先是通过ES5提供的

Object.defineProperty()方法来劫持(监听)各属性的getter、setter,并在当监听的属性发生变动时通知订阅者,是

否需要更新,若更新就会执行对应的更新函数。

数据代理:

Object.defineProperty(对象,属性名,配置项)

<script type="text/javascript">
let number=18
let person={
    name:'张三',
    sex:'男',
}

Object.defineProperty(person,'age',{
    //value:18,
    //enumerable:true,//控制属性是否可以枚举,默认值是false
    //writable:true,//控制属性是否被修改,默认值是false
    //configurable:true,//控制属性是否被删除,默认值是false
    
    //当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
    get(){
        console.log('有人读取了age属性了')
        return number
    },
    
    //当有人修改person的age的属性时,set函数(setter)就会被调用,且会收到修改的具体值
    set(value){
        console.log('有人修改了age属性,且值是',value)
        number=value
    }
})
</script>

扩展:vue3响应式的原理是通过proxy代理来实现的

什么是数据劫持

数据劫持比较好理解,通常我们利用Object.defineProperty劫持对象的访问器,在属性值发生变化时我们可以获

取变化,从而进行进一步操作

22.vue2和vue3的区别

①响应式原理不同

vue2是利用ES5的object.definePropert()对数据进行监听和结合发布订阅模式的方式来实现的

vue3中使用了ES6的proxy对数据代理

②组合API

vue2采用选项式API对比vue3组合式API

vue3中没有this,没有beforecreate和created,它们的功能放在了setup中

③根节点

vue2只能有一个根节点,vue3可以有多个根节点

vue2若想新增或者修改一个需求,就需要分别修改:data、methods、computed,不便于维护和复用

vue3的优点

1.首次渲染更快

2.diff算法更快

3.内存占用更少

4.打包体积更小

5.更好的支持TypeScript

6.Composition API

vue3不同点:

1.组件一个根节点非必需

2.创建应用挂载到根容器

3.入口页面,ESM(模块化)加载资源

23.vue3的注意事项

1.setup函数中不能使用this。vue为了避免我们错误的使用,直接将setup函数中的this修改成了undefined

2.setup函数中的props是响应式的,当传入新的prop时,他将被更新。但是,因为props是响应式的,你不能使

用ES6解构,因为它会消除prop的响应式,如果需要解构prop,可以使用setup函数中的toRefs来完成此操作。

24.组件通信方式eventBus原理

EventBus 是一种用于在不同的组件或模块之间传递事件的方法。它通常通过一个中央事件总线来实现,该事件总线可以连接不同的组件或模块,使得它们可以进行松耦合通信。

以下是使用 EventBus 的一个简单示例:

首先,你需要安装 EventBus 库,如果你使用的是 Node.js,可以通过 npm 安装:

npm install eventbus

然后,你可以创建一个 EventBus 实例并使用它来发送和监听事件:

// 引入 EventBus
const EventBus = require('eventbus');
 
// 创建 EventBus 实例
const bus = new EventBus();
 
// 组件 A 监听事件
bus.on('eventName', (data) => {
  console.log('Event received in Component A with data:', data);
});
 
// 组件 B 触发事件
bus.emit('eventName', { message: 'Hello from Component B!' });

在这个例子中,组件 A 通过 bus.on 监听名为 'eventName' 的事件,而组件 B 通过 bus.emit 触发同样名为 'eventName' 的事件,并附带数据。当事件被触发时,监听该事件的所有组件都会接收到数据并执行相应的回调函数。

这就是 EventBus 的基本使用方法。实际应用中,你可能需要根据具体情况扩展和定制 EventBus,例如添加事件命名空间、支持异步事件监听器等。

25.vue-router路由钩子有哪些

全局钩子beforeEach、afterEach

单个路由里面的钩子:beforeEnter、beforeLeave

组件路由:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave