【Vue】Vue2 学习记录
npm和yarn
Yarn是由Facebook、Google、Exponent 和 Tilde 联合推出了一个新的 JS 包管理工具。
Yarn 是为了弥补 npm 的一些缺陷而出现的。
Vue
Vue.js 是什么
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。
与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
- 学习vue
- vue 的指令
- 组件(对UI结构的复用)
- 路由
- Vuex
特性
- 数据驱动视图
- 双向数据绑定
数据驱动视图
https://blog.csdn.net/weixin_44867717/article/details/104856436
vue 会监听数据的变化,自动重新渲染页面的结构。(数据的变化驱动视图的更新)
好处:程序员只管维护好数据,vue 会自动渲染出页面结构。
注意:数据驱动视图是单向的数据绑定。
双向数据绑定
在网页中,form 表单负责采集数据,Ajax 负责提交数据
双向数据绑定可以辅助开发者在不操作 DOM 的情况下,自动把用户在表单中填写的内容同步到数据源中。
好处:开发者不再需要手动操作 DOM 元素来获取表单中最新的值。
MVVM
MVVM 是 vue 实现数据驱动视图和双向数据绑定的核心原理。
- Model(M):普通的 JavaScript 对象,例如 Vue 实例中的 data
- 普通数据
- 当前页面渲染时依赖的数据源
- View(V):视图
- HTML DOM 模板
- 当前页面渲染的 DOM 结构
- ViewModel(VM):Vue实例,MVVM 的核心
- 负责数据和视图的更新
- 它是
Model 数据
和View 视图
通信的桥梁
MVVM 的工作原理
- 当数据源发生变化时,会被 ViewModel 监听到,VM 会根据最新的数据源自动更新页面的结构
- 当表单元素的值发生变化时,也会被 VM 监听到,VM 会把变化过后最新的值自动同步到 Model 数据源中
Vue 的基本使用
<!-- 用 Vue 来控制下面这个 div -->
<div id="app"> <!-- mustache 语法 -->
{{ username }}
{{ message }}
</div>
<!-- 1. 导入 vue.js -->
<script src="./lib/vue.js"></script>
<!-- 2. 创建 Vue 的实例对象 -->
<script>
let vm = new Vue({
el: '#app', // el属性表示当前 Vue 实例要控制页面上哪个区域,属性值为一个选择器
data: { // data 对象就是要渲染的数据
username: 'zhang san',
message: 'Hello Vue!'
}
});
</script>
效果:
以上代码与 MVVM 的对应关系:
浏览器插件
vue 的调试工具,Chrome 和 Firefox 都可安装。
vue 的指令与过滤器
- 指令(Directives)是 vue 为开发者提供的模板语法,用于辅助开发者渲染页面的基本结构。
- vue 中的指令按照不同的用途可以分为如下 6 大类:
- 内容渲染指令
- 属性绑定指令
- 事件绑定指令
- 双向绑定指令
- 条件渲染指令
- 列表渲染指令
内容渲染指令
内容渲染指令用来辅助开发者渲染 DOM 元素的文本内容。常用的内容渲染指令有如下3个:
v-text
{{ }}
v-html
-
v-text
v-text
指令会覆盖元素内部原有的内容。<!-- 用 Vue 来控制下面这个 div --> <div id="app"> <p v-text="username"></p> <!-- username 对应的值渲染到 p 标签中 --> <p v-text="gender">性别</p> <!-- 文本“性别”会被覆盖 --> </div>
<!-- 1. 导入 vue.js --> <script src="./lib/vue.js"></script> <!-- 2. 创建 Vue 的实例对象 --> <script> let vm = new Vue({ el: '#app', // el属性表示当前 Vue 实例要控制页面上哪个区域 data: { // data 对象就是要渲染的数据 username: 'zhang san', gender: '男' } }); </script>
效果:
-
{{ }}
vue 提供的一种语法,专门用来解决 v-text 会覆盖原有内容的问题。这种
{{}}
语法也叫插值表达式,英文名:Mustache。实际开发中用得最多。<!-- 用 Vue 来控制下面这个 div --> <div id="app"> <p v-text="username"></p> <p v-text="gender">性别</p> <hr> <p>用户:{{ username }}</p> <p>性别:{{ gender }}</p> </div>
<!-- 1. 导入 vue.js --> <script src="./lib/vue.js"></script> <!-- 2. 创建 Vue 的实例对象 --> <script> let vm = new Vue({ el: '#app', // el属性表示当前 Vue 实例要控制页面上哪个区域 data: { // data 对象就是要渲染的数据 username: 'zhang san', gender: '男' } }); </script>
效果:
-
v-html
v-text
指令 和{{}}
只能渲染纯文本内容,如果要把包含 HTML 标签的字符串渲染为页面的 HTML 元素,则需要用到v-html
这个指令。<!-- 用 Vue 来控制下面这个 div --> <div id="app"> <p v-text="username"></p> <p v-text="gender">性别</p> <hr> <p>用户:{{ username }}</p> <p>性别:{{ gender }}</p> <hr> <p>{{ info }}</p> <p v-html="info"></p> </div>
<!-- 1. 导入 vue.js --> <script src="./lib/vue.js"></script> <!-- 2. 创建 Vue 的实例对象 --> <script> let vm = new Vue({ el: '#app', // el属性表示当前 Vue 实例要控制页面上哪个区域 data: { // data 对象就是要渲染的数据 username: 'zhang san', gender: '男', info: '<strong style="color: darkred">这是一段信息</strong>' } }); </script>
效果:
属性绑定指令
注意:
{{}}
只能用在元素的内容节点中,不能用在元素的属性节点。
如果需要为元素的属性动态绑定值,则需要用到属性绑定指令 v-bind
。
示例如下:
<div id="app">
<input type="text" v-bind:placeholder="tips">
<p>
<!-- `v-bind:` 可以简写为 `:` -->
<img :src="img" alt="" height="100px">
</p>
</div>
<script src="./lib/vue.js"></script>
<script>
let vm = new Vue({
el: '#app', // el属性表示当前 Vue 实例要控制页面上哪个区域,属性值为一个选择器
data: { // data 对象就是要渲染的数据
tips: '请输入内容',
img: 'https://cn.vuejs.org/images/logo.svg'
}
});
</script>
效果:
说明
在 vue 提供的模板渲染语法中,除了支持绑定简单的数据值之外,还支持 js 表达式的运算。
<div id="app">
<input type="text" v-bind:placeholder="tips">
<p>
<img v-bind:src="img" alt="" height="100px">
</p>
<p>1+2 = {{ 1+2 }}</p>
<p>{{ text }} 反转后: {{ text.split('').reverse().join('') }}</p>
<div v-bind:id="'box-' + index">这是盒子{{ index }}</div>
</div>
<script src="./lib/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
tips: '请输入内容',
img: 'https://cn.vuejs.org/images/logo.svg',
text: '倒过来念的是猪',
index: '1'
}
});
</script>
效果:
事件绑定指令
vue 提供了事件绑定指令 v-on
,用来辅助开发者为 DOM 元素绑定事件。
注意:原生 DOM 对象有 onclick
、oninput
、onkeyup
等原生事件,替换为vue的事件绑定形式后,分别为:v-on:click
、v-on:input
、v-on:keyup
<div id="app">
<p>count 的值为:{{ count }}</p>
<!-- 给按钮绑定了点击事件 -->
<button v-on:click="add"> +1 </button>
<button v-on:click="sub"> -1 </button>
</div>
编写事件处理函数:
<script>
let vm = new Vue({
el: '#app',
data: {
count: 0
},
methods: { // methods 中可以定义事件函数
add: function() {
console.log('add');
},
sub() { //简写形式
console.log('sub');
}
}
})
</script>
利用 this 访问 Vue 实例中的数据:
<script>
let vm = new Vue({
el: '#app',
data: {
count: 0
},
methods: { // methods 中可以定义事件函数
add() {
// console.log(vm); //一个Vue实例
// console.log(vm === this); //true
this.count++;
},
sub() {
this.count--;;
}
}
})
</script>
console.log(vm) 可以看到如下内容
如果想给事件处理函数传参,只需在函数名后面加上()
:
<div id="app">
<p>count 的值为:{{ count }}</p>
<button @click="add(2)"> +2 </button>
<button @click="sub(2)"> -2 </button>
</div>
v-on:event
可以简写为@event
事件对象 $event
利用事件对象的 target 属性,可以获取触发该事件的 DOM 元素
存在的问题:如果绑定事件时传入了参数,就接收不到事件对象了
解决方案:vue 提供了内置变量 $event
,它就是原生 js 的事件对象。(参数的顺序没有要求)
事件修饰符
在事件处理函数中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。因此,vue 提供了事件修饰符的概念,来辅助程序员更方便的对事件的触发进行控制。
常用的5个事件修饰符如下:
事件修饰符 | 说明 |
---|---|
.prevent | 阻止默认行为(例如:阻止a标签跳转、阻止表单提交等) |
.stop | 阻止事件冒泡 |
.capture | 以捕获模式触发当前的事件处理函数 |
.once | 绑定的事件只触发一次 |
.self | 只有在 event.target 是当前元素自身时触发事件处理函数 |
原生写法:
<div id="app">
<a href="https://www.baidu.com" @click="showInfo">百度</a>
</div>
let vm = new Vue({
el: '#app',
methods: {
showInfo(e) {
e.preventDefault(); //阻止默认行为,在此处即为阻止a标签的跳转
console.log('a标签被点击了');
}
}
})
vue 写法:
<div id="app">
<a href="https://www.baidu.com" @click.prevent="showInfo">百度</a>
</div>
let vm = new Vue({
el: '#app',
methods: {
showInfo() {
console.log('a标签被点击了');
}
}
})
按键修饰符
在监听键盘事件时,我们经常需要判断详细的按键。此时,可以为键盘相关的事件添加按键修饰符
<div id="app">
<input type="text" @keyup.enter="show" @keyup.esc="clear">
</div>
<script src="./lib/vue.js"></script>
<script src="./lib/jquery-3.6.0.min.js"></script>
<script>
let vm = new Vue({
el: '#app',
methods: {
show(e) {
let text = $(e.target).val();
console.log(text);
},
clear(e) {
$(e.target).val('');
},
}
})
</script>
双向绑定指令
vue 提供了双向数据绑定指令 v-model
,让开发者能够不操作 DOM 就可以获取表单中的数据。
v-model
指令底层会判断表单元素的类型(输入框 text、单选框 radio、复选框 checkbox 等),然后根据表单元素的类型选取正确的方法来更新元素。
<div id="app">
<p>用户名:{{ username }}</p>
<p><input type="text" v-model="username"> v-model</p>
<p><input type="text" :value="username"> v-bind</p>
<hr>
<select v-model="city">
<option value="bj">北京</option>
<option value="sh">上海</option>
<option value="gz">广州</option>
<option value="">请选择</option>
</select>
</div>
<script src="./lib/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
username: 'xiaoming',
city: '',
},
})
</script>
v-model 指令的修饰符
为了方便对用户输入的内容进行处理,vue 为 v-model
指令提供了 3 个修饰符:
修饰符 | 作用 | 示例 |
---|---|---|
.number | 将用户的输入转为数值类型 | <input v-model.number="age"> |
.trim | 过滤用户输入的收尾空白字符 | <input v-model.trim="msg"> |
.lazy | 在 ‘change’ 时而非 ‘input’ 时更新 | <input v-model.lazy="msg"> |
示例:
<div id="app">
<p>
<input type="text" v-model.number="n1"> +
<input type="text" v-model.number="n2"> =
<span>{{ n1 + n2 }}</span>
</p>
</div>
<script src="./lib/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
n1: 1,
n2: 2
},
})
</script>
<div id="app">
<p>
<input type="text" v-model.trim="username">
<button @click="showUsername">获取用户名</button>
</p>
</div>
<script src="./lib/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
username: ''
},
methods: {
showUsername() {
console.log(`用户名:${this.username}`);
}
}
})
</script>
条件渲染指令
条件渲染指令用来辅助开发者按需控制 DOM 的显示与隐藏。
v-if
v-show
示例:
<div id="app">
<p v-if="flag">这是 v-if 控制的元素</p>
<p v-show="flag">这是 v-show 控制的元素</p>
<p><button @click="toggle">切换</button></p>
</div>
<script src="./lib/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
flag: true,
},
methods: {
toggle() {
this.flag = !this.flag;
}
}
})
</script>
两个指令的区别:
v-show
:动态地给 DOM 元素添加/移除display: none
的样式,来实现元素的隐藏/显示- 如果需要频繁切换元素的显示状态,v-show 的性能会更好
v-if
:每次地向 DOM 树内添加或移除元素,来实现元素的显示或隐藏- v-if更加灵活
- 实际开发中,大多使用 v-if
v-if 相关的指令
v-else-if
v-else
上面两个指令都需要配合 v-if
一起使用,否则无法被识别。
示例:
<div id="app">
<p v-if="grade === 'A'">优</p>
<p v-else-if="grade === 'B'">良</p>
<p v-else-if="grade === 'C'">中</p>
<p v-else>差</p>
</div>
<script src="./lib/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
grade: 'A',
}
})
</script>
列表渲染指令
vue 提供了列表渲染指令 v-for
,用来辅助开发者基于一个数组来循环渲染一个列表结构。
v-for
指令需要使用 item in items
形式的特殊语法,其中:
- items 是待循环的数组
- item 是数组中的某一项
v-for
指令还支持一个可选的参数——当前项的索引。语法格式为 (item,index) in items
。
示例:
<div id="app">
<table border="1px">
<thead>
<th>index</th>
<th>id</th>
<th>name</th>
</thead>
<tbody>
<!-- <tr v-for="item in ajax_list"> -->
<tr v-for="(item,index) in ajax_list">
<td>{{ index }}</td>
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
</tr>
</tbody>
</table>
</div>
<script src="./lib/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
ajax_list: [
{ id: '001', name: '张三'},
{ id: '002', name: '李四'},
{ id: '103', name: '王五'},
{ id: '104', name: '小明'},
{ id: '405', name: '小红'},
]
}
})
</script>
注意:v-for
中的 item 和 index 都是形参,可以根据需要重命名。
v-for
中的 key 属性(https://www.zhihu.com/question/61064119)- 在写 v-for 的时候,最好给元素加上一个 key 属性
- key 属性可以提高渲染性能、避免数据混乱的情况出现
- key 的值必须具有唯一性(与 item 能够一一对应)
- key 的值需要为
string/number
类型 - index 的值不应拿来做 key 的值
<tbody>
<tr v-for="(item,index) in ajax_list" :key="item.id">
<td>{{ index }}</td>
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
</tr>
</tbody>
<script src="./lib/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
ajax_list: [
{ id: '001', name: '张三'},
{ id: '002', name: '李四'},
{ id: '103', name: '王五'},
{ id: '104', name: '小明'},
{ id: '405', name: '小红'},
]
}
})
</script>
过滤器 Filters
Vue 3 中已废弃了过滤器。简单了解即可。
vue 允许开发者自定义过滤器,可被用于一些常见的文本格式化。
过滤器可以用在两个地方:插值表达式 和 v-bind
。
过滤器应该被添加在 JavaScript 表达式的尾部,由管道符 |
表示:
<!-- 在双花括号中 -->
{{ message | capitalize }}
<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>
示例:
<div id="app">
<p>message 的值为:{{ message | cap }}</p>
</div>
<script src="./lib/vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data: {
message: 'hello,vue.js'
},
filters: { //在这个节点下定义过滤器函数
cap(val) {
// 过滤器中需要返回值
// console.log(val);
return val.substring(0,1).toUpperCase() + val.substring(1);
}
}
})
</script>
注意事项:
- 过滤器本质是一个函数,需要定义在 Vue 示例的 filters 节点下
- 过滤器函数中一定要有返回值
- 在过滤器的形参中,可以获取到 管道符
|
前面待处理的值
全局过滤器
在 filters 节点下定义的过滤器称为局部过滤器,它只能在当前 Vue 实例所控制的 el 区域内使用。
如果希望在多个 Vue 实例之间共享过滤器,可以定义全局过滤器。
在创建 Vue 实例之前全局定义过滤器:
Vue.filter('toUpper', function (val) {
return val.toUpperCase();
})
new Vue({
// ...
})
当全局过滤器和局部过滤器重名时,会采用局部过滤器。
实际开发中,使用全局过滤器更多一些
串联调用
<p>{{ message | filterA | filterB }}</p>
在这个例子中,filterA
被定义为接收单个参数的过滤器函数,表达式 message
的值将作为参数传入到函数中。然后继续调用同样被定义为接收单个参数的过滤器函数 filterB
,将 filterA
的结果传递到 filterB
中。
更多参数
<p>{{ message | filterA('arg1', arg2) }}</p>
<script src="./lib/vue.js"></script>
<script>
Vue.filter('filterA', function (val, ar1, arg2) {
//return ...
})
new Vue({
// ...
})
</script>
这里,filterA
被定义为接收三个参数的过滤器函数。
其中 message
的值作为第一个参数,普通字符串 'arg1'
作为第二个参数,表达式 arg2
的值作为第三个参数。
侦听器 watch
侦听器让开发者能够侦听数据的变化,从而针对数据的变化作出特定的响应。
<div id="app">
<input type="text" v-model="username">
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
username: ''
},
watch: { // 侦听器都应定义在这里
// 侦听器本质上是一个函数,如果 `username` 发生改变,这个函数就会运行
// 新值在前,旧值在后
username(newVal, oldVal) {
console.log('监听中。。。', newVal, oldVal);
}
}
})
</script>
对象格式的侦听器
-
函数格式的侦听器
- 无法在刚进入页面的时候,自动触发
- 当侦听的是一个对象时,如果对象中的属性发生了变化,不会触发侦听器
-
对象格式的侦听器
-
可以通过 immediate 选项,让侦听器立即被调用
<div id="app"> <input type="text" v-model="username"> </div> <script> let vm = new Vue({ el: '#app', data: { username: 'admin', }, watch: { // 侦听器都应定义在这里 username: { handler(newVal, oldVal) { console.log(newVal, oldVal); }, immediate: true, // 默认值为false } } }) </script>
-
可以通过 deep 选项,让侦听器深度监听对象中属性的变化
<div id="app"> <input type="text" v-model="userinfo.username"> </div> <script> let vm = new Vue({ el: '#app', data: { userinfo: { username: 'admin', password: '123456' } }, watch: { // 侦听器都应定义在这里 userinfo: { handler(newVal, oldVal) { console.log(newVal, oldVal); //是同一个对象 }, deep: true, // 开启深度侦听 } } }) </script>
-
侦听对象的单个属性
<div id="app">
<input type="text" v-model="userinfo.username">
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
userinfo: {
username: 'admin',
password: '123456'
}
},
watch: { // 侦听器都应定义在这里
//必须要加单引号
'userinfo.username'(newVal, oldVal) {
console.log(newVal, oldVal);
}
}
})
</script>
计算属性 computed
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如:
<div id="example"> {{ message.split('').reverse().join('') }} </div>
在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量
message
的翻转字符串。当你想要在模板中的多处包含此翻转字符串时,就会更加难以处理。所以,对于任何复杂逻辑,你都应当使用计算属性。
计算属性指的是通过一系列运算之后,最终得到的一个属性值。
- 定义时是一个函数
- 函数的返回值会作为一个属性被绑定到当前 Vue 实例上
- 你可以像使用
data
中的 property 一样使用计算属性
这个动态计算出来的属性值可以被 模板结构 或 methods 中使用。示例代码如下:
<div id="app">
<p>R: <input type="text" v-model.number="color.r"></p>
<p>G: <input type="text" v-model.number="color.g"></p>
<p>B: <input type="text" v-model.number="color.b"></p>
<div id="colorBox" :style="`background-color: ${rgb};`">
{{ rgb }}
</div>
<p><button @click="print">输出rgb</button></p>
</div>
<script>
let vm = new Vue({
el: '#app',
data: {
color: { r: 0, g: 0, b: 0 },
},
methods: {
print() {
console.log(this.rgb);
}
},
computed: { // 计算属性都在这里定义
rgb() { // 一个函数
return `rgb(${this.color.r}, ${this.color.g}, ${this.color.b})`;
}
}
})
</script>
Vue 知道计算属性
vm.rgb
依赖于vm.color
,当vm.color
发生改变时,vm.rgb
也会更新。
axios
axios 是一个专注于网络数据请求的库
用 axios 发起简单的 get 请求:
let result = axios({ //发送请求
url: './finduser.json',
method: 'get',
})
console.log(result); // 一个 Promise 对象,其中的`data`属性值是真实的返回数据
result.then(function (result) {
console.log(result.data);
})
传参:
axios({
url: 'xxx',
method: 'get',
params: {}, // url 中的参数
data: {} // 请求体中的参数
})
除了直接调用 axios()
之外,还能以 axios.get()
、axios.post()
等方式发起不同类型的请求:
// get 请求
axios.get('/user', {
params: {
id: 12345
}
}).then(function (response) {
console.log(response);
})
// post 请求
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
}).then(function (response) {
console.log(response);
})
响应结构
某个请求的响应包含以下信息
{
// `data` 由服务器提供的响应
data: {},
// `status` 来自服务器响应的 HTTP 状态码
status: 200,
// `statusText` 来自服务器响应的 HTTP 状态信息
statusText: 'OK',
// `headers` 服务器响应的头
headers: {},
// `config` 是为请求提供的配置信息
config: {},
// `request` is the request that generated this response
// It is the last ClientRequest instance in node.js (in redirects)
// and an XMLHttpRequest instance the browser
request: {}
}
vue-cli
单页面应用程序
单页面应用程序 (Single Page Application, SPA) ,顾名思义,指的是一个 Web 应用中只有唯一的一个HTML页面,所有的功能与交互都在这唯一的一个页面内完成。
什么是 vue-cli
vue-cli
是Vue.js 开发的标准工具。它简化了程序员基于 webpack 创建工程化的 Vue 项目的过程。
Vue CLI 致力于将 Vue 生态中的工具基础标准化。它确保了各种构建工具能够基于智能的默认配置即可平稳衔接,这样开发者可以专注在撰写应用上,而不必花好几天去纠结配置的问题。
安装
vue-cli 是npm 上的一个全局包,使用如下命令,即可把它安装到自己的电脑上:
npm install -g @vue/cli
# OR
yarn global add @vue/cli
安装之后,你就可以在命令行中访问 vue
命令。你可以通过简单运行 vue
,看看是否展示出了一份所有可用命令的帮助信息,来验证它是否安装成功。
你还可以用这个命令来检查其版本是否正确:
vue --version
# 或者
vue -V
如需升级全局的 Vue CLI 包,请运行:
npm update -g @vue/cli
# 或者
yarn global upgrade --latest @vue/cli
创建项目
运行以下命令来创建一个新项目:
vue create 项目名
运行一下项目
查看项目根目录的 package.json
,可以看到 vuecli 创建好的一些命令:
开发模式 (development) :
npm run serve
# OR
yarn serve
生产模式 (production) :
npm run build
# OR
yarn build
项目目录结构
public -> index.html
是项目中唯一的一个页面。
src 目录的结构:
名称 | 说明 |
---|---|
assets 目录 | 存放项目中用到的静态资源,如:css 文件、图片等 |
components 目录 | 存放开发者封装的一些组件 |
main.js | 项目的入口文件,项目运行时会先执行 main.js |
App.vue | 项目的根组件 |
vue 项目的运行流程
在工程化的项目中,vue要做的事情很单纯:通过 main.js
把 App.vue
渲染到 index.html
的指定区域中。
App.vue
用来编写待渲染的模板结构index.html
中需要预留一个 el 区域main.js
把App.vue
渲染到了index.html
预留的区域中
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div> <!-- 此div将会被替换 -->
<!-- built files will be auto injected -->
</body>
</html>
<template>
<div>
<h2>hello, world</h2>
<h3>by vue</h3>
</div>
</template>
// 导入 vue 包,得到 Vue 构造函数
import Vue from 'vue'
// 导入根组件 App.vue,将来要把 App.vue 中的模板结构渲染到 html 页面中
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
// 告诉 Vue 实例,App.vue 要渲染到哪里
el: '#app',
// 把 render 函数指定的组件渲染到 html 页面中
render: h => h(App),
})
/* 另一种写法
new Vue({
render: h => h(Test),
}).$mount('#app')
*/
el 和 $mount 在使用效果上没有任何区别,都是为了将实例化后的 Vue 挂载到指定的 dom 元素中。
vue-组件
vue 中的组件化开发
组件化开发:
根据封装的思想,把页面上可重用的 UI 结构封装为组件,从而方便项目的开发和维护。
vue 是一个支持组件化开发的前端框架。
vue 中规定:组件的后缀名是 .vue
。之前接触到的 App.vue
文件就是一个 vue 的组件。
vue 组件的组成部分
每个 .vue
组件都由 3 部分构成:
- template:组件的模板结构
- script:组件的 js 行为
- style:组件的样式
<template>
<div class="box">
<h2>自定义的组件 Test.vue</h2>
<h3>from {{ username }}</h3>
</div>
</template>
<script>
// 默认导出。这是固定写法
export default {
// 组件中的 data 是一个函数,返回值是一个数据对象
data() {
return {
username: 'skyey'
}
},
}
</script>
<style>
.box {
background-color: antiquewhite;
}
</style>
注意事项:
- 为什么 data 选项变成了一个函数
- template 节点下必须仅有一个 DOM 元素,如果有多个则会报错。
在组件中定义 methods
在组件中定义 methods 和之前在 Vue 实例中基本没有区别:
<template>
<div class="box">
<h2>自定义的组件 Test.vue</h2>
<h3>from {{ username }}</h3>
<p>
<input type="text" placeholder="请输入用户名" v-model="input">
<button @click="changeUsername">修改用户名</button>
</p>
</div>
</template>
<script>
// 默认导出。这是固定写法
export default {
data() { // 组件中的 data 是一个函数,返回值是一个数据对象
return {
username: 'skyey',
input: ''
}
},
methods: {
changeUsername() {
console.log(this); // 这里的 this 是 VueComponent 实例
this.username = this.input;
this.input = '';
}
}
}
</script>
<style>
.box {
background-color: antiquewhite;
}
</style>
值得注意的是,这里的
this
指向的是当前组件的实例
除了 methods
之外,过滤器、侦听器、计算属性的定义和用法都和在 Vue 实例中的基本一致。
在组件中使用 less 语法
在 style
元素中加入 lang
属性:
<style lang="less">
.box {
background-color: antiquewhite;
h3 {
color: #8a8a8a;
}
}
</style>