1.基本使用
2.生命周期钩子
3.模板语法
4.常用指令
5.数据侦听器
6.Class、Style 绑定
7.条件渲染
8.列表渲染
9.表单输入绑定
10.组件
11.插槽
12.脚手架环境配置
13.目录结构与组件路由
14.整合 bootstrap
15.使用 vuex
16.整合 elementUI
1.基本使用
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
英文官网: https//vuejs.org
中文官网: https:/cn.vuejs.org
最简单的安装方式是创建一个 .html 文件,然后通过如下方式引入 Vue:
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
当然也可以使用 Node.js 的构建工具安装 vue-cli。这种方式主要针对专业前端开发,这里便不再赘述。
为了使 idea 有更好的代码提示效果,建议安装 vue.js 插件。
正在上传…重新上传取消
Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统,以操作数据的方式操作 DOM 节点,Vue 不建议使用者直接操作节点内容,目前大部分开发平台都倡导以修改数据的方式操作节点,操作节点被认为是一种落后的技术。
<div id="app">
{{ message }}
</div>
渲染代码:
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
如此便成功创建了第一个 Vue 应用!看起来这跟渲染一个字符串模板非常类似,但是 Vue 在背后做了大量工作。现在数据和 DOM 已经被建立了关联,所有东西都是响应式的。
通过浏览器控制台输入 app.message="测试" 可以修改vue的数据,会发现一旦数据变化了,vue 管理的页面也发生变化。
为了让用户和你的应用进行交互,我们可以用 v-on 指令添加一个事件监听器,通过它调用在 Vue 实例中定义的方法:
<div id="app-5">
<p>{{ message }}</p>
<button v-on:click="reverseMessage">反转消息</button>
</div>
渲染代码:
var app5 = new Vue({
el: '#app-5',
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
})
注意在 reverseMessage 方法中,更新了应用的状态,但没有触碰 DOM。所有的 DOM 操作都由 Vue 来处理,编写的代码只需要关注逻辑层面即可。
2.生命周期钩子
每个 Vue 实例在被创建时都要经过一系列的初始化过程。例如:需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
比如 created 钩子可以用来在一个实例被创建之后执行代码:
new Vue({
data: {
a: 1
},
created: function () {
// `this` 指向 vm 实例
console.log('a is: ' + this.a)
}
})
// => "a is: 1"
也有一些其它的钩子,在实例生命周期的不同阶段被调用,如 mounted、updated 和 destroyed。生命周期钩子的 this 上下文指向调用它的 Vue 实例。
这是官方文档给出的一个组件从被创建出来到最后被销毁所要经历的一系列过程,所以这个过程也叫做一个组件的生命周期图。从图中我们可以看到,一个组件从被创建到最后被销毁,总共要经历以下8个过程:
beforeCreate 组件创建之前
created 组件创建完毕
beforeMount 组件挂载之前
mounted 组件挂载完毕
beforeUpdate 组件更新之前
updated 组件更新完毕
beforeDestroy 组件销毁之前
destroyed 组件销毁完毕
案例:
let app = new Vue({
el: "#app",
data: {
message: "大家好,我是vue"
},
beforeCreate() {
console.info("beforeCreate:组件创建之前")
},
created() {
console.info("created:组件创建完毕")
},
beforeMount() {
console.info("beforeMount:组件挂载之前")
},
mounted() {
console.info("mounted:组件挂载完毕")
},
beforeUpdate() {
console.info("beforeUpdate:组件更新之前")
},
updated() {
console.info(" updated:组件更新完毕")
},
beforeDestroy() {
console.info("beforeDestroy:组件销毁之前")
},
destroyed() {
console.info("destroyed:组件销毁完毕")
},
methods: {
setMessage() {
this.message = this.message.split('').reverse().join('')
}
}
})
3.模板语法
1.插值
数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:
<span>Message: {{ msg }}</span>
Mustache 标签将会被替代为对应数据对象上 msg 属性的值。无论何时,绑定的数据对象上 msg 属性发生了改变,插值处的内容都会更新。
通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定:
<span v-once>这个将不会改变: {{ msg }}</span>
2.原始 HTML
双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html 指令:
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
这个 span 的内容将会被替换成为属性值 rawHtml,直接作为 HTML——会忽略解析属性值中的数据绑定。
3.Attribute
Mustache 语法不能作用在 HTML attribute 上,遇到这种情况应该使用 v-bind 指令:
<div v-bind:id="dynamicId"></div>
对于布尔 attribute (它们只要存在就意味着值为 true),v-bind 工作起来略有不同,在这个例子中:
<button v-bind:disabled="isButtonDisabled">Button</button>
如果 isButtonDisabled 的值是 null、undefined 或 false,则 disabled attribute 甚至不会被包含在渲染出来的 button 元素中。
4.使用 JavaScript 表达式
迄今为止,在我们的模板中,我们一直都只绑定简单的属性键值。但实际上,对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>
4.常用指令
指令(Directives)是带有 v- 前缀的特殊 attribute。指令 attribute 的值预期是单个 JavaScript 表达式 (v-for 是例外情况,稍后我们再讨论)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。回顾前面看到的例子:
<p v-if="seen">现在你看到我了</p>
这里,v-if 指令将根据表达式 seen 的值的真假来插入/移除
元素。
一些指令能够接收一个“参数”,在指令名称之后以冒号表示。例如,v-bind 指令可以用于响应式地更新 HTML attribute:
<a v-bind:href="url">...</a>
在这里 href 是参数,告知 v-bind 指令将该元素的 href 与 attribute 与表达式 url 的值绑定。
另一个例子是 v-on 指令,它用于监听 DOM 事件:
<a v-on:click="doSomething">...</a>
在这里参数是监听的事件名。我们也会更详细地讨论事件处理。
从 2.6.0 开始,可以用方括号括起来的 JavaScript 表达式作为一个指令的参数,但是变量名会被 vue 转为小写,所以建议使用下划线命名。
<a v-bind:[attribute_name]="url"> ... </a>
这里的 attribute_name 会被作为一个 JavaScript 表达式进行动态求值,求得的值将会作为最终的参数来使用。例如,Vue 实例有一个 data 属性 attribute_name,其值为 "href",那么这个绑定将等价于 v-bind:href。
同样地,你可以使用动态参数为一个动态的事件名绑定处理函数:
<a v-on:[event_name]="doSomething"> ... </a>
在这个示例中,当 eventName 的值为 "focus" 时,v-on:[eventName] 将等价于 v-on:focus。
指令缩写
1.v-bind 缩写
<!-- 完整语法 -->
<a v-bind:href="url">...</a>
<!-- 缩写 -->
<a :href="url">...</a>
<!-- 动态参数的缩写 (2.6.0+) -->
<a :[key]="url"> ... </a>
2.v-on 缩写
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>
<!-- 缩写 -->
<a @click="doSomething">...</a>
<!-- 动态参数的缩写 (2.6.0+) -->
<a @[event]="doSomething"> ... </a>
它们看起来可能与普通的 HTML 略有不同,但 : 与 @ 对于 attribute 名来说都是合法字符,在所有支持 Vue 的浏览器都能被正确地解析。而且,它们不会出现在最终渲染的标记中。缩写语法是完全可选的。
5.数据侦听器
当需要监听数据变化时就需要侦听器。Vue 通过 watch 选项提供了一套更通用的方法,来响应数据的变化。
<div id="watch-example">
<p>
Ask a yes/no question:
<input v-model="question">
</p>
<p>{{ answer }}</p>
</div>
渲染代码:
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
// 如果 `question` 发生改变,这个函数就会运行
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
}
}
})
6.Class、Style 绑定
我们可以传给 v-bind:class 一个对象,以动态地切换 class:
<div v-bind:class="{ active: isActive }"></div>
上面的语法表示 active 这个 class 存在与否将取决于数据 property isActive 的 truthiness。 你可以在对象中传入更多字段来动态切换多个 class。此外,v-bind:class 指令也可以与普通的 class attribute 共存。当有如下模板:
<div class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
和如下 data:
data: {
isActive: true,
hasError: false
}
结果渲染为:
<div class="static active"></div>
当 isActive 或者 hasError 变化时,class 列表将相应地更新。例如,如果 hasError 的值为 true,class 列表将变为 "static active text-danger"。
绑定的数据对象不必内联定义在模板里:
<div v-bind:class="classObject"></div>
data: {
classObject: {
active: true,
'text-danger': false
}
}
v-bind:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
渲染模板数据:
data: {
activeColor: 'red',
fontSize: 30
}
直接绑定到一个样式对象通常更好,这会让模板更清晰:
<div v-bind:style="styleObject"></div>
渲染模板数据:
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
v-bind:style 的数组语法可以将多个样式对象应用到同一个元素上:
<div v-bind:style="[baseStyles, overridingStyles]"></div>
7.条件渲染
1.v-if 用于条件限制某节点的渲染与否。
<h1 v-if="awesome">Vue is awesome!</h1>
也可以用 v-else 添加一个“else 块”:
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no </h1>
vue 2.1.0 新增 v-else-if,顾名思义,充当 v-if 的“else-if 块”,可以连续使用:
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
2.v-show 用于根据条件展示元素的指令。用法与 v-if 大致一样。
<h1 v-show="ok">Hello!</h1>
不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS 属性 display。
8.列表渲染
我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。
<ul id="example-1">
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
渲染代码:
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
在 v-for 还支持一个可选的第二个参数,即当前项的索引。
<ul id="example-2">
<li v-for="(item, index) in items">
- {{ index }} - {{ item.message }}
</li>
</ul>
你也可以用 of 替代 in 作为分隔符,因为它更接近 JavaScript 迭代器的语法:
<div v-for="item of items"></div>
在 v-for 里使用对象,也可以用 v-for 来遍历一个对象的属性。
<ul id="v-for-object">
<li v-for="value in object">
{{ value }}
</li>
</ul>
渲染代码:
new Vue({
el: '#v-for-object',
data: {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
})
你也可以提供第二个的参数为 property 名称 (也就是键名):
<div v-for="(value, name) in object">
{{ name }}: {{ value }}
</div>
还可以用第三个参数作为索引:
<div v-for="(value, name, index) in object">
{{ index }}. {{ name }}: {{ value }}
</div>
9.表单输入绑定
你可以用 v-model 指令在表单 input、textarea 及 select 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
- text 和 textarea 元素使用 value 属性和 input 事件
- checkbox 和 radio 使用 checked 属性和 change 事件
- select 字段将 value 作为 prop 并将 change 作为事件
1.单行文本
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
2.多行文本
<p>Message is: {{ message }}</p>
<textarea v-model="message" placeholder="add multiple lines"></textarea></p><p>3.复选框</p><p>单个复选框,绑定到布尔值:</p><input type="checkbox" v-model="checked">
<p>选中:{{ checked }}</p>
多个复选框,绑定到同一个数组:
<div id='example-3'>
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<span>Checked names: {{ checkedNames }}</span>
</div>
4.单选按钮绑定到普通字符串
<div id="example-4">
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<span>Picked: {{ picked }}</span>
</div>
5.选择框
单选时:
<div id="example-5">
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
多选时 (绑定到一个数组):
<div id="example-6">
<select v-model="selected" multiple>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
用 v-for 渲染的动态选项:
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
渲染数据:
new Vue({
el: '...',
data: {
selected: 'A',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
})
10.组件
组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
注册一个全局组件语法格式如下:
Vue.component(tagName, options)
tagName 为组件名,options 为配置选项。
注册后,我们可以使用以下方式来调用组件:
<tagName></tagName>
组件虽然在单独使用 vue.js 时使用不多,但在 vue 单页面应用即 vue 脚手架中使用颇多。
<div id="app">
<runoob></runoob>
</div>
<script>
// 注册
Vue.component('runoob', {
template: '<h1>自定义组件!</h1>'
})
// 创建根实例
new Vue({
el: '#app'
})
</script>
Prop
prop 是子组件用来接受父组件传递过来的数据的一个自定义属性。 父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
<div id="app">
<child message="hello!"></child>
</div>
<script>
// 注册
Vue.component('child', {
// 声明 props
props: ['message'],
// 同样也可以在 vm 实例中像 "this.message" 这样使用
template: '<span>{{ message }}</span>'
})
// 创建根实例
new Vue({
el: '#app'
})
</script>
动态 Prop
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件。
<div id="app">
<div>
<input v-model="parentMsg">
<child v-bind:message="parentMsg"></child>
</div>
</div>
<script>
Vue.component('child', {
props: {'message': {type: String, default: ""}},
template: '<span>{{ message }}</span>'
})
new Vue({
el: '#app',
data: {
parentMsg: '父组件内容'
}
})
</script>
注意:
1.prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
2.props 里面的键必须是中划线命名,不能使用驼峰命名。
当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。 type 可以是下面原生构造器: String Number Boolean Array Object Date Function Symbol type 也可以是一个自定义构造器,使用 instanceof 检测。
子组件向父组件传值,子组件向父组件传值是通过 emit 方法的方式。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h1>{{formSon}}</h1>
<com2 @func="show"></com2>
<com2 @func="show"></com2>
</div>
<template id="tmpl">
<div>
<p>这是子组件</p>
<input type="button" :value="son.age" @click="sonClick()">
</div>
</template>
<script>
Vue.component('com2', {
template: '#tmpl',
data() {
return {
son: {
name: '小头儿子',
age: 6
}
}
},
methods: {
sonClick() {
this.son.age++;
this.$emit('func', this.son)
}
}
});
let vm = new Vue({
el: '#app',
data: {
formSon: {}
},
methods: {
show(data) {
this.formSon = data
}
}
});
</script>
</body>
</html>
11.插槽
插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的标签。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h1>{{message}}</h1>
<com2>
<div>
<h1>父组件给子组件传代码块1</h1>
</div>
</com2>
<com2>
<div>
<h1>父组件给子组件传代码块2</h1>
</div>
</com2>
</div>
<template id="tmpl">
<div>
<p>这是子组件</p>
<slot></slot>
</div>
</template>
<script>
Vue.component('com2', {
template: '#tmpl',
data() {
return {}
}
});
let vm = new Vue({
el: '#app',
data: {
message: "演示插槽"
},
methods: {}
});
</script>
</body>
</html>
注意:如果子组件没有使用插槽,父组件如果需要往子组件中填充模板或者html, 是没法做到的
具名插槽案例:
具名插槽其实就是给插槽取个名字。一个子组件可以放多个插槽,而且可以放在不同的地方,而父组件填充内容时,可以根据这个名字把内容填充到对应插槽中,父组件通过 v-slot:[name] 的方式指定到对应的插槽中。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h1>{{message}}</h1>
<com2>
<template v-slot:slot1>
<h1>父组件给子组件传代码块1</h1>
</template>
<template v-slot:slot2>
<h1>父组件给子组件传代码块2</h1>
</template>
</com2>
<com2>
<template v-slot:slot2>
<h1>父组件给子组件传代码块2</h1>
</template>
<template v-slot:slot1>
<h1>父组件给子组件传代码块1</h1>
</template>
</com2>
</div>
<template id="tmpl">
<div>
<p>这是子组件</p>
<slot name="slot1"></slot>
<slot name="slot2"></slot>
</div>
</template>
<script>
Vue.component('com2', {
template: '#tmpl',
data() {
return {}
}
});
let vm = new Vue({
el: '#app',
data: {
message: "演示插槽"
},
methods: {}
});
</script>
</body>
</html>
12.脚手架环境配置
1.安装 node js 安装完成后 cmd 打开命令提示符窗口,输入: npm -v 检测是否安装成功,如果输出版本号,则表示安装成功。
2.配置 npm
npm(node package manager):nodejs 的包管理器,用于 node 插件管理(包括安装、卸载、管理依赖等)因为 npm 安装插件是从国外服务器下载,受网络的影响比较大,可能会出现异常,所以我们乐于分享的淘宝团队干了这事。来自官网:这是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10 分钟一次以保证尽量与官方服务同步。
npm config set registry https://registry.npm.taobao.org
验证命令 npm config get registry 如果返回 https://registry.npm.taobao.org/,说明镜像配置成功。有时一些项目中相关依赖下载报错也可以安装 cnpm。使用时只需要将原来的 npm 换成 cnpm 命令即可。 安装 cnpm 命令如下:
npm install -g cnpm --registry=https://registry.npm.taobao.org
在一些大型前端项目中可能会报错说 python 没找到。只需要为 npm 或 cnpm 全局安装 windows-build-tools 即可。
npm install --global --production windows-build-tools
3.在 NPM 中全局安装 Vue.js 构建大型应用。
npm install vue --global
4.全局安装 vue-cli
npm install --global vue-cli
5.创建一个基于 webpack 模板的新项目
vue init webpack my-project
输入命令后,会跳出几个选项让你回答:
Project name (baoge): -----项目名称,直接回车,按照括号中默认名字(注意这里的名字不能有大写字母,如果有会报错Sorry, name can no longer contain capital letters),
Project description (A Vue.js project): ----项目描述,也可直接点击回车,使用默认名字
Author (): ----作者,输入你的大名 接下来会让用户选择:
Runtime + Compiler: recommended for most users 运行加编译,既然已经说了推荐,就选它了
Install vue-router? (Y/n) 是否安装vue-router,这是官方的路由,输入“y”回车或直接回车安装。
Use ESLint to lint your code? (Y/n) 是否使用 ESLint 管理代码,ESLint 是个代码风格管理工具,是用来统一代码风格的,选择不安装。
Pick an ESLint preset (Use arrow keys) 选择一个ESLint预设,编写vue项目时的代码风格,选择不安装。
Setup unit tests with Karma + Mocha? (Y/n) 是否安装单元测试,选择不安装。
Setup e2e tests with Nightwatch(Y/n)? 是否安装e2e测试 ,选择不安装。
npm 安装依赖,选择使用自定义。
回答完毕后上图就开始构建项目了
启动并允许
cd my-project
npm install
npm run dev
DONE Compiled successfully in 4388ms
> Listening at http://localhost:8080
打开地址:http://localhost:8080/
将项目拖入 idea 进行开发,idea 需要安装 vue.js 插件,由于 vue 脚手架项目会大量更新 node_modules 下的文件,导致软件卡顿。使用如下配置可以让 idea 忽略检查该目录。
注意:Vue.js 不支持 IE8 及其以下 IE 版本。
扩展:ESLint
ESLint 是一个插件化并且可配置的 JavaScript语法规则和代码风格的检查工具。ESLint能够帮你轻松写出高质量的 JavaScript代码。如果安装 ESLint 后 package.json 中的 scripts 里面多了一条命令:
"lint": "eslint --ext .js,.vue src",
同时 devDependencies 中多了如下依赖,在 devDependencies 中安装依赖命令为 npm install --save-dev 依赖包名
"babel-eslint": "^8.2.1",
"eslint": "^4.15.0",
"eslint-config-standard": "^10.2.1",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.7.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^5.2.0",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^3.0.1",
"eslint-plugin-vue": "^4.0.0",
项目中同时也会增加两个文件,一个存放忽略检查文件路径,一个是 eslint 的核心配置
.eslintignore
.eslintrc.js
最后在 build 下的 webpack.base.conf.js 中多了如下配置:
...
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
module.exports = {
....,
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
....
]
},
....
}
13.目录结构与组件路由
上一章节中我们使用了 npm 安装项目,我们在 IDED 中打开该目录,结构如下所示:
目录解析
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 格式
修改 HelloWorld.vue 中的 msg 的值,页面跟着相应的变化。
在 components 下创建组件 About.vue 和 User.vue 内容如下:
<template>
<div class="user">
<h1>用户管理</h1>
</div>
</template>
<script>
export default {
name: "User"
}
</script>
<style scoped="">
</style>
在router/index.js 中配置路由信息:
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import User from "../components/User";
import About from "../components/About";
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/user',
name: 'user',
component: User
},
{
path: '/about',
name: 'about',
component: About
},
]
})
在 App.vue 中添加对应的 router-link 标签,router-view 就是我们路由视图的具体显示位置。
<template>
<div id="app">
<router-link to="/">首页</router-link>
<router-link to="/user">用户管理</router-link>
<router-link to="/about">关于我们</router-link>
<router-view>
</router-view></div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
</style>
项目打包命令:
cnpm run build
build 进行中,一般这个过程需要一点点时间,打包完成,可以看到有提示 build complete 完成时候可以在相中发现多了一个 dist 文件夹,里面包括一个 css文件,js 文件和 index.html。生成的项目路径全部是以 / 开头,需放入 web 服务器的根目录才能访问,如果希望使用相对路径则修改:config/index.js里面的 build->assetsPublicPath 将原来的 / 改为 ./ 即可。
14.整合 bootstrap
打开 bootstrap3 起步,在实例精选中找到 入门级模板 后得到其源代码,将其中的重要的 css 与 js 引入项目根目录的 index.html 中
将导航代码拷贝如我们项目的 App.vue ,将所有的 a 标签换成 router-link ,并在所有组件中加入类型 container ,去掉导航的 navbar-fixed-top 类型
<template>
<div id="app">
<nav class="navbar navbar-inverse">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">第一个vue项目</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="active"><router-link to="/">首页</router-link></li>
<li><router-link to="/user">用户管理</router-link></li>
<li><router-link to="/about">关于我们</router-link></li>
</ul>
</div>
</div>
</nav>
<router-view>
</router-view></div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
</style>
效果如下:
路由时传参数
<router-link :to="'/user/'+12">用户管理</router-link>
路由表中指定参数名
{
path: '/user/:id',
name: 'user',
component: User
}
组件页面配置接收参数
<template>
<div class="user container">
<h1>用户管理</h1>
{{id}}
</div>
</template>
<script>
export default {
name: "User",
data() {
return {
id: ""
}
},
created() {
this.id = this.$route.params.id;
}
}
</script>
<style scoped="">
</style>
当路由到某个组件时,由于组件会复用,所以生命周期函数不会再次执行,如果这个组件是模板组件,靠传入不同数据来显示的。那么,可能会发生参数变化了但页面数据却不变化。这时就需要使用路由的两个回调方法。beforeRouteEnter 与 beforeRouteUpdate 方法。前者在进入路由所在组件时(路由发生变化)执行,后者在路由的参数变化时执行在这两个方法里执行刷新数据,两者时机对应两种切换路由操作。(经过实践经验,要两者配合才行)
beforeRouteEnter(to, from, next) {
next((vm) => {
vm.setId(to.params.id);
});
},
beforeRouteUpdate(to, from, next) {
this.setId(to.params.id);
next();
},
发送请求:
npm install vue-resource --save
导入和使用
import VueResource from 'vue-resource'
Vue.use(VueResource)
发送请求:
this.$http.post('action')
.then(function(res){
alert(res.data);
},function(){
alert('false')
});
15.使用 vuex
打开 vuex 官网地址:What is Vuex? | Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
安装 vuex
npm install vuex --save
显式地通过Vue.use() 来使用 Vuex
import Vuex from 'vuex'
Vue.use(Vuex)
没有使用 vuex 前我们父子组件数据传递使用如下方式:
父组件
<template>
<div>
<h1>用户管理{{id}}</h1>
<t-dialog1 :show="show" @update="closeDialog"></t-dialog1>
<button class="showDialog" @click="show=true">显示1</button>
</div>
</template>
<script>
import dialog1 from '@/components/Dialog1.vue'
export default {
name: "User",
components: {
"t-dialog1": dialog1
},
data() {
return {
show: true
}
}, methods: {
closeDialog: function (data) {
this.show = data
}
}
}
</script>
<style scoped="">
</style>
子组件
<template>
<div class="alert alert-success" v-show="show" @click="closDialog">弹窗内容</div>
</template>
<script>
export default {
name: "Dialog1",
props:["show"],
methods:{
closDialog(){
this.$emit("update",false)
}
}
}
</script>
<style scoped="">
</style>
之所以这么麻烦 , 是因为父组件可以通过 props 给子组件传递参数,但子组件内却不能直接修改父组件传过来的参数。
这时候,使用 vuex 就可以比较方便的解决这种问题了:
父组件
<template>
<div>
<h1>用户管理{{id}}</h1>
<t-dialog2></t-dialog2>
<button class="showDialog" @click="$store.state.show=true">显示2</button>
</div>
</template>
<script>
import dialog2 from '@/components/Dialog2.vue'
export default {
name: "User",
components: {
"t-dialog2": dialog2,
},
data() {
return {
}
}
}
</script>
<style scoped="">
</style>
子组件:
<template>
<div class="alert alert-success" v-show="$store.state.show" @click="$store.state.show=false">弹窗内容</div>
</template>
<script>
export default {
name: "Dialog2",
methods:{
}
}
</script>
<style scoped="">
</style>
是不是方便了许多,这就是 vuex 最简单的应用,不要被网上其他教程吓到,vuex 原来可以这么简单 !
只需要在 main.js 中加入
import Vuex from 'Vuex'
Vue.use(Vuex)
var store = new Vuex.Store({//store对象
state:{
show:false
}
})
再然后 , 在实例化 Vue对象时加入 store 对象 :
new Vue({
el: '#app',
router,
store,//使用store
template: '<app>',
components: { App }
})</app>
完成到这一步 , 上述例子中的 $store.state.show 就可以使用了。
16.整合 elementUI
Element,一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库。
安装 element ui
npm install element-ui --save
在main.js中声明element-ui
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
在helloworld.vue中加入
<el-button type="primary">element 按钮</el-button>
安装软件时可能出现安装版本不兼容问题。安装时使用
npm install --save <包名>@版本
如果不知道该包有哪些版本,可以使用
npm view <包名> versions --json