Vue.js 简介和特性

1. Vue.js 简介

Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架。它易于上手,同时也提供了强大的功能,适用于从小型项目到大型单页应用(SPA)的开发。Vue.js 的核心库专注于视图层,可以轻松地与其他库或现有项目集成。

1.1 Vue.js 的核心特性

  • 响应式数据绑定:Vue.js 使用双向数据绑定,当数据发生变化时,视图会自动更新。
  • 组件化开发:Vue.js 支持组件化开发,可以将复杂的 UI 拆分为多个独立的组件。
  • 模板语法:Vue.js 使用基于 HTML 的模板语法,使得开发者可以轻松地将 DOM 与 Vue 实例的数据绑定。
  • 虚拟 DOM:Vue.js 使用虚拟 DOM 来优化 DOM 操作,提高应用性能。
  • 丰富的生态系统:Vue.js 拥有丰富的插件和工具,如 Vue Router、Vuex 等,帮助开发者构建复杂的应用。

2. 开发环境搭建

在开始使用 Vue.js 之前,我们需要搭建一个开发环境。Vue.js 提供了两种常用的工具来快速搭建项目:Vue CLI 和 Vite。

2.1 Vue CLI

Vue CLI 是一个官方提供的脚手架工具,可以帮助我们快速创建和管理 Vue.js 项目。

安装 Vue CLI

npm install -g @vue/cli

创建新项目

vue create my-first-vue-app

2.2 Vite

Vite 是一个由 Vue.js 作者尤雨溪开发的构建工具,旨在提供更快的开发体验。Vite 使用原生 ES 模块导入,无需打包即可实现快速的热更新。

安装 Vite

npm init vite@latest

创建新项目

npm init vite@latest my-first-vite-app --template vue

3. 创建第一个 Vue 应用

3.1 使用 Vue CLI 创建应用

  1. 创建项目:

    vue create my-first-vue-app
    
  2. 进入项目目录:

    cd my-first-vue-app
    
  3. 启动开发服务器:

    npm run serve
    

3.2 使用 Vite 创建应用

  1. 创建项目:

    npm init vite@latest my-first-vite-app --template vue
    
  2. 进入项目目录:

    cd my-first-vite-app
    
  3. 安装依赖:

    npm install
    
  4. 启动开发服务器:

    npm run dev
    

3.3 项目结构

无论是使用 Vue CLI 还是 Vite 创建的项目,其基本结构如下:

my-first-vue-app/
├── node_modules/
├── public/
├── src/
│   ├── assets/
│   ├── components/
│   ├── App.vue
│   ├── main.js
├── package.json
├── README.md
  • src/:存放源代码的目录。
  • public/:存放静态资源的目录。
  • App.vue:应用的根组件。
  • main.js:应用的入口文件。

4. Vue 实例和生命周期

4.1 Vue 实例

每个 Vue 应用都是通过创建一个 Vue 实例开始的。Vue 实例是 Vue 应用的核心,它包含了应用的数据、方法和生命周期钩子。

new Vue({
  el: '#app',
  data: {
    message: 'Hello, Vue!'
  },
  methods: {
    greet() {
      alert(this.message);
    }
  }
});

4.2 生命周期钩子

Vue 实例在创建、更新和销毁的过程中会触发一系列的生命周期钩子。常见的生命周期钩子包括:

  • beforeCreate:实例初始化之后,数据观测和事件配置之前。
  • created:实例创建完成后,数据观测和事件配置完成。
  • beforeMount:挂载开始之前,模板编译完成。
  • mounted:实例挂载到 DOM 上。
  • beforeUpdate:数据更新时,DOM 重新渲染之前。
  • updated:数据更新后,DOM 重新渲染完成。
  • beforeDestroy:实例销毁之前。
  • destroyed:实例销毁后。
new Vue({
  el: '#app',
  data: {
    message: 'Hello, Vue!'
  },
  beforeCreate() {
    console.log('beforeCreate');
  },
  created() {
    console.log('created');
  },
  beforeMount() {
    console.log('beforeMount');
  },
  mounted() {
    console.log('mounted');
  }
});

5. 模板语法和数据绑定

5.1 插值

Vue.js 使用双大括号 {{ }} 进行文本插值。

<div id="app">
  <p>{{ message }}</p>
</div>

5.2 指令

Vue.js 提供了多种指令来操作 DOM,常见的指令包括:

  • v-bind:动态绑定属性。
  • v-model:双向数据绑定。
  • v-if:条件渲染。
  • v-for:列表渲染。
<div id="app">
  <p v-bind:title="message">Hover me!</p>
  <input v-model="message">
  <p v-if="show">This is visible.</p>
  <ul>
    <li v-for="item in items" :key="item.id">{{ item.name }}</li>
  </ul>
</div>
new Vue({
  el: '#app',
  data: {
    message: 'Hello, Vue!',
    show: true,
    items: [
      { id: 1, name: 'Item 1' },
      { id: 2, name: 'Item 2' },
      { id: 3, name: 'Item 3' }
    ]
  }
});

6. 组件化开发

6.1 创建组件

在 Vue.js 中,组件是可复用的 Vue 实例。我们可以通过 Vue.component 或 .vue 文件来定义组件。

Vue.component('my-component', {
  template: '<div>A custom component!</div>'
});

6.2 使用组件

定义好组件后,可以在其他组件或根实例中使用。

<div id="app">
  <my-component></my-component>
</div>

6.3 单文件组件

在实际开发中,我们通常使用单文件组件(.vue 文件)来组织代码。单文件组件包含模板、脚本和样式。

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

<style scoped>
.hello {
  font-size: 2em;
  color: #42b983;
}
</style>

7. 组件通信

7.1 Props

父组件可以通过 props 向子组件传递数据。

<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent :message="parentMessage" />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  data() {
    return {
      parentMessage: 'Hello from parent!'
    };
  }
};
</script>
<!-- ChildComponent.vue -->
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  props: {
    message: String
  }
};
</script>

7.2 Events

子组件可以通过 $emit 向父组件发送事件。

<!-- ChildComponent.vue -->
<template>
  <div>
    <button @click="sendMessage">Send Message</button>
  </div>
</template>

<script>
export default {
  methods: {
    sendMessage() {
      this.$emit('message-sent', 'Hello from child!');
    }
  }
};
</script>
<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent @message-sent="handleMessage" />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  methods: {
    handleMessage(message) {
      alert(message);
    }
  }
};
</script>

7.3 Provide/Inject

provide 和 inject 用于跨层级组件通信。父组件通过 provide 提供数据,子组件通过 inject 接收数据。

<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  provide() {
    return {
      message: 'Hello from parent!'
    };
  }
};
</script>
<!-- ChildComponent.vue -->
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  inject: ['message']
};
</script>

8. 计算属性和侦听器

8.1 计算属性

计算属性是基于依赖进行缓存的属性,只有在依赖发生变化时才会重新计算。

<template>
  <div>
    <p>Original message: "{{ message }}"</p>
    <p>Computed reversed message: "{{ reversedMessage }}"</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello'
    };
  },
  computed: {
    reversedMessage() {
      return this.message.split('').reverse().join('');
    }
  }
};
</script>

8.2 侦听器

侦听器用于监听数据的变化,并在变化时执行相应的操作。

<template>
  <div>
    <p>Message: "{{ message }}"</p>
    <input v-model="message">
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello'
    };
  },
  watch: {
    message(newVal, oldVal) {
      console.log(`Message changed from ${oldVal} to ${newVal}`);
    }
  }
};
</script>

9. 条件渲染和列表渲染

9.1 条件渲染

v-if 和 v-show 用于条件渲染。v-if 会根据条件决定是否渲染元素,而 v-show 则通过 CSS 控制元素的显示和隐藏。

<template>
  <div>
    <p v-if="show">This is visible.</p>
    <p v-else>This is hidden.</p>
    <p v-show="show">This is always in the DOM.</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      show: true
    };
  }
};
</script>

9.2 列表渲染

v-for 用于列表渲染,可以遍历数组或对象。

<template>
  <div>
    <ul>
      <li v-for="item in items" :key="item.id">{{ item.name }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: [
        { id: 1, name: 'Item 1' },
        { id: 2, name: 'Item 2' },
        { id: 3, name: 'Item 3' }
      ]
    };
  }
};
</script>

10. 表单输入绑定

v-model 用于双向数据绑定,常用于表单输入。

<template>
  <div>
    <input v-model="message" placeholder="Enter a message">
    <p>Message is: {{ message }}</p>
  </div>
</template>

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

11. 单文件组件 (.vue 文件)

单文件组件(.vue 文件)是 Vue.js 推荐的组件组织方式,包含模板、脚本和样式。

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

<style scoped>
.hello {
  font-size: 2em;
  color: #42b983;
}
</style>

12. 组件注册 (全局和局部)

12.1 全局注册

全局注册的组件可以在任何地方使用。

Vue.component('my-component', {
  template: '<div>A custom component!</div>'
});

12.2 局部注册

局部注册的组件只能在注册它的组件中使用。

<template>
  <div>
    <my-component></my-component>
  </div>
</template>

<script>
import MyComponent from './MyComponent.vue';

export default {
  components: {
    MyComponent
  }
};
</script>

13. Scoped CSS

Scoped CSS 允许我们在单文件组件中定义局部样式,避免样式污染。

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

<style scoped>
.hello {
  font-size: 2em;
  color: #42b983;
}
</style>

14. CSS 预处理器 (Sass, Less)

Vue.js 支持使用 CSS 预处理器,如 Sass 和 Less。

14.1 使用 Sass

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

<style lang="scss" scoped>
$primary-color: #42b983;

.hello {
  font-size: 2em;
  color: $primary-color;
}
</style>

14.2 使用 Less

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

<style lang="less" scoped>
@primary-color: #42b983;

.hello {
  font-size: 2em;
  color: @primary-color