Skip to content

第一章 Vue2入门基础 v1.0

第一部分 Vue入门

一、Vue2基本语法

1.基本使用示例

html
<!--1.引入Vue依赖(此为Vue2)-->
<script src="../module/vue.js"></script>
<!--2.准备容器-->
<div id="box">
  {{ msg }}
</div>
<!--3.创建Vue对象并挂载-->
<script>
  const app=new Vue({
    el:"#box",  //挂载点
    data:{  //数据,在外部可以通过对象获取或修改(此处对象为app),如app.msg
      msg:"msg"
    },
    methods:{}  //内联函数
  });
</script>

2.插值表达式

Vue的一种模板语法,利用表达式进行插值,渲染到页面中

语法:{{ 表达式 }}

注意要点: ①数据需要预定义 ②支持表达式而非语句 ③不能再标签属性中使用

3.Vue指令

HTML标签上带有v-前缀的特殊属性,不同指令有不同作用

  1. v-bind(v-bind:可缩写为:):为HTML标签绑定属性值
  2. v-html:控制元素内的html渲染
  3. v-model:在表单元素上创建双向数据绑定
  4. v-on(v-on:可缩写为@):为HTML元素绑定事件
  5. v-show:通过控制display属性控制元素的隐藏
  6. v-if/v-else-if/v-else:通过条件判断控制元素的渲染与删除
  7. v-for:列表渲染,遍历容器的元素或对象的属性
①v-for

标准语法:v-for="(item,index) in iterator" :key="item.id"
key的作用:为元素添加唯一标识,便于Vue进行列表的正确排序复用,必须具有唯一性

②v-bind

对于样式控制的增强

  1. 操作class对象:<div :class="{ 类名1:布尔值, 类名2:布尔值 }">
  2. 操作class数组:<div :class="[ 类名1, 类名2, 类名3 ]">
  3. 操作style:<div :style="{ 属性名1:属性值, 属性名2:属性值 }">
③v-model

v-model原理:本质上是一个语法糖,应用在输入框上就是:value@input的合写,作用是提供双向数据绑定

html
<input v-model="msg" type="text"> <!-- 等价于下方写法 -->
<input :value="msg" @input="msg = $event.target.value" type="text">

:value:修改视图,数据随视图变化而变化
@input="msg = $event.target.value":数据变化视图自动更新

当v-model绑定不同表单元素时绑定不同的数值:

  1. input/textarea:输入内容(字符串)
  2. checkbox:是否选中(布尔值)
  3. radio:选中的value值(字符串)
  4. select:选中的value值(字符串)

二、指令修饰符

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

1.常用事件指令修饰符

  • @keyup.enter:监听键盘回车按键,之后执行指定操作
  • @事件名.stop:阻止冒泡
  • @事件名.prevent:阻止默认行为

2.v-model指令修饰符

  • v-model.trim:去除绑定数据的前后空格
  • v-model.number:将绑定内容转换为数字

三、计算属性(computed)

1.基本概念

定义:基于现有的数据计算所得到的新属性,依赖的数据变化,自动重新计算
使用:声明在computed配置项中,一个属性对应一个函数,使用可以和普通属性一样使用

2.语法

javascript
compyted:{
  property() {  //调用只需使用 {{ property }} 即可
    //数据操作逻辑
    return data;
  }
}
javascript
compyted:{
  property: {  //调用只需使用 {{ property }} 即可
    get() {
      //数据操作逻辑
      return data;
    },
    set(value) {  //修改赋值时操作
      //数据修改逻辑
    }  
  }
}

四、watch监听器

监视数据变化,执行一些业务逻辑或异步操作

1.语法

javascript
const app=new Vue({
  el:'#app',
  data: {
    words: ''
  },
  watch: {
    words(newValue, oldValue){
      console.log("变化了", newValue, oldValue);
    }
  } 
})
javascript
const app=new Vue({
  el:'#app',
  data: {
    obj: {
      words: ''
    }
  },
  watch: {
    'obj.words'(newValue, oldValue){
      console.log("变化了", newValue, oldValue);
    }
  } 
})
javascript
// 可以添加额外配置项
const app=new Vue({
  el:'#app',
  data: {
    obj:{
      words: '',
      anotherWords: ''
    }
  },
  watch: {
    obj: {
      deep: true,       // 复杂类型深度监视,监视复杂对象中的所有属性变化
      immediate: true,  // 初始化页面立即执行一次
      handler (newValue, oldValue){
        console.log("变化了", newValue, oldValue);
      }
    }
  } 
})

2.示例

javascript
const app=new Vue({
  el:'#app',
  data: {
    obj: {
      words: ''
    }
  },
  watch: {
    async 'obj.words'(newValue){
      const res = await axios({
        url:"http://...",
        params:{
          words: newValue
        }
      })
      console.log(res.data.data)
    }
  } 
})
javascript
const app=new Vue({
  el:'#app',
  data: {
    obj: {
      words: ''
    },
    result: ''
  },
  watch: {
    'obj.words'(newValue){
      clearTimeout(this.timer)
      this.timer = setTimeout(async () => {
        const res = await axios({
          url:"http://...",
          params:{
            words: newValue
          }
        })
        this.result = res.data.data
        console.log(res.data.data)
      },300)
    }
  }
})

五、生命周期

1.生命周期

一个Vue实例从创建到销毁的整个过程,共有四个阶段,分别是: ①创建 ②挂载 ③更新 ④销毁

2.生命周期函数(钩子函数)

①简介

Vue生命周期过程中,会自动运行一些函数,被称为生命周期钩子,让开发者可以在特定阶段运行自己的代码。

②使用示例
javascript
const app = new Vue({
  el: "#app",
  data: {
    list: []
  },
  async created (){
    const res = await axios.get("...")
    this.list = res.data.data
  }
})
javascript
const app = new Vue({
  el: "#app",
  mounted() {
    document.querySelector('#inp').focus()  // 选择元素并聚焦
  }
})

第二部分 工程化开发

一、脚手架

1.使用VueCli创建Vue工程

Vue官方提供的一个全局命令工具,可以帮助我们快速创建一个开发Vue项目的标准化基础架子(集成了webpack配置)

npm和yarn都是管理第三方包的,使用VueCli的步骤如下:

bash
npm i @vue/cli -g          # 安装脚手架
vue --version              # 查看Vue版本
vue create <project-name>  # 创建项目
npm run serve              # 启动项目
bash
yarn global add @vue/cli   # 安装脚手架
vue --version              # 查看Vue版本
vue create <project-name>  # 创建项目
yarn serve                 # 启动项目

2.其他创建方法

create-vue是官方新的脚手架工具,底层切换到了vite,默认版本为Vue3,相较于webpack,响应更快

bash
npm create vue@latest
>> 输入模块名
>> 配置选项
cd <模块>
npm i  #安装相关依赖
npm run dev  #运行
bash
npm create vite@latest
>> 输入模块名
>> 配置选项
cd <模块>
npm i  #安装相关依赖
npm run dev  #运行

3.目录结构

text
vue-project
   ├- node_modules      [第三方包文件夹]
   ├- src               [源代码目录]
     ├- assets            [静态资源目录] 存放文件、字体等
     ├- router            [路由目录] 存放路由管理的js文件
     ├- views             [页面组件] 页面展示相关组件,配合路由使用
     ├- components        [复用组件] 展示数据相关组件,常用于复用
     ├- App.vue           App根组件
     └- main.js           入口文件,打包运行时第一个执行的文件
   ├- public            [静态资源目录]
   ├- jsconfig.json     js配置文件
   ├- package.json      项目配置文件,包含项目名、版本号、依赖包等
   └- vue.config.js     vue配置文件(vite则为vite.config.js)

二、路径别名

在Vue中(webpack配置),引入文件时可以通过@路径代表根路径(以src为根)
例:import MyCom from '@/views/MyCom'

在Vue中,我们可以通过对应config.js中修改选项,自己定义相关路径别名

javascript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      "@": path.resolve("src")   // 相对路径别名配置,使用 @ 代替 src
    }
  }
})

三、代码结构

1.main.js

核心作用:导入App.vue, 基于App.vue创建结构渲染index.html

javascript
// 1.导入Vue 核心包
import Vue from 'vue'
// 2.导入App.vue 根组件
import App from './App.vue'
//提示:当前处于什么环境(生产环境/开发环境)
Vue.config.productionTip = false
// 3. Vue实例化,提供render方法 -> 基于App.vue创建结构渲染index.html
new Vue({
  render: h => h(App),
}).$mount('#app')
javascript
// 1.导入Vue 核心包
import Vue from 'vue'
// 2.导入App.vue 根组件
import App from './App.vue'
//提示:当前处于什么环境(生产环境/开发环境)
Vue.config.productionTip = false
// 3. Vue实例化,提供render方法 -> 基于App.vue创建结构渲染index.html
new Vue({  //指定Vue管理的容器
  el:'#app',
  render: (createElement) => {  //完整写法
    return createElement(App)
  },  
})

2.App.vue

App组件,在其核心代码结构同时也是组件结构,详见组件化

vue
<template>
  <!-- 模板结构 -->
</template>
<script>
  //js逻辑结构
</script>
<style lang='less'>
  /* 样式结构 */
</style>
vue
<template>
  <!-- 模板结构,有且只能有一个根元素(Vue2,Vue3无限制) -->
</template>
vue
<script>
  export default {
    //导出的是当前组件的配置项
    //可以提供 data methods computed watch 生命周期钩子函数
    data:{
      //...
    }
  }
</script>
vue
<style lang='less' scoped>
  /* 样式,默认不支持less,需要装包,npm install less less-loader */
  /*
  style中样式默认为全局样式,容易造成多个组件的样式冲突问题;添加scoped为局部样式,只作用于当前组件
    scoped原理:
    1.给组件所有元素添加一个自定义属性data-v-hash值
    2.在css选择器后自动处理,在后面添加了属性选择器,如:div[data-v-hash]
  */
</style>

第三部分 组件化

组件化开发是Vue构建大型、可维护前端应用的关键实践。组件化允许开发者将界面划分为独立的、可复用的组件,每个组件都有自己的逻辑和样式。

一、定义组件

使用一个.vue文件来定义组件,和前面App.vue一样,包含三个部分

1.单文件组件

vue
<template>
  <!-- 模板结构 -->
</template>
<script>
  //js逻辑结构
</script>
<style lang='less'>
  /* 样式结构 */
</style>
vue
<template>
  <div class="my-component">
    <h1>{{ message }}</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Component!'
    };
  }
};
</script>

<style scoped>
.my-component h1 {
  color: blue;
}
</style>

2.data

一个组件的data选项是一个函数,用于维护每个组件实例一份独立的数据对象

vue
<script>
  export default {
    data () {
      return {
        count: 1000
      }
    }
  }
</script>

3.props

组件上注册的一些自定义属性,可以传递任意数量,任意类型的变量

vue
<script>
  export default {
    props: ['element1', 'element2', ...]
  }
</script>

props校验: 为组件的prop指定校验要求,不符合要求,控制台就会有错误提示,可以帮助开发者快速发现错误

vue
<script>
  export default {
    props: {
      element1: Number,
      element2: String,
      func1: Function
    }
  }
</script>
vue
<!--复杂校验:可以进行类型、非空、默认值设置、自定义校验规则校验-->
<script>
  export default {
    props: {
      属性名: {
        type: 属性,  //属性校验
        required: true,  //是否必填
        default: 默认值,  //设置默认值
        validator (value) {  //自定义校验逻辑
          if(condition) {  //通过验证条件
            return true
          } else {
            console.error("错误描述")
            return flase
          }
        }
      }
    }
  }
</script>

二、组件注册

在 Vue 2 中,你可以通过 Vue.component() 方法全局注册组件,或者在特定 Vue 实例中通过 components 选项局部注册。

1.局部注册(只能在注册的组件内使用)

使用步骤: ①创建.vue文件 ②在使用的组件内导入并注册
使用方法: 直接当成html标签使用:<标签名></标签名>(使用大驼峰命名)

vue
<template>
  <组件名></组件名>    <!-- 使用组件 -->
</template>
<script>
  import <组件名> from 'Xxx.vue'
  export default {
    components: {
      <组件名>  // 完整写法为 <组件名>: <组件对象>
    }
  }
</script>

2.全局注册(所有组件内都能使用)

使用步骤: ①创建.vue文件 ②在main.js中进行全局注册

javascript
import <组件名> from 'Xxx.vue'
// 规范:导入的代码在main.js的顶部编写
Vue.component(组件名,组件对象)

三、组件通信

1.常见组件通信解决方案

  • 父子组件: props和$emit
  • 非父子组件: provide&inject、enentbus
  • 通用解决方案: Vuex

2.父子组件通信

父传子
vue
<template>
  <Son :title="myTitle"></Son>  <!-- 指定传值给Son的title属性 -->
</template>
<script>
  import Son from 'Son.vue'
  export default {
    data () {
      return {
        myTitle: "my_title"
      }
    },
    components: {
      Son
    },
  }
</script>
vue
<template>
  {{ title }}
</template>
<script>
  export default {
    props: ['title']  //可以接受父组件传递的值
  }
</script>
子传父
vue
<template>
  <div>{{ title }}</div>
  <button @click="changeT">修改Title</button>
</template>
<script>
  export default {
    props: ['title'],
    methods: {
      changeT() {  //通过$emit向父组件发送消息通知
        this.$emit("changeTitle", "修改后的标题")
      }
    }
  }
</script>
vue
<template>
  <Son :title="myTitle" @changeTitle="handleChange"></Son>  <!-- 指定接收消息后的处理函数 -->
</template>
<script>
  import Son from 'Son.vue'
  export default {
    methods: {
      handleChange (newTitle) {  //处理函数
        this.myTitle = newTitle
      }
    },
    data () {
      return {
        myTitle: "my_title"
      }
    },
    components: {
      Son  
    },
  }
</script>

3.非父子组件通信

跨层级共享数据(provide&inject)

vue
<script>
  export default {
    provide () {
      return {
        属性1: this.属性1,
        属性2: this.属性2,
      }
    },
    data () {
      return {
        属性1: "1",  //简单类型(非响应式)
        属性2: {  //复杂类型(响应式,推荐使用)
          属性3: '3',
          属性4: '4'
        },
    }
  }
</script>
vue
<script>
  export default {  //被包含在内的组件直接通过inject获取属性
    inject: ['属性1','属性2']
  }
</script>
事件总线(enent bus)

javascript
import Vue from 'vue'
//创建一个都能访问到的事件总线(空的Vue实例)
const Bus = new Vue()
export default Bus
vue
<script>
  import Bus from 'utils/EventBus'
  export default {
    created () {  //在接收方监听Bus的事件(订阅消息)
      Bus.$on('sendMsg', (msg) => {
        //接收消息后的主要代码逻辑
      })
    }
  }
</script>
vue
<template>
  <button @click="clickSend">发布通知</button>
</template>
<script>
  import Bus from 'utils/EventBus'
  export default {
    methods: {
      clickSend () {
        //触发并发送消息
        Bus.$emit("sendMsg","msg")
      }
    }
  }
</script>

4.表单类组件封装

vue
<template>
  <!-- 3.监听数据变化,使用$event直接接收传值结果 -->
  <Son :selectId="selectId" @changeTitle="selectId = $event"></Son>   
</template>
<script>
  import Son from 'Son.vue'
  export default {
    data () {
      return {
        selectId: "100"
      }
    },
    components: {
      Son  
    },
  }
</script>
vue
<template>
  请输入selectId:<input :value="selectId" @change="handleChange"></input>
</template>
<script>
  export default {
    props: {
      selectId: String  //1.不能使用v-model,使用 :value 绑定渲染数据
    },
    methods: {
      handleChange (e) {
        this.$emit("changeId", e.target.value)  //2.传递修改的数据
      }
    }
  }
</script>
表单类组件封装(使用v-model优化)
vue
<template>
  <!-- 修改为v-model 原理:v-model => :value + @input -->
  <Son v-model="selectId"></Son>   
</template>
<script>
  import Son from 'Son.vue'
  export default {
    data () {
      return {
        selectId: "100"
      }
    },
    components: {
      Son  
    },
  }
</script>
vue
<template>
  <!-- 2.修改为value绑定数据 -->
  请输入selectId:<input :value="value" @change="handleChange"></input>
</template>
<script>
  export default {
    props: {
      value: String  //1.修改属性为value接收
    },
    methods: {
      handleChange (e) {
        this.$emit("input", e.target.value)  //3.事件名修改为input
      }
    }
  }
</script>

5.弹窗类组件封装

.sync修饰符可以实现子组件与父组件数据的双向绑定,简化代码,props属性名可以自定义

本质::visible.sync="isShow"等价于:visible="isShow"@update:visible="isShow = $event"

vue
<template>
  <BaseDialog :visible.sync="isShow" />
</template>
vue
<template>
    <BaseDialog :visible="isShow"
        @update:visible="isShow = $event" />
</template>
vue
<script>
  export default {
    props: {
      visible: Boolean
    },
    methods:{
        close() {
          // 当触发close时,修改对应visible属性值
          this.$emit('update:visible', false)
        }
    }
  }
</script>

四、操作dom元素

1.querySelector

作用: 查找整个页面中制定选择器的页面元素

语法:document.querySelector('选择器')

2.ref 和 $refs

作用: 通过ref属性可以查找指定元素(但需要页面渲染完后才能获取),查找范围是当前组件内,更加精确稳定。且利用 ref 和 $refs 不仅可以用来操作dom元素,还可以操作组件实例调用组件对象中的方法

vue
<template>
  <div ref="myRef"><!-- 1.添加ref属性 -->
    ...
  </div>
</template>
<script>
  export default {
    mounted() {  // 在实例挂载后修改内容,修改div中内容为 "123"
      this.$refs.myRef.innerText = '123';   // 2.页面渲染完通过 this.$refs.myRef 获取元素
    }
  };
</script>
vue
<template>
  <BaseModule ref="myRef" /><!-- 1.添加ref属性 -->
</template>
<script>
  export default {
    mounted() {  // 在实例挂载后立刻调用组件方法
      this.$refs.myRef.func();   // 2.页面渲染完通过 this.$refs.myRef 获取元素
    }
  };
</script>

3.Vue异步dom更新

Vue是异步更新dom的,要等dom更新后再操作,可以使用$nextTick

$nextTink作用:等dom更新完之后,立即执行函数体中的操作

vue
<script>
  export default {
    methods: {
      handleUpdateDom (){
        // 1.显示dom元素(执行dom更新)
        this.showDom = true
        // 2.获取焦点
        this.$nextTink(() => {
          this.$refs.inp.focus()  //执行下一步更新
        })
      }
    }
  }
</script>
vue
<script>
  export default {
    methods: {
      handleUpdateDom (){
        // 1.显示dom元素(执行dom更新)
        this.showDom = true
        // 2.延时执行,获取焦点
        setTimeout(() => {
          this.$refs.inp.focus()  //执行下一步更新
        }, 300)
      }
    }
  }
</script>