Vue.js 基础知识大全

一、Vue 核心概念

1. Vue 是什么

复制代码
// Vue 是一个渐进式 JavaScript 框架
// 特点:易用、灵活、高效
new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
});

2. MVVM 模式

复制代码
Model(数据) ↔ ViewModel(Vue实例) ↔ View(DOM)
双向数据绑定

二、Vue 实例

1. 创建 Vue 实例

复制代码
const vm = new Vue({
  // 选项对象
  el: '#app',           // 挂载元素
  data: {               // 数据
    message: 'Hello'
  },
  methods: {            // 方法
    greet() {
      alert(this.message);
    }
  },
  computed: {           // 计算属性
    reversedMessage() {
      return this.message.split('').reverse().join('');
    }
  },
  watch: {              // 侦听器
    message(newVal, oldVal) {
      console.log('消息变化了', oldVal, '→', newVal);
    }
  }
});

2. 生命周期钩子

复制代码
export default {
  // 初始化阶段
  beforeCreate() {
    // 实例初始化之后,数据观测之前
  },
  created() {
    // 实例创建完成,可以访问 data、methods
    // 适合发起异步请求
  },
  
  // 挂载阶段
  beforeMount() {
    // 模板编译/挂载之前
  },
  mounted() {
    // 挂载完成,可以访问 DOM
    // 适合操作 DOM、初始化插件
  },
  
  // 更新阶段
  beforeUpdate() {
    // 数据更新,DOM 重新渲染之前
  },
  updated() {
    // DOM 更新完成
  },
  
  // 销毁阶段
  beforeDestroy() {
    // 实例销毁之前
    // 适合清理定时器、解绑事件
  },
  destroyed() {
    // 实例销毁后
  },
  
  // keep-alive 相关(仅 keep-alive 组件)
  activated() {
    // 组件激活时
  },
  deactivated() {
    // 组件停用时
  }
}

三、模板语法

1. 插值

复制代码
<template>
  <!-- 文本插值 -->
  <p>{{ message }}</p>
  
  <!-- 原始 HTML -->
  <p v-html="rawHtml"></p>
  
  <!-- 属性绑定 -->
  <div :id="dynamicId"></div>
  <button :disabled="isDisabled">按钮</button>
  
  <!-- JavaScript 表达式 -->
  <p>{{ number + 1 }}</p>
  <p>{{ ok ? 'YES' : 'NO' }}</p>
  <p>{{ message.split('').reverse().join('') }}</p>
</template>

2. 指令

复制代码
<template>
  <!-- 条件渲染 -->
  <p v-if="type === 'A'">A</p>
  <p v-else-if="type === 'B'">B</p>
  <p v-else>C</p>
  
  <!-- v-show 通过 CSS display 控制 -->
  <p v-show="isShow">显示/隐藏</p>
  
  <!-- 列表渲染 -->
  <ul>
    <li v-for="(item, index) in items" :key="item.id">
      {{ index }} - {{ item.name }}
    </li>
  </ul>
  
  <!-- 遍历对象 -->
  <div v-for="(value, key) in object">
    {{ key }}: {{ value }}
  </div>
  
  <!-- 事件处理 -->
  <button @click="handleClick">点击</button>
  <button @click="handleClick($event, 'param')">带参数</button>
  
  <!-- 事件修饰符 -->
  <form @submit.prevent="onSubmit"></form>
  <a @click.stop="doThis"></a>
  <input @keyup.enter="submit">
  
  <!-- 双向绑定 -->
  <input v-model="message" type="text">
  <textarea v-model="message"></textarea>
  <input v-model="checked" type="checkbox">
  <input v-model="picked" type="radio" value="A">
  <select v-model="selected">
    <option>A</option>
    <option>B</option>
  </select>
</template>

四、计算属性和侦听器

1. 计算属性 (computed)

复制代码
export default {
  data() {
    return {
      firstName: '张',
      lastName: '三',
      books: [
        { title: 'Vue指南', price: 50 },
        { title: 'React指南', price: 60 }
      ]
    };
  },
  computed: {
    // 基本用法
    fullName() {
      return this.firstName + this.lastName;
    },
    
    // 带 setter 的计算属性
    fullName2: {
      get() {
        return this.firstName + ' ' + this.lastName;
      },
      set(newValue) {
        const names = newValue.split(' ');
        this.firstName = names[0];
        this.lastName = names[1];
      }
    },
    
    // 依赖数组的计算属性
    totalPrice() {
      return this.books.reduce((sum, book) => sum + book.price, 0);
    }
  }
};

2. 侦听器 (watch)

复制代码
export default {
  data() {
    return {
      question: '',
      answer: '',
      user: {
        name: '张三',
        info: {
          age: 20
        }
      }
    };
  },
  watch: {
    // 基本用法
    question(newVal, oldVal) {
      this.getAnswer();
    },
    
    // 深度监听对象
    user: {
      handler(newVal, oldVal) {
        console.log('user 变化了');
      },
      deep: true,      // 深度监听
      immediate: true  // 立即执行
    },
    
    // 监听对象某个属性
    'user.info.age': function(newVal, oldVal) {
      console.log('age 变化了');
    }
  },
  methods: {
    getAnswer() {
      // 异步操作
      setTimeout(() => {
        this.answer = '答案是...';
      }, 1000);
    }
  }
};

五、Class 与 Style 绑定

复制代码
<template>
  <!-- Class 绑定 -->
  <div :class="{ active: isActive, 'text-danger': hasError }"></div>
  <div :class="[activeClass, errorClass]"></div>
  <div :class="[isActive ? activeClass : '', errorClass]"></div>
  
  <!-- Style 绑定 -->
  <div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
  <div :style="[baseStyles, overridingStyles]"></div>
  
  <!-- 自动添加前缀,支持数组/对象 -->
  <div :style="{ transform: 'scale(' + scale + ')' }"></div>
</template>

<script>
export default {
  data() {
    return {
      isActive: true,
      hasError: false,
      activeClass: 'active',
      errorClass: 'text-danger',
      activeColor: 'red',
      fontSize: 14,
      baseStyles: { color: 'red' },
      overridingStyles: { fontSize: '20px' },
      scale: 1.2
    };
  }
};
</script>

六、组件基础

1. 组件注册

复制代码
// 全局注册
Vue.component('my-component', {
  template: '<div>我的组件</div>'
});

// 局部注册
const ComponentA = {
  template: '<div>组件A</div>'
};

export default {
  components: {
    'component-a': ComponentA
  }
};

2. Props 传递数据

复制代码
<!-- 父组件 -->
<template>
  <child-component :title="parentTitle" @custom-event="handleEvent" />
</template>

<script>
export default {
  data() {
    return {
      parentTitle: '来自父组件的标题'
    };
  },
  methods: {
    handleEvent(data) {
      console.log('收到子组件事件:', data);
    }
  }
};
</script>

<!-- 子组件 ChildComponent.vue -->
<template>
  <div>
    <h3>{{ title }}</h3>
    <button @click="$emit('custom-event', '数据')">触发事件</button>
  </div>
</template>

<script>
export default {
  props: {
    // 基础类型检查
    title: String,
    
    // 多个可能的类型
    propA: [String, Number],
    
    // 必填项
    propB: {
      type: String,
      required: true
    },
    
    // 默认值
    propC: {
      type: Number,
      default: 100
    },
    
    // 自定义验证函数
    propD: {
      validator(value) {
        return ['success', 'warning', 'danger'].includes(value);
      }
    }
  },
  methods: {
    emitEvent() {
      this.$emit('custom-event', '自定义数据');
    }
  }
};
</script>

3. 插槽 Slot

复制代码
<!-- 子组件 -->
<template>
  <div class="container">
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot>默认内容</slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

<!-- 父组件使用 -->
<template>
  <child-component>
    <template v-slot:header>
      <h1>标题</h1>
    </template>
    
    <p>主要内容</p>
    
    <template #footer>
      <p>底部信息</p>
    </template>
  </child-component>
</template>

4. 作用域插槽

复制代码
<!-- 子组件 -->
<template>
  <ul>
    <li v-for="item in items">
      <slot :item="item">
        {{ item.name }}
      </slot>
    </li>
  </ul>
</template>

<!-- 父组件使用 -->
<template>
  <my-list :items="userList">
    <template v-slot:default="slotProps">
      <span class="red">{{ slotProps.item.name }}</span>
    </template>
  </my-list>
</template>

七、组件通信

1. 父子组件通信

复制代码
// 父 → 子:props
// 子 → 父:$emit

// 父组件访问子组件
this.$refs.childName.methodName();

// 子组件访问父组件
this.$parent.methodName();

// 访问根实例
this.$root.methodName();

2. 事件总线(非父子组件)

复制代码
// eventBus.js
import Vue from 'vue';
export const EventBus = new Vue();

// 组件A发送事件
EventBus.$emit('event-name', data);

// 组件B接收事件
EventBus.$on('event-name', (data) => {
  console.log(data);
});

// 取消监听
EventBus.$off('event-name');

3. Provide / Inject(跨级组件)

复制代码
// 祖先组件
export default {
  provide() {
    return {
      theme: this.theme,
      changeTheme: this.changeTheme
    };
  },
  data() {
    return {
      theme: 'dark'
    };
  },
  methods: {
    changeTheme(theme) {
      this.theme = theme;
    }
  }
};

// 后代组件
export default {
  inject: ['theme', 'changeTheme'],
  mounted() {
    console.log(this.theme);
    this.changeTheme('light');
  }
};

八、表单输入绑定修饰符

复制代码
<template>
  <!-- .lazy - 转为 change 事件后同步 -->
  <input v-model.lazy="msg">
  
  <!-- .number - 自动转为数字 -->
  <input v-model.number="age" type="number">
  
  <!-- .trim - 自动过滤首尾空白 -->
  <input v-model.trim="msg">
  
  <!-- 组合使用 -->
  <input v-model.lazy.trim="msg">
</template>

九、Vue 实例属性/方法

复制代码
// 常用实例属性
this.$data        // 数据对象
this.$props       // props 对象
this.$el          // 根 DOM 元素
this.$options     // 实例选项
this.$parent      // 父实例
this.$root        // 根实例
this.$children    // 子实例数组
this.$slots       // 插槽内容
this.$scopedSlots // 作用域插槽
this.$refs        // 持有注册过 ref 的所有 DOM/组件
this.$attrs       // 父作用域中不作为 prop 被识别的 attribute
this.$listeners   // 父作用域中的事件监听器

// 常用实例方法
this.$watch()     // 创建侦听器
this.$set()       // 响应式添加属性
this.$delete()    // 响应式删除属性
this.$on()        // 监听自定义事件
this.$once()      // 监听一次性事件
this.$off()       // 取消事件监听
this.$emit()      // 触发事件
this.$nextTick()  // DOM 更新后执行回调
this.$forceUpdate() // 强制重新渲染

十、最佳实践

1. 组件设计原则

  • • 单一职责
  • • 可复用性
  • • 可维护性
  • • 良好的命名规范

2. 性能优化

复制代码
// 1. 合理使用 v-if 和 v-show
// 频繁切换用 v-show,不常变化用 v-if

// 2. 列表使用 key
<li v-for="item in list" :key="item.id">

// 3. 避免同时使用 v-for 和 v-if
// 错误写法
<div v-for="item in list" v-if="item.active">

// 正确写法
<div v-for="item in activeList">

// 4. 合理使用计算属性和侦听器
// 计算属性缓存结果,避免重复计算

// 5. 组件懒加载
const LazyComponent = () => import('./LazyComponent.vue');

3. 代码规范

复制代码
// 组件文件名:PascalCase(如 MyComponent.vue)
// 组件名:PascalCase(如 MyComponent)
// Prop 定义:提供类型和默认值
// 事件名:kebab-case(如 custom-event)

十一、常见问题

1. 数组/对象更新检测

复制代码
// Vue 不能检测到以下数组变动
// 解决方案:
this.$set(this.items, index, newValue);
this.items.splice(index, 1, newValue);

// 添加新属性到对象
this.$set(this.obj, 'newProp', 123);

2. nextTick 的使用

复制代码
// DOM 更新后执行
this.message = '更新';
this.$nextTick(() => {
  // DOM 现在更新了
  console.log(this.$el.textContent);
});

3. 组件命名冲突

复制代码
<!-- 使用 kebab-case -->
<my-component-name></my-component-name>

<!-- 或 PascalCase -->
<MyComponentName></MyComponentName>

这个基础知识涵盖了 Vue 2.x 的核心内容,掌握了这些就能进行基本的 Vue 开发了。

相关推荐
console.log('npc')4 小时前
vue2 使用高德接口查询天气
前端·vue.js
天天向上10244 小时前
vue3 实现el-table 部分行不让勾选
前端·javascript·vue.js
Mr Xu_5 小时前
前端实战:基于Element Plus的CustomTable表格组件封装与应用
前端·javascript·vue.js·elementui
diygwcom8 小时前
自已学习Cursor Skills Vue实现第一个例子
前端·vue.js·学习
前端小超人rui8 小时前
【react - swc】
前端·react.js·前端框架
小马_xiaoen9 小时前
Vue3 + TS 实现一键复制指令 v-copy(优雅解决文本复制需求)
前端·javascript·vue.js
王同学 学出来9 小时前
vue复习
前端·javascript·vue.js
Irene19919 小时前
Vue 3 中使用 Vue Router 实现 SPA(单页应用)
vue.js·spa·router
chenhdowue11 小时前
vue表单vxe-form如何对一个规则同时多字段联动校验,对一个控件校验多个关联字段
vue.js·vxe-table·vxe-ui
大猩猩X11 小时前
vxe-table 表格 vue 单元格渲染上传附件,显示图片列表,适配上传附件样式的用法
vue.js·vxe-table