1 vue简介
Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面
Vue 是一个框架,也是一个生态。其功能覆盖了大部分前端开发常见的需求。但 Web 世界是十分多样化的,不同的开发者在 Web 上构建的东西可能在形式和规模上会有很大的不同。考虑到这一点,Vue 的设计非常注重灵活性和“可以被逐步集成”这个特点。根据你的需求场景,你可以用不同的方式使用 Vue:
- 无需构建步骤,渐进式增强静态的 HTML
- 在任何页面中作为 Web Components 嵌入
- 单页应用 (SPA)
- 全栈 / 服务端渲染 (SSR)
- Jamstack / 静态站点生成 (SSG)
- 开发桌面端、移动端、WebGL,甚至是命令行终端中的界面
2. 安装和创建一个vue项目
- 安装vue
1
$ npm install vue@^2
- 全局安装
vue CLI
。Vue CLI是一个基于Node.js的全局npm包,它提供了标准化的项目结构和开发流程1
npm install -g @vue/cli
- 快速搭建vue应用
1 | vue create myproject-veutest --default |
项目打包:打包 Vue 项目使用以下命令:
执行完成后,会在 Vue 项目下生成一个 dist 目录,一般包含 index.html 文件及 static 目录,static 目录包含了静态文件 js、css 以及图片目录 images。
1 >npm run build
2.1 项目的目录结构
上面我们使用npm创建了项目,打开myproject-vuetest
后,其目录有如下:
目录/文件 | 说明 |
---|---|
build | 项目构建(webpack)相关代码 |
config | 配置目录,包括端口号等。我们初学可以使用默认的。 |
node_modules | npm 加载的项目依赖模块 |
src | 这里是我们要开发的目录,基本上要做的事情都在这个目录里。里面包含了几个目录及文件: assets:放置一些图片,如logo等。 components: 目录里面放了一个组件文件,可以不用。 App.vue: 项目入口文件,我们也可以直接将组件写这里,而不使用 components 目录。 main.js: 项目的核心文件。 |
static | 静态资源目录,如图片、字体等。 |
test | 初始测试目录,可删除 |
.xxxx文件 | 这些是一些配置文件,包括语法配置,git配置等。 |
index.html | 首页入口文件,你可以添加一些 meta 信息或统计代码啥的。 |
package.json | 项目配置文件。 |
README.md | 项目的说明文档,markdown 格式 |
3. 重要的vue指令
v-bind
:v-bind 用于动态地绑定一个或多个属性,或一个组件 prop 到表达式。当表达式的值改变时,该属性将会更新。(可简写为:
)1
2
3
4#将src绑定到imageSrc上
<img v-bind:src="imageSrc" />
<!-- 简写形式 -->
<img :src="imageSrc" />v-text
:v-text 指令用于更新元素的 textContent。它会覆盖元素中原有的内容。1
2
3
4
5#输出message的文本内容
<span v-text="message"></span>
<!-- 简写形式(Vue 2.x 不支持简写) -->
<!-- Vue 3.x 中也没有直接简写,但你可以使用插值表达式 {{ }} -->
<span>{{ message }}</span>v-if
: 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。并且页面源码不会被隐藏1
2#showMessage为true时,才显示文本Hello, Vue!
<div v-if="showMessage">Hello, Vue!</div>v-else
:v-else
指令表示v-if
或v-else-if
条件块之后的“else 块”。v-else 元素必须紧跟在带 v-if 或 v-else-if 元素的兄弟元素之后,否则它将不会被识别。1
2
3<div v-if="condition1">条件1</div>
<div v-else-if="condition2">条件2</div>
<div v-else>其他情况</div>v-show
:根据条件来显示或隐藏元素。元素始终保持在 DOM 中,其低层原理是通过改变display
属性的值进行切换。因此源码在不显示时会被隐藏1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26<template>
<div>
<p v-show="isVisible">这个段落是可见的。</p>
<button @click="toggleVisibility">切换可见性</button>
</div>
</template>
<script>
export default {
data() {
return {
isVisible: true // 初始状态为可见
};
},
methods: {
toggleVisibility() {
this.isVisible = !this.isVisible; // 切换 isVisible 的值
}
}
}
</script>
<style scoped>
/* 这里的样式是可选的,仅为了说明可以添加样式 */
p {
transition: opacity 0.5s ease; /* 添加过渡效果,使显示和隐藏更平滑 */
}
</style>v-for
:基于数组或对象来渲染一个列表。注意在使用 v-for 时,应该提供一个唯一的:key
绑定,以帮助 Vue 跟踪每个节点的身份,从而重用和重新排序现有元素。>在这个例子中,v-for 指令用于在 items 数组上循环输出元素。:key 是一个特殊的绑定,用于给每个循环的元素提供一个唯一的 key,帮助 Vue 跟踪每个节点的身份。1
2
3
4
5
6
7
8
9
10
11
12
13<ul>
<li v-for="(item, index) in items" :key="index">
{{ item }}
</li>
</ul>
<script>
new Vue({
el: '#app',
data: {
items: ['Apple', 'Banana', 'Cherry']
}
})
</script>v-on
:用于监听 DOM 事件,并在触发时运行一些 JavaScript 代码。如 @click 或 v-on:click。(可简写为@
)1
2
3<button v-on:click="handleClick">点击我</button>
<!-- 简写形式 -->
<button @click="handleClick">点击我</button>v-model
:创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。主要用于表单输入元素,如<input>、<textarea>
和<select>
。>在这个例子中,v-model 指令将 input 元素和 Vue 实例中的 message 属性建立了双向数据绑定。当用户在 input 元素中输入信息时,Vue.js 会自动更新 message 属性的值。1
2
3
4
5
6
7
8
9
10<input v-model="message" placeholder="输入信息">
<script>
new Vue({
el: '#app',
data: {
message: ''
}
})
</script>v-once
:v-once 关联的实例,只会渲染一次。之后的重新渲染,实例及其所有的子节点将被视为静态内容忽略。这可以用于优化更新性能。
4 重要的vue属性1
el 属性:用来指示 Vue 编译器从什么地方开始解析 Vue 的语法,通常是一个占位符。
- data 属性:用来组织从视图中抽象出来的属性,即视图的数据抽象存放在 data 中。data 是一个特殊的选项,它用于存储组件的私有状态。这些状态可以是简单的变量(如字符串、数字、布尔值等),也可以是数组、对象等复杂类型。data 中的属性是响应式的,意味着当它们改变时,视图会自动更新。
- 函数形式:data 必须是一个函数,而不是一个对象。这是因为每个组件实例都有自己的 data 对象副本,而对象形式的 data 会导致多个组件实例共享同一个数据对象,这是不安全的。通过将 data 定义为函数,我们可以确保每个组件实例都有自己独立的数据副本。
- 响应式:data 中的属性是响应式的,但 Vue 不能检测对象属性的添加或删除。如果你需要添加或删除属性,并且希望这些变化能够触发视图更新,你应该使用 Vue.set 方法或 Object.assign 方法来添加属性,或者使用 Vue.delete 方法来删除属性。
- 避免直接修改 props:虽然 data 和 props 都是用于存储组件的状态,但你应该避免直接修改从父组件传入的 props。如果 props 的值需要被修改,你应该在 data 中创建一个新的状态变量,并使用 props 的值来初始化它。这样,你就可以安全地修改 data 中的状态,而不会影响到父组件或其他子组件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<template>
<div>
<p>Message: {{ message }}</p>
<button @click="changeMessage">Change Message</button>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello Vue!'
};
},
methods: {
changeMessage() {
this.message = 'Hello, world!';
}
}
};
</script>
methods 属性:放置页面中的业务逻辑,JS 方法一般都放置在 methods 中。
>在这个例子中,我们定义了一个 Vue 组件,其中包含了数据 message 和一个方法 reverseMessage。当按钮被点击时,reverseMessage 方法会被调用,从而改变 message 的值。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<template>
<div>
<p>{{ message }}</p>
<button @click="reverseMessage">Reverse</button>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello, Vue!'
};
},
methods: {
reverseMessage() {
this.message = this.message.split('').reverse().join('');
}
}
}
</script>- computed 属性:用于计算 Vue.js 计算属性,当依赖的数据发生变化时,计算属性会重新求值。允许我们定义基于其他属性的计算属性。这些计算属性是响应式的,并且只有当其依赖的数据属性发生变化时才会重新计算
- 特点:
- 基于依赖进行缓存:computed属性的值会被缓存,并且只有在相关依赖属性发生变化时才会重新计算。这可以避免重复计算,提高代码效率。
- 自动更新:computed属性的值会根据相关依赖的变化而自动更新,无需手动触发。
- 使用函数返回结果:computed属性的定义类似于普通的属性,但需要使用函数来返回计算结果。 >在上面的例子中,我们定义了一个名为fullName的计算属性,它根据firstName和lastName计算得出。同时,我们还为fullName定义了setter方法,以便当fullName被赋值时能够更新firstName和lastName的值。 > >在Vue的模板中,我们可以像使用普通属性一样使用computed属性。Vue会自动处理计算属性的依赖关系,并在相关数据变化时更新计算属性。 > >
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18new Vue({
data: {
firstName: 'John',
lastName: 'Doe'
},
computed: {
fullName: {
get: function () {
return this.firstName + ' ' + this.lastName;
},
set: function (newValue) {
var names = newValue.split(' ');
this.firstName = names[0];
this.lastName = names[names.length - 1];
}
}
}
});>在这个例子中,我们直接在模板中使用了fullName计算属性。当firstName或lastName发生变化时,fullName的值会自动更新,并且模板中的显示也会相应地更新。1
><div>{{ fullName }}</div>
- 特点:
- watch 属性:Vue.js 监听属性,可以通过 watch 来响应数据的变化。当需要在数据变化时执行异步操作或开销较大的操作时,watch 是一个非常有用的工具。下面做一个简单介绍
- 在 Vue 实例或组件的 watch 属性中,可以定义一个或多个观察器。每个观察器都是一个函数或对象,用于指定要观察的数据属性和当该数据属性变化时执行的回调函数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16new Vue({
el: '#app',
data: {
nestedObj: {
prop: 'Hello'
}
},
watch: {
nestedObj: { //观察的对象是nestedObj
handler(newValue, oldValue) {
console.log('nestedObj changed');
},
deep: true // 深度监听
}
}
});
- 在 Vue 实例或组件的 watch 属性中,可以定义一个或多个观察器。每个观察器都是一个函数或对象,用于指定要观察的数据属性和当该数据属性变化时执行的回调函数。
生命周期钩子:Vue 实例从创建到销毁的过程中,会经历一系列的事件,这些事件被称为 Vue 的生命周期钩子。包括
beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy 和 destroyed
等。>在这个例子中,我们使用了1
2
3
4
5
6
7
8
9
10
11
12<script>
export default {
// ...其他选项...
created() {
console.log('Component has been created!');
},
mounted() {
console.log('Component has been mounted to the DOM!');
}
// ...其他生命周期钩子...
}
</script>created
和mounted
这两个生命周期钩子。当组件被创建时,created
钩子会被调用;当组件被挂载到 DOM 时,mounted
钩子会被调用。这些钩子允许我们在组件的不同阶段执行特定的操作。props
:props(属性) 是 Vue.js 中组件间通信的一种重要方式,用于父组件向子组件传递数据。在 Vue.js 中,组件是可复用的 Vue 实例,带有可复用的模板和逻辑。props 使我们可以明确地向子组件传递数据,而不需要依赖全局状态管理或其他方法。- 使用
- 子组件需要明确声明props,可以通过字符串数组或对象的形式来定义。
- 父组件通过组件标签上的属性将数据传递给子组件。
- 当使用非字符串模板时,prop的名字形式会从camelCase(驼峰命名)转为kebab-case(短横线命名)。
- 特性
- Prop是单向数据流,只能从父组件流向子组件。子组件不能直接修改props的值,只能通过父组件来修改。
- 可以通过v-bind(或简写为:)来动态绑定props的值到父组件的数据上。这样当父组件的数据变化时,子组件也会得到更新。
- Props可以进行类型验证、设置默认值等,以确保接收到的数据符合期望。 >在这个示例中,父组件通过message属性向子组件传递了一个字符串"Hello, Vue!",子组件在模板中使用了这个prop来显示内容。
1
2
3
4
5
6
7// 子组件定义
Vue.component('child-component', {
props: ['message'],
template: '<span>{{ message }}</span>'
})
// 父组件使用
<child-component message="Hello, Vue!"></child-component>
- 使用
注意:
- new vue:显示创建了一个vue实例,这个实例包含了data、methods、computed、watch、template
- export default:导出的是一个 Vue 组件对象,而不是一个直接的 Vue 实例,这个组件对象包含了定义该组件所需的所有选项,如 data、methods、computed、watch、template等,当年将这个组件挂载到DOM上时,vue会根据这个组件自动创建一个或多个对于的实例。
5 vue重要属性2
template
:template 是 Vue.js 组件中的一个选项,用于定义组件的 HTML 模板。它可以是内联的 HTML 字符串,也可以是一个选择器,用于在 HTML 文档中查找已存在的模板。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18Vue.component('my-component', {
data: function() {
return {
message: 'Hello, Vue!'
};
},
template: `
<div>
<h1>{{ message }}</h1>
<button @click="changeMessage">Change Message</button>
</div>
`,
methods: {
changeMessage: function() {
this.message = 'Hello, World!';
}
}
});render
:render 是一个函数,它使用 Vue 的虚拟 DOM 来构建组件的 HTML 结构。在复杂的应用中,render 函数通常用于编写更复杂的逻辑和渲染条件。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22Vue.component('my-component', {
data: function() {
return {
message: 'Hello, Vue!'
};
},
render: function(createElement) {
return createElement('div', [
createElement('h1', this.message),
createElement('button', {
on: {
click: this.changeMessage
}
}, 'Change Message')
]);
},
methods: {
changeMessage: function() {
this.message = 'Hello, World!';
}
}
});components
:components 选项用于在 Vue 组件中注册子组件。这使得我们可以在父组件的模板中使用子组件。在 Vue.js 中,你可以定义自己的组件,并在其他 Vue 实例或组件的模板中使用它们,后续详解filters
:filters 选项用于定义全局或组件级别的文本过滤器。过滤器可以用于在 mustache 插值({{ }})
或v-bind
表达式中,用于在显示之前对文本进行格式化。1
2
3
4
5
6
7
8
9
10
11Vue.filter('uppercase', function(value) {
if (!value) return ''
value = value.toString()
return value.toUpperCase()
})
new Vue({
el: '
' hello
6 component
Vue.js 中可以自定义组件。在 Vue.js 中,你可以定义自己的组件,并在其他 Vue 实例或组件的模板中使用它们。以下是关于如何使用
6.1 定义组件
在Vue中,export default是一种ES6模块语法的特性,用于将一个模块或对象的默认导出。对于Vue组件来说,你可以使用export default来导出你的组件定义,然后在其他文件中通过import语句来引入并使用这个组件。 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<!-- MyComponent.vue -->
<template>
<div>这是一个自定义组件</div>
</template>
<script>
export default {
name: 'MyComponent',
// 其他组件选项,如data、methods、props等
}
</script>
<style scoped>
/* 组件的样式 */
</style>
6.2 使用该组件
在使用这个组件时,你需要导入这个组件,并且做全局注册或者局部注册后再使用,或者直接再模板中使用:
局部注册
1
2
3
4
5
6
7
8
9
10// 引入组件
import MyComponent from './MyComponent.vue'
// 注册并使用组件
new Vue({
el: '#app',
components: {
'my-component': MyComponent // 这里你可以使用其他名称来注册组件,但在模板中需要使用这个名称
}
})全局注册
1
2
3
4
5Vue.component('my-component', {
// 组件选项
template: '<div>这是一个自定义组件</div>',
// 还可以有 data、methods、props 等其他选项
});模板中像HTNL元素一样使用
因为你的组件设置了,因此整体模板等价于这样:1
2
3<div id="app">
<my-component></my-component>
</div>1
2
3<div id="app">
<div>这是一个自定义组件</div>
</div>
6.3 例子
props 是 Vue 组件中非常重要的一个概念,它允许你向子组件传递数据。你可以将 props 当作子组件的属性来使用,这些属性可以在子组件的模板、计算属性、方法以及生命周期钩子中被访问和使用。
在定义组件时,你可以在组件的 props 选项中声明一个属性列表,并指定它们的类型、默认值、是否必传等。然后,在父组件中使用子组件时,可以通过特性(attribute)的方式向子组件传递这些 props
1 | <!-- MyComponent.vue --> |
在另一个文件使用MyComponent.vue
: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- App.vue 或其他使用 MyComponent 的地方 -->
<template>
<div id="app">
<!-- 使用 MyComponent 并传递 message prop -->
<MyComponent message="这是从父组件传递的消息"></MyComponent>
</div>
</template>
<script>
import MyComponent from './MyComponent.vue';
export default {
name: 'App',
components: {
MyComponent
}
}
</script>
注意,子组件应该避免修改通过 props 传递进来的数据,因为这可能会导致数据流变得难以理解和维护。如果子组件需要基于 props 的值来改变其状态,它应该使用 data 或 computed 属性来保存这个状态,而不是直接修改 props。