Vue2基础
大家好呀,我是小笙!我来和大家简述一些我的笔记
Vue2
基本介绍
Vue (Vue.js 的简称)是一个前端框架, 易于构建用户界面
Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或项目整合
MVVM思想
M∶即 Model,模型,包括数据和一些基本操作
V∶即 View,视图,页面渲染结果
VM∶即 View-Model,模型与视图间的双向操作(无需开发人员干涉)
快速入门Hello,Vue
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="./Vue/vue.js"></script>
</head>
<body>
<div id="app">
<!--
{{ }} 插值表达式
会到data数据池中去匹配数据, 如果匹配上, 就进行替换
如果没有匹配上, 就是输出空 -->
{{message}}{{name}}
</div>
<script type="text/javascript">
let vm = new Vue({
el:"#app", // 绑定id等于app的控件
data:{ // data:{} 表示数据池(model),以 k-v 形式设置
message:"Hello,",
name: "Vue!"
}
})
</script>
</body>
</html>
注意:注意代码顺序,要求 div 在前,script 在后,否则无法绑定数据
数据单向渲染 v-bind
v-bind 是数据单向渲染: data 数据池绑定的数据变化,会影响 view
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<h1>{{message}}</h1>
<!--
1. 使用插值表达式引用 data 数据池数据是在标签体内 <h1></h1>
2. 如果是在标签/元素 的属性上去引用 data 数据池数据时,不能使用插值表达式
-->
<img v-bind:src="img_src" v-bind:width="img_width">
<!-- v-bind 简写形式就是一个冒号(:) -->
<img :src="img_src":width="img_width">
</div>
</body>
<script type="text/javascript" src="./Vue/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
message:"数据单向渲染 ",
img_src:"imgs/1.jpg",
img_width:"200px"
}
})
</script>
</html>
数据双向绑定 v-model
v-model 是数据的双向渲染
- data 数据池绑定的数据变化,会影响 view 【底层的机制是 Data Bindings】
- view 关联的的元素值变化, 会影响到 data 数据池的数据【底层机制是 Dom Listeners】
案例:需求在输入框中输入信息,会更新到相应绑定的位置
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<div>{{message}}</div>
<!-- 可以将 v-model:value="hobby" 简写成 v-model="hobby" -->
<input type="text" v-model:value="hobby"><br/>
<!-- 可以将 v-bind:value="hobby" 简写成 :value="hobby" -->
<input type="text" v-bind:value="hobby"><br/>
<span>您输入的爱好是:</span>{{hobby}}
</div>
</body>
<script type="text/javascript" src="./Vue/vue.js"></script>
<script type="text/javascript">
let vm = new Vue({
el:"#app",
data:{
message:"输入你的爱好:",
hobby: ""
},
})
</script>
</html>
事件绑定 v-on
使用 v-on 进行事件处理,比如: v-on:click 表示处理鼠标点击事件
事件调用的方法定义在 vue 对象声明的 methods 节点中
演示 Vue 事件绑定操作
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>事件绑定</title>
</head>
<body>
<div id="app">
<p>{{message}}</p>
<!-- v-on:click 表示我们要给 button 元素绑定一个 click 的事件 -->
<button v-on:click="hi()">按钮1</button>
<button v-on:click="cry()" >按钮2</button>
<!-- 如果方法不需要传递参数,可以省略() -->
<button v-on:click="hi">按钮3</button>
<!-- v-on:click 可以简写@, 但是需要浏览器支持 -->
<button @click="cry">按钮4</button><strong></strong>
</div>
</body>
<script type="text/javascript" src="Vue/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
message:"事件绑定"
},
// hi() 表示绑定的方法, 在方法池 methods{} 定义
methods:{
hi(){
console.log("hi...");
},
cry(){
console.log("cry...");
}
}
})
</script>
</html>
事件绑定练习
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<button v-on:click="add">点击增加+1</button>
<button v-on:click="sum += 2">点击增加+2</button><hr>
<span>一共被点击{{sum}}次</span>
</div>
</body>
<script type="text/javascript" src="./Vue/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
sum : 0
},
methods:{
add(){
this.sum += 1;
console.log(this.sum);
}
}
})
</script>
</html>
修饰符
修饰符 (Modifiers) 是以(.)指明的后缀,指出某个指令以特殊方式绑定
阻止事件原本的默认行为
事件修饰符
- .stop 阻止事件继续传播
- .prevent 阻止标签默认行为
- .capture 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理
- .self 只当在 event.target 是当前元素自身时触发处理函数
- .once 事件将只会触发一次
- .passive 告诉浏览器你不想阻止事件的默认行为
键盘事件的修饰符
项目经常需要监听一些键盘事件来触发程序的执行,而 Vue 中允许在监听的时候添 加关键修饰符
双向绑定的修饰符
自动过滤用户输入的首尾空格
代码示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<!--
1. 修饰符用于指出一个指令应该以特殊方式绑定。
2. v-on:submit.prevent 的.prevent 修饰符表示阻止表单提交的默认行为
-->
<form action="http://www.baidu.com" v-on:submit.prevent="onMySubmit">
妖怪名: <input type="text" v-model="monster.name"><br/>
<button type="submit">注册</button>
</form>
<button v-on:click.once="onMySubmit">点击一次</button><br/>
<!-- 键盘事件的修饰符 -->
<input type="text" v-model="monster.name" v-on:keyup.enter="onMySubmit">
<input type="text" v-model="monster.name" v-on:keyup.down="onMySubmit">
</div>
</body>
<script type="text/javascript" src="./Vue/vue.js"></script>
<script type="text/javascript">
let vm = new Vue({
el:"#app",
data:{
monster:{
},
},
methods:{
onMySubmit() {
if(this.monster.name){
console.log(this.monster.name);
location.href="http://www.baidu.com";
}else{
alert("没有输入信息!");
return false;
}
}
}
})
</script>
</html>
条件渲染 v-if v-show
v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 true 值的时候被渲染,也可以用 v-else 添加一个else块
v-show 根据条件展示元素,不同的是带有 v-show 的元素始终会被渲染并保留在DOM中,v-show 只是简单地切换元素的 CSS 属性 display
代码示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<input type="checkbox" v-model="sel">是否同意条款[v-if v-show实现]
<!-- v-if/v-else 会根据返回的值,来决定是否动态创建对应的子组件<h1> -->
<h1 v-if="sel">你同意条款</h1>
<h1 v-else>你不同意条款</h1>
<!-- v-show的使用 -->
<h1 v-show="sel">你同意条款</h1>
<h1 v-show="!sel">你不同意条款</h1>
</div>
</body>
<script type="text/javascript" src="./Vue/vue.js"></script>
<script type="text/javascript">
let vm = new Vue({
el:"#app",
data:{
sel:false
}
})
</script>
</html>
v-if 和 v-show 的区别
v-if 会确保在切换过程中,条件块内的事件监听器和子组件能动态的销毁和重建
v-show 机制相对简单, 不管初始条件是什么,元素总是会被渲染,并且只是对 CSS 进行切换
如果要频繁地切换,建议使用 v-show ;如果运行时条件很少改变,使用 v-if 较好
列表渲染 v-for
演示列表渲染使用使用(v-for)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<li v-for="i in 4">{{i}}</li>
<li v-for="(i,index) in 3">{{i}}-{{index}}</li>
<table width="400px" border="1px">
<!-- 遍历数组monsters,数据存放在数据池 -->
<tr v-for="(monster,index) in monsters">
<td>{{index+1}}</td>
<td>{{monster.name}}</td>
<td>{{monster.age}}</td>
</tr>
</table>
<br/>
<table width="400px" border="1px">
<!-- 遍历数组monsters,数据存放在数据池 -->
<tr>
<th>id</th>
<th>name</th>
<th>age</th>
<th>score</th>
</tr>
<tr v-for="student in students" style="text-align: center;">
<td>{{student.id}}</td>
<td>{{student.name}}</td>
<td>{{student.age}}</td>
<td>{{student.score}}</td>
</tr>
</table>
</div>
</body>
<script type="text/javascript" src="./Vue/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
monsters:[
{name:"牛魔王",age:800},
{name:"黑山老妖",age:900},
{name:"红孩儿",age:200}
],
students:[
{id:1,name:"jack",age:20,score:90},
{id:3,name:"mary",age:20,score:60}
]
}
})
</script>
</html>
组件化编程
在大型应用开发的时候,页面可以划分成很多部分,往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航
所以我们会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发
- 组件(Component) 是 Vue.js 最强大的功能之一
- 组件也是一个Vue实例,也包括∶ data、methods、生命周期函数等
- 组件渲染需要 html模板,所以增加了template 属性
- 对于全局组件,任何vue 实例都可以直接在 HTML 中通过组件名称来使用组件
- data 是一个函数,不再是一个对象, 这样每次引用组件都是独立的对象/数据
需求如下, 点击一个按钮, 可以显示点击的次数
全局组件化
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<counter></counter><br/><br/>
<counter></counter><br/><br/>
<counter></counter><br/><br/>
</div>
</body>
<script type="text/javascript" src="./Vue/vue.js"></script>
<script>
// 要把组件视为一个 Vue 实例,也有自己的数据池和方法池
Vue.component("counter",{
template: `<button v-on:click="click()">点击次数= {{count}} 次【全局组件化】 </button>`,
data(){
// 对于组件,我们的数据池的数据,是使用函数/方法返回
// [目的是为 了保证每个组件的数据是独立], 不能使用原来的方式
return {
count:10
}
},
methods:{
click(){
this.count++
}
}
})
// 组件定义需要放置在 new Vue() 前,否则组件注册会失败
new Vue({
el:"#app",
});
</script>
</html>
局部组件化
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
<localcounter></localcounter><br/><br/>
</div>
<localcounter></localcounter><br/><br/>
</body>
<script type="text/javascript" src="./Vue/vue.js"></script>
<script>
// 要把组件视为一个 Vue 实例,也有自己的数据池和方法池
const Counter_Components = {
template: `<button v-on:click="click()">点击次数= {{count}} 次【全局组件化】 </button>`,
data(){
// 对于组件,我们的数据池的数据,是使用函数/方法返回
// [目的是为 了保证每个组件的数据是独立], 不能使用原来的方式
return {
count:10
}
},
methods:{
click(){
this.count++
}
}
}
new Vue({
el:"#app",
components:{
'localcounter':Counter_Components,
}
});
</script>
</html>
生命周期和监听函数(钩子函数)
Vue 实例有一个完整的生命周期,也就是说从开始创建、初始化数据、编译模板、挂载 DOM、渲染-更新-渲染、卸载等一系列过程,我们称为 Vue 实例的生命周期
钩子函数(监听函数): Vue 实例在完整的生命周期过程中(比如设置数据监听、编译模板、将实例挂载到 DOM 、在数据变化时更新 DOM 等), 也会运行叫做生命周期钩子的函数;钩子函数的作用就是在某个阶段, 给程序员一个做某些处理的机会
生命周期
- new Vue() 创建一个 Vue 的实例对象,此时就会进入组件的创建过程
- Init Events & Lifecycle 初始化组件的事件和生命周期函数
- beforeCreate 组件创建之后遇到的第一个生命周期函数,这个阶段 data 和 methods 以及 dom 结构都未被初始化,也就是获取不到 data 的值,不能调用 methods 中的函数
- Init injections & reactivity 这个阶段中, 正在初始化 data 和 methods 中的方法
- created - 这个阶段组件的 data 和 methods 中的方法已初始化结束,可以访问,但是 dom 结构未初始化,页面未渲染 ,在这个阶段,经常会发起 Ajax 请求
- 编译模板结构(在内存)
- beforeMount 当模板在内存中编译完成,此时内存中的模板结构还未渲染至页面上,看不到真实的数据
- Create vm.$el and replace ‘el’ with it 这一步,再在把内存中渲染好的模板结构替换至真实的 dom 结构也就是页面上
- mounted 此时,页面渲染好,用户看到的是真实的页面数据, 生命周期创建阶段完毕,进入到了运行中的阶段
- 生命周期运行中
10.1 beforeUpdate 当执行此函数,数据池的数据新的,但是页面是旧的
10.2 Virtual DOM re-render and patch 根据最新的 data 数据,重新渲染内存中的模板结构,并把渲染好的模板结构,替换至页面上
10.3 updated 页面已经完成了更新,此时,data 数据和页面的数据都是新的 - beforeDestroy 当执行此函数时,组件即将被销毁,但是还没有真正开始销毁,此时组件的 data、methods
数据或方法 还可被调用 - Teardown…注销组件和事件监听
- destroyed 组件已经完成了销毁
代码实例-展示 Vue 实例生命周期和钩子函数执行时机
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>生命周期和监听函数</title>
</head>
<body>
<div id="app">
<span id="span">num={{num}}</span><br>
<button v-on:click="click()">点赞!</button>
<h1>{{name}}有{{num}}次点赞!</h1>
</div>
</body>
<script type="text/javascript" src="./Vue/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
name:"jack",
num:0
},
methods:{
click(){
this.num++
}
},
// 1.组件创建之后遇到的第一个生命周期函数,这个阶段 data 和 methods 以及 dom
// 结构都未被初始化,也就是获取不到 data 的值,不能调用 methods 中的函数
beforeCreate() {
console.log("=========beforeCreate========");
// Vue实例的数据和方法没有创建
console.log(this.num); // undefined
// 页面已经被加载,但是数据没有被渲染
console.log(document.getElementById("span").innerText); // num={{num}}
},
// 2.这个阶段组件的 data 和 methods 中的方法已初始化结束,可以访问,
// 但是 dom 结构未初始化,页面未渲染 ,在这个阶段,经常会发起 Ajax 请求
created() {
console.log("=========created========");
// Vue实例的数据和方法已经被加载到内存
console.log(this.num); // 0
// 页面已经被加载,但是数据没有被渲染
console.log(document.getElementById("span").innerText);// num={{num}}
},
// 3.当模板在内存中编译完成,此时内存中的模板结构还未渲染至页面上,
// 看不到真实的数据
beforeMount() {
console.log("=========beforeMount========");
// Vue实例的数据和方法已经被加载到内存
console.log(this.num); // 0
// 页面已经被加载,但是数据没有被渲染
console.log(document.getElementById("span").innerText);// num={{num}}
},
// 4.此时,页面渲染好,用户看到的是真实的页面数据, 生命周期创建阶段完毕,
// 进入到了运行中的阶段
mounted() {
console.log("=========mounted========");
// Vue实例的数据和方法已经被加载到内存
console.log(this.num); // 0
// 页面已经被加载,但是数据没有被渲染
console.log(document.getElementById("span").innerText);// num=0
},
// 点击一次
// 当执行此函数,数据池的数据新的,但是页面是旧的
beforeUpdate() {
console.log("=========beforeUpdate========");
console.log(document.getElementById("span").innerText);// num=0
},
// 页面已经完成了更新,此时,data 数据和页面的数据都是新的
updated() {
console.log("=========updated========");
console.log(document.getElementById("span").innerText);// num=1
}
})
</script>
</html>
Vue2 脚手架模块化开发
npm 和 cnpm 的区别
- 两者之间只是 node 中包管理器的不同, 都可以使用
- npm 是 node 官方的包管理器;cnpm 是个中国版的 npm,是淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm
- 如果因为网络原因无法使用 npm 下载,那 cnpm 这个就派上用场了
- 小结: npm 和 cnpm 只是下载的地址不同,npm 是从国外下载东西,cnpm 是从国内下载东西
脚手架生成文件目录分析
案例:输入hello跳转到该页面
<!-- 被Vue实例绑定的页面 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>vue_project</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
创建Vue对象实例,分别做了三件事
- 挂载到首页面(id=app)
- router路由的访问
- 初始化模板和组件渲染到首页面
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App' // import App from './App.vue'
import router from './router'// import router from './router/index.js
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router, // router: router
components: { App }, // components: {'App':App}
template: '<App/>'
})
router路由的访问
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Hello from '@/components/Hello';
Vue.use(Router)
export default new Router({
routes: [
{
path: '/hello', // 路由路径
name: 'Hello',
component: Hello
}
]
})
<template>
<h3>Hello,mary</h3>
</template>
<script>
export default {
name: "Hello"
}
</script>
<style scoped>
</style>
初始化模板和组件渲染到首页面
<template>
<div id="app">
<img src="./assets/logo.png">
<!--将路由后的页面/视图渲染到这里-->
<router-view/>
</div>
</template>
<script>
export default {
name: 'App'
}
</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>
ElementUI
ElementUI 是组件库,网站快速成型工具
注意:Vue2 -> ElementUI Vue3 -> ElementPlus
命令: npm i element-ui@2.12.0
在main.js中引入包
// 引入ElementUI组件库,就可以使用ElementUI组件库
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
然后根据在线文档引入操作