vue的项目结构

首先需要了解下vue的项目结构,根据vue-cli创建的初始项目可以看到主要由下面的方式组成。

public(放置各种不需要打包处理的文件)
src
  |__assets(各种资源,图片、字体等)
  |__components(小组件,如树形组件等)
  |__plugins(插件配置)
  |__router(各页面路由管理)
  |__store(状态记录仓库)
  |__views(一个完整视图组件)
  |__App.vue(根组件,可理解为首页)
  |__main.js(由此创建实例,并将用到的组件挂载到public里的index.html中)
package.json(npm包管理文件)
package-lock.json(锁定版本的包)
babel.config.js(babel配置文件)
.gitignore(git忽略文件)

创建vue实例

每个 Vue 应用都是通过用 createApp 函数创建一个新的应用实例开始的:

const app = Vue.createApp({
  /* 选项 */
})

实例的大多数方法返回值都是此实例,允许链式调用:

Vue.createApp({})
  .component('SearchInput', SearchInputComponent)
  .directive('focus', FocusDirective)
  .use(LocalePlugin)

根组件

传递给createApp的选项用于配置根组件。当我们挂载应用时,该组件被用作渲染的起点。

一个应用需要被挂载到一个 DOM 元素中。例如,如果你想把一个 Vue 应用挂载到 <div id="app"></div>,应该传入#app

const RootComponent = { 
  /* 选项 */ 
}
const app = Vue.createApp(RootComponent)
const vm = app.mount('#app')

与大多数应用方法不同的是,mount不返回应用本身。相反,它返回的是根组件实例。

每个.vue文件都是一个组件,而上面提到的App.vue就是一个根组件,它一般会在main.js中以下面的方式挂载到index.html的DOM中。

import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

模版语法

首先一个.vue文件由以下几部分组成:

<template>
<!-- 这里可以写html,以及使用vue的模版语法,类似于thymeleaf -->
</template>

<script>
// 这里可以写js、ts代码
export default {
  name: 'App'
}
</script>

<style>
// 这里可以写组件用到的css、scss、sass等样式
</style>

组件实例属性

在一个vue文件中使用export导出的对象就是这个组件的实例对象,在这个对象中有datamethodspropscomputedinjectsetup等属性可以使用。

template标签中要想使用动态的值就需要在这个组件的data属性中设置(data是一个函数,且函数返回值必须为一个json对象),如果想要动态改变这个值那么可以在methods对象中添加函数去控制。可以通过props属性向子组件传递值。

下面给出一个简单的案例(基于vue-cli创建的demo做出的修改):

  • 子组件
<template>
  <div>{{ msg }}</div>
  <h1>{{ tips }}</h1>
  <button v-on:click="change">change</button>
</template>

<script>
export default {
  name: "Demo",
  props: {
    msg: String
  },
  data() {
    return {
      tips: 'this is a demo data'
    }
  },
  methods: {
    change() {
      this.tips = this.tips + ' by change.'
    }
  }
}
</script>

<style scoped>
button {
  width: 100px;
  height: 40px;
  background-color: antiquewhite;
}

div {
  font-size: medium;
  font-weight: bold;
}
</style>
  • 父组件
<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <Demo msg="this is a parent msg"/>
</template>

<script>
import Demo from "./components/Demo";

export default {
  name: 'App',
  components: {
    Demo,
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

插值

在上面这个案例中我用到了两个模版语法:{{}}v-on,其中“Mustache”语法的{{}}被称为插值{{}}仅可以在标签的body中使用,而v-bind可以用于标签的属性上。无论是插值还是指令都支持JavaScript表达式,但是仅限于单个表达式,不包括流程控制、变量声明、声明函数等。支持例如下面这样的:

{{ number + 1 }}

{{ ok ? 'YES' : 'NO' }}

{{ message.split('').reverse().join('') }}

<div v-bind:id="'list-' + id"></div>

{{}}中的变量值如果被更改了那么html中也会被更改,如果想要仅执行一次插值,后续变量更改不变那么v-once可以满足这样的需求。

<span v-once>这个将不会改变: {{ msg }}</span>

{{}}中的文本会被解析为普通文本,如果这个文本内容是一个html也不会被渲染,如果需要渲染变量中的html需要使用到v-html指令

<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>

指令

上面的案例还用到了一个v-on,它通常被称为指令。指令 (Directives) 是带有v-前缀的特殊attribute。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM。

参数

一些指令能够接收一个“参数”,在指令名称之后以冒号表示。例如,v-bind指令可以用于响应式地更新 HTML attribute:

<a v-bind:href="url"> ... </a>

再比如案例中v-on:click指令用于监听DOM事件。

指令的参数可以使用js表达式,方式是用[]代替:,这样的参数被称为动态参数。

修饰符

修饰符 (modifier) 是以半角句号.指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent修饰符告诉v-on指令对于触发的事件调用event.preventDefault()

<form v-on:submit.prevent="onSubmit">...</form>

缩写

对于常用的v-bindv-on指令,Vue提供了它们的缩写方式:

  • v-bind缩写
<!-- 完整语法 -->
<a v-bind:href="url"> ... </a>

<!-- 缩写 -->
<a :href="url"> ... </a>

<!-- 动态参数的缩写 -->
<a :[key]="url"> ... </a>
  • v-on缩写
<!-- 完整语法 -->
<a v-on:click="doSomething"> ... </a>

<!-- 缩写 -->
<a @click="doSomething"> ... </a>

<!-- 动态参数的缩写 (2.6.0+) -->
<a @[event]="doSomething"> ... </a>

附录

指令作用详细说明
v-if条件渲染v-if
v-else-if配合v-if使用v-else-if
v-else配合v-if使用v-else
v-show控制元素是否显示v-show
v-for列表渲染v-for
v-onDOM事件监听v-on
v-model表单输入双向绑定v-model
v-bind数据绑定v-bind
v-once不更新插值,仅渲染一次v-once
v-html渲染数据中的htmlv-html
v-is解除原生 HTML 解析规则的约束,如<table>下只能用<tr>v-is
v-pre原样显示原始 Mustache 标签,不编译v-pre
v-cloak可配合css让关联组件未完成编译前不显示v-cloak
v-text等价于Mustache插值v-text
v-slot提供具名插槽或需要接收 prop 的插槽。v-slot

参考文献

vue官方文档