大家好,欢迎来到IT知识分享网。
文章目录

🍋Vue是什么?
- Vue(读音 /vju:/, 类似于 view) 是一个前端框架, 易于构建用户界面
- Vue的核心库只关注图层, 不仅易于上手, 还便于与第三方库或项目整合
- 支持和其它类库结合使用
- 开发复杂的单页应用非常方便
- Vue 是 Vue.js的简称
🍋MVVM思想
图解
- M: 即 Model, 模型, 包括数据和一些基本操作.
- V: 即 View, 视图, 页面渲染结果.
- VM: 即 View-Model, 模型与视图间的双向操作(无需开发人员干涉).
- 在 MVVM 之前, 开发人员从后端获取需要的数据模型, 然后要通过DOM操作Model, , 把数据渲染到View中. 而后当用户操作视图, 我们还需要通过DOM操作获取View中的数据, 然后同步到Model中.
- 而MVVM中的 VM 要做的事情就是把DOM操作完全封装起来, 开发人员不用再关心Model 和 View之间是如何互相影响的.
- 只要我们 Model 发生了变化, View上自然就会表现出来.
- 当用户修改了 View, Model 中的数据也会跟着改变.
结果: 把开发人员从繁琐的DOM操作中解放出来, 把关注点放在如何操作Model上, 大大提高我们的开发效率.
🍋vue2快速入门

quick_start.html -> 数据绑定机制验证
<body>
<!-- 1.div元素不是必须的, 也可以是其它元素, 比如span, 但是约定都是将vue实例挂载到div下 因为div更加适合做布局 2.id 不是必须为app, 是程序员指定的, 一般我们就使用app -->
<div id="app">
<!-- 1.{
{message}}: 插值表达式 2.message 就是从model的data数据池来设置 3.当我们的代码执行时, 会到我们的data数据池中去匹配我们的数据. 4.如果匹配上, 就进行替换; 如果没有匹配上, 就会输出空 -->
<h1>欢迎{
{message}}--{
{name}}</h1>
</div>
<!--引入vue.js-->
<script src="vue.js"></script>
<script> //创建Vue对象 / * 1.创建Vue对象实例 * 2.我们在控制台输出vm对象, 看看该对象的结构! 数据在哪里 listeners在哪里 */ let vm = new Vue({
el: "#app",//创建的vue实例挂载到id=app的div data: {
//data{} 表示数据池[model的数据池有了数据], 有很多数据, 以k-v形式设置(根据业务需要来设置) message: "hello-Vue!", name: "赵志伟" } }); console.log("vm=>", vm); console.log(vm._data.message); console.log(vm._data.name); console.log(vm.message); console.log(vm.name); </script>
</body>
🍋注意事项
- 注意代码顺序, 要求div在前, script在后, 否则无法绑定数据
- 从案例可以体会声明式渲染: Vue.js 采用简洁的模板语法来声明式地将数据渲染进DOM的系统, 做到数据和显示分离
- Vue没有繁琐的DOM操作, 如果使用jQuery, 我们需要先找到div节点, 获取到DOM对象, 然后进行节点操作, 显然没有Vue更加简洁
🍋数据单向渲染
数据单向渲染.html
需求: 演示v-bind 的使用, 可以绑定元素的属性
1.插值表达式是在标签体的
2.如果给标签属性绑定值, 则使用 v-bind 指令
<body>
<div id="app">
<h1>{
{message}}</h1>
<!-- 1.使用插值表达式 引用data数据池 数据是在标签体内 2.如果是在标签/元素的属性上去引用data数据池数据时, 不能使用插值表达式 3.需要使用v-bind, 因为b-bind是由vue解析的, 默认爆红, 但是不影响解析 4.如果不希望看到爆红, 直接alt+enter引入 xmlns:v-bind 5.v-bind: 可以简写成一个冒号 -->
<!--<img src="{
{img_src}}">-->
<img v-bind:src="img_src" v-bind:width="img_width">
<img :src="img_src" :width="img_width">
</div>
<script src="vue.js"></script>
<script> let vm = new Vue({
el: "#app",//创建的vue实例挂载到id=app的div data: {
//data{} 表示数据池[model的数据池有了数据], 有很多数据, 以k-v形式设置(根据业务需要来设置) message: "Hello-温暖女孩!", img_src: "1.jpg", img_width: "200px" } }); console.log("vm=>", vm); </script>
🍋数据双向渲染
数据双向渲染.html
<div id="app">
<h1>{
{message}}</h1>
<!--解读 1.v-bind是数据单项渲染: data数据池绑定的数据变化, 会影响view 2.v-model="hobby.val" 是数据的双向渲染 (1)data数据池绑定的数据变化, 会影响View -> 底层机制是 Data Bindings (2)view 关联的元素变化, 会影响到data数据池的数据 -> 底层机制是 Dom Listeners -->
<input type="text" v-model="hobby.val"/><br/><br/>
<input type="text" :value="hobby.val"/><br/><br/>
<p>你输入的爱好是: {
{hobby.val}}</p>
</div>
<script src="vue.js"></script>
<script> let vm = new Vue({
el: "#app",//创建的vue实例挂载到id=app的div data: {
//data{} 表示数据池[model的数据池有了数据], 有很多数据, 以k-v形式设置(根据业务需要来设置) message: "你好, 输入你的爱好!", hobby: {
val: "购物" } } }); console.log("vm=>", vm); </script>
🍋作业布置
homework01.html
使用Vue的数据双向绑定, 完成
- 当用户在输入框输入1,jpg, 2.jpg, 3.jpg时可以切换显示对应的图片
- 使用Vue的数据双向绑定, 完成
<body>
<div id="app">
<h1>{
{message}}</h1>
<!-- 1.这里我们使用了数据的双向渲染-data{}数据池的img_src -->
<input type="text" v-model="img_src"/><br/><br/>
<img v-bind:src="img_src" v-bind:width="img_width"/><br/><br/>
<img src="1.jpg" v-bind:width="img_width"/>
<img src="2.jpg" v-bind:width="img_width"/>
<img src="3.jpg" v-bind:width="img_width"/>
</div>
<script src="vue.js"></script>
<script> let vm = new Vue({
el: "#app",//创建的vue实例挂载到id=app的div data: {
//data{} 表示数据池[model的数据池有了数据], 有很多数据, 以k-v形式设置(根据业务需要来设置) message: "请输入图片编号 1.jpg, 2.jpg, 3.jpg!", img_src: "1.jpg", img_width: "400px" } }); console.log("vm=>", vm); </script>
</body>
🍋事件绑定
event.html
基本说明
- 使用 v-on 进行事件处理, 比如: v-on: click 表示处理鼠标点击事件
- 时间调用的方法定义在 vue 对象声明的methods节点中
- v-on: 事件名, 可以绑定指定事件
- 官方网站: https://v2.cn.vuejs.org/v2/guide/events.html
需求: 演示Vue事件绑定操作
<body>
<div id="app">
<h1>{
{message}}</h1>
<!-- 1.v-on:click 表示我们要给button元素, 绑定一个click事件 2.sayHi() 表示绑定的方法, 在我们的方法池 methods{} 中定义 3.这里需要js的基础, 底层仍然是dom编程 4.如果方法不需要传递参数, 可以省略() [主流浏览器都是支持这个写法的] 5.v-on:click 可以简写成 @click, [需要浏览器支持, 主流浏览器都支持] -->
<button v-on:click="sayHi()">点击输出</button>
<button v-on:click="sayOk()">点击输出</button>
<button v-on:click="sayHi">点击输出</button>
<button @click="sayOk">点击输出</button>
</div>
<script src="vue.js"></script>
<script> //1.创建一个Vue实例, 并挂载到id=app的div上, el 就是element的简写 //2.这里创建的Vue实例, 可以不去接收, 也可以去接收. 接收方便我们调试信息 let vm = new Vue({
el: "#app", data: {
//data{} 表示数据池[model的数据池有了数据], 有很多数据, 以k-v形式设置(根据业务需要来设置) message: "vue事件处理的案例 ", }, //解读: // 1.是一个methods属性, 对应的值是对象{} // 2.在{ }中, 可以写很多的方法, 可以理解成是一个方法池 methods: {
sayHi() {
console.log("hi, 银角大王"); }, sayOk() {
console.log("hi, 金角大王"); }, }, }); </script>
</body>
🍋事件处理机制
🍋注意事项和细节
- 如果方法不需要传递参数, 可以省略() [主流浏览器都是支持这个写法的]
- v-on:click 可以简写成 @click, [需要浏览器支持, 主流浏览器都支持]
- 在挂载的div的某个元素上可以查看可以绑定的事件, 通过控制台
🍋作业布置
event-homework01.html
需求: 点击按钮, 次数联动变化
- 当用户 “点击增加+1” 按钮时, 次数+1
- 当用户 “点击增加+2” 按钮时, 次数+2
- 使用常规方法和表达式形式完成(两种方式都要掌握)
<body>
<div id="app">
<h1>{
{message}}</h1>
<button v-on:click="add">点击增加+1</button>
<!-- 第二种写法 1.这里 count += 2 的count数据是data数据池的count -->
<button @click="count += 2">点击增加+2</button>
<p>你的按钮被点击了{
{count}}次</p>
</div>
<script src="vue.js"></script>
<script> let vm = new Vue({
el: "#app", data: {
//data{} 表示数据池[model的数据池有了数据], 有很多数据, 以k-v形式设置(根据业务需要来设置) message: "演示Vue事件绑定操作", count: 0,//点击的次数 }, methods: {
add() {
//修改data数据池中的数据 //因为data和methods在同一个Vue实例中, 因此可以通过 this.数据名 来获取 //this在对象中使用, 在这里是vm实例 this.count += 1; // vm.count += 1; // vm._data.count += 1; // this._data.count += 1; // vm.$data.count += 1; // this.$data.count += 1; }, }, }); </script>
</body>
event-homework02.html
需求: 根据用户的输入, 弹窗显示内容
- 用户可以在输入框输入内容
- 点击按钮, 可以显示书名
<body>
<div id="app">
<h1>{
{message}}</h1>
书名: <input type="text" v-model="bookName"/>
<button v-on:click="listBook">点击显示输入框的内容</button>
</div>
<script src="vue.js"></script>
<script> let vm = new Vue({
el: "#app", data: {
//data{} 表示数据池[model的数据池有了数据], 有很多数据, 以k-v形式设置(根据业务需要来设置) message: "演示Vue事件绑定操作", bookName: "笑傲江湖~", }, //解读: // 1.是一个methods属性, 对应的值是对象{} // 2.在{ }中, 可以写很多的方法, 可以理解成是一个方法池 methods: {
listBook() {
//this在对象中使用, this 当前对象 //this要带上, 否则报错 "ReferenceError: bookName is not defined" alert("书名=" + bookName); }, }, }); </script>
</body>
🍋修饰符
vue_modifier.html
基本说明
- 修饰符(Modifiers)是以 ( . ) 指明的后缀, 指出某个指令以特殊方式绑定
- 官方文档: https://v2.cn.vuejs.org/v2/guide/events.html#事件修饰符
需求: 演示v-on:submit.prevent 的使用, 如果没有输入名字, 控制台输出 “请输入名字”, 否则输出 “提交表单”
- 为什么在开发中, 有时需要, 让某个指令以特殊方式提交, 比如表单提交
- 我们不希望这个表单进行整体提交, 而是以Ajax的方式进行提交
- 因为表单整体提交会导致重载页面, 而Ajax方式可以有选择性地提交数据, 并且可局部刷新
<body>
<div id="app">
<!-- 1.修饰符用于指出一个指令应该以特殊方式绑定 2.v-on:submit.prevent的.prevent 修饰符表示阻止表单提交的默认行为 3.执行 程序员 指定的方法 -->
<form action="http://www.baidu.com" v-on:submit.prevent="mySubmit">
妖怪名: <input type="text" v-model="monster.name"><br/><br/>
<button type="submit">注册</button>
</form>
<p>服务器回送的数据是{
{count}}</p>
</div>
<script src="vue.js"></script>
<script> let vm = new Vue({
el: "#app", data: {
//数据池 monster: {
//monster数据(对象)的属性, 可以动态生成 //这里不写name, 不影响浏览器端生成的vm实例中monster.name的生成 }, count: 0, }, methods: {
//方法池 mySubmit() {
// 这里不能用this.name获取 if (this.monster.name) {
// "" undefined都是false console.log("提交表单 name=", this.monster.name); //这里, 程序员就可以根据自己的业务发出ajax请求到后端 //得到数据后,再进行数据更新-局部刷新 this.count = 1; } else {
console.log("请输入名字"); } }, }, }); </script>
</body>
🍋扩展案例
<h1>修饰符扩展案例</h1>
<!--在同一个页面, 只能点击一次-->
<button v-on:click.once="onMySubmit">点击一次</button><br/><br/>
<!--按键修饰符-->
<input type="text" v-on:keyup.enter="onMySubmit">
<input type="text" v-on:keyup.right="onMySubmit">
<!--去掉两边的空格-->
<input type="text" v-model.trim="count">
🍋条件渲染/控制
🍋v-if介绍
v_if.html
v-if指令用于条件性地渲染一块内容, 这块内容只会在指令的表达式返回true值时被渲染
细节: ok是要往data数据池中找的, 如果ok为true, 那么这个标题被输出; 如果在data数据池中没有找到这个变量, ok返回undefined, 在js中, undefined为false, 则不会被渲染
<h1 v-if="ok">hello</h1>
也可以用v-else添加一个”else”块
<h1 v-if="ok">hello</h1>
<h1 v-else>no 😊</h1>
应用实例
<body>
<div id="app">
<!-- 这里还可以看到checkbox的 checked属性值 在vm实例$el属性 childNodes下找到checkbox节点 -->
<input type="checkbox" v-model="ok"/>是否同意条款[v-if实现]
<h1 v-if="ok">你同意条款</h1>
<h1 v-else>你不同意条款</h1>
</div>
<script src="vue.js"></script>
<script> //为了调试方便, 用vm来接收Vue实例 let vm = new Vue({
el: "#app",//创建的vue实例挂载到id=app的div data: {
//data{} 表示数据池[model的数据池有了数据], 有很多数据, 以k-v形式设置(根据业务需要来设置) ok: false, } }); </script>
</body>
🍋v-show介绍
v_show.html
另一个用于根据条件展示元素的选项是v-show指令, 用法大致一样
细节: 去data数据池中获取ok的值, 如果ok值为true, 标签被渲染; 如果ok值为false, 不会被渲染
<h1 v-show="ok">hello</h1>
应用实例
<input type="checkbox" v-model="ok"/>是否同意条款[v-show实现]
<!--这里的ok不要把它理解为字符串, 它是数据池里的一个变量-->
<h1 v-show="ok">你同意条款</h1>
<h1 v-show="!ok">你不同意条款</h1>
🍋机制剖析
🍋作业布置
条件渲染-homework01.html
需求: 当用户输入成绩时, 可以输出对应的级别
- 90分以上, 显示优秀
- 80分以上, 显示良好
- 60分以上, 显示及格
- 低于60分, 显示不及格
- 如果用户输入的成绩大于100, 就修正成100; 如果用户输入的成绩小于0, 就修正成0
Vue 输入框组件 @input、@keyup.enter、@change、@blur
<body>
<div id="app">
<h1>{
{message}}</h1>
<!--思路 1.当用户输入成绩后, 我们判断成绩的范围, 并进行修正 2.事件处理: input 实时监听事件,只要输入的值变化了就会触发input -->
输入成绩1-100: <input type="text" v-model="score" v-on:input="correct"/>
<p>你当前的成绩是 {
{score}}</p>
<p v-if="score >= 90">优秀</p>
<p v-else-if="score >= 80">良好</p>
<p v-else-if="score >= 60">及格</p>
<p v-else>不及格</p>
</div>
<script src="vue.js"></script>
<script> //为了调试方便, 用vm来接收Vue实例 let vm = new Vue({
el: "#app",//创建的vue实例挂载到id=app的div data: {
//data{} 表示数据池[model的数据池有了数据], 有很多数据, 以k-v形式设置(根据业务需要来设置) message: "演示条件判断", score: "",//当前的成绩 }, methods: {
correct() {
//判断成绩并修正 this.score = (this.score > 100) ? 100 : this.score; this.score = (this.score < 0) ? "" : this.score; }, } }); </script>
</body>
🍋列表渲染
v_for.html
基本说明
- Vue提供了 v-for 列表循环指令
官网文档: https://v2.cn.vuejs.org/v2/guide/list.html
<body>
<div id="app">
<ul>
<h1>简单的列表渲染</h1>
<li v-for="i in 3">{
{i}}</li>
</ul>
<ul>
<h1>简单的列表渲染-带索引</h1>
<!--索引不一定要用index表示, 只是一般是用index-->
<li v-for="(j, index) in 3">{
{j}} - {
{index}}</li>
</ul>
<h1>遍历数据列表</h1>
<table border="1px" width="500px">
<tr v-for="(monster, index) in monsters">
<td>{
{index}}</td>
<td>{
{monster.id}}</td>
<td>{
{monster.name}}</td>
<td>{
{monster.age}}</td>
</tr>
</table>
</div>
<script src="vue.js"></script>
<script> //为了调试方便, 用vm来接收Vue实例 let vm = new Vue({
el: "#app",//创建的vue实例挂载到id=app的div data: {
//数据池 monsters: [ {
id:1, name:"牛魔王", age:800}, {
id:2, name:"齐天大圣", age:900}, {
id:3, name:"红孩儿", age:200}, ] }, }); </script>
</body>
🍋作业布置
v_for_homework.html
需求: 显示成绩及格的学生列表
- 将学生对象, 存放在数组中
- 遍历显示所有学生, 只显示成绩及格的学员
<body>
<div id="app">
<h1>{
{message}}</h1>
<table border="1px" width="300px">
<tr>
<td>index</td>
<td>id</td>
<td>name</td>
<td>age</td>
<td>score</td>
</tr>
<tr v-for="(student, index) in students">
<template v-if="student.score >= 60">
<td>{
{index}}</td>
<td>{
{student.id}}</td>
<td>{
{student.name}}</td>
<td>{
{student.age}}</td>
<td>{
{student.score}}</td>
</template>
</tr>
</table>
</div>
<script src="vue.js"></script>
<script> //为了调试方便, 用vm来接收Vue实例 let vm = new Vue({
el: "#app",//创建的vue实例挂载到id=app的div data: {
//数据池 message: "学生成绩列表-及格的学生", students: [ {
id: 1, name: "jack", age: 20, score: 90}, {
id: 2, name: "john", age: 19, score: 55}, {
id: 3, name: "tom", age: 21, score: 42}, {
id: 4, name: "mary", age: 20, score: 60} ] }, }); </script>
</body>
🍋组件化编程
基本说明
- 在大型应用开发的时候, 页面可以划分为很多部分, 往往不同的页面, 会有相同的部分. 例如可能会有相同的头部导航.
- 但是如果每个页面都独自开发, 这无疑增加了我们开发的成本. 所以我们会把页面的不同部分拆分成独立的组件, 然后在不同页面就可以共享这些组件, 避免重复开发
- 组件(Component)是 Vue.js最强大的功能之一[可以提高复用性(1.界面 2.业务逻辑)]
- 组件也是一个Vue实例, 也包括: data, methods, 生命周期函数等
- 组件渲染需要html模板, 所以增加了template属性, 值就是html模板
- 对于全局组件, 任何vue实例都可以直接在html中通过组件名称来使用组件
- data是一个函数, 不再是一个对象, 这样每次引用组件都是独立的对象/数据
🍋非组件化编程
组件化编程1.html
<body>
<div id="app">
<!--非组件化方式 - 普通方式-->
<button v-on:click="click1()">点击次数= {
{count}}次 [非组件化方式]</button><br/><br/>
<!--有多个按钮, 都要进行点击统计-->
<!-- 1.其实三个按钮的界面一样, 但是目前我们都重新写了一次, 复用性低 2.点击各个按钮的业务都是对 次数+1, 因此业务处理类似, 但是也都重新写了一次, 复用性低 3.解决: 组件化编程 -->
<button v-on:click="click2()">点击次数= {
{count2}}次 [非组件化方式]</button><br/><br/>
<button v-on:click="click3()">点击次数= {
{count3}}次 [非组件化方式]</button><br/><br/>
</div>
<script src="vue.js"></script>
<script> //为了调试方便, 用vm来接收Vue实例 let vm = new Vue({
el: "#app",//创建的vue实例挂载到id=app的div data: {
//数据池 count: 0, count2: 0, count3: 0, }, methods: {
//methods属性, 可以定义相应的方法 click1() {
this.count++; }, click2() {
this.count2++; }, click3() {
this.count3++; }, } }); </script>
</body>
🍋全局组件
组件化编程2.html
<body>
<div id="app">
<h1>{
{message}}</h1>
<!--使用全局组件-->
<counter></counter><br/><br/>
<counter></counter>
</div>
<script src="vue.js"></script>
<script> //1.定义一个全局组件, 名称为counter //2.{} 表示我们组件相关的内容 //3.template用于指定该组件的界面, 因为会引用到数据池里的数据, 所以需要使用模板字符串 //4.这里要特别强调: 要把组件视为一个Vue实例, 也有自己的数据池和methods //5.特别说明: 对于组件, 我们的数据池的数据是使用函数/方法返回[目的是为了保证每个组件的数据是独立的], 不能使用原来的方式 //6.这时我们就达到了, 界面通过template实现共享, 业务处理也复用 Vue.component("counter", {
template: `<button v-on:click="click()">点击次数= {
{count}}次 [全局组件化]</button>`, /*data: {//错误方式 The "data" option should be a function that returns a per-instance value in component definitions. count: 10 },*/ data() {
//这里需要注意, 和原来的方式不一样!!! return {
count: 10, } }, methods: {
click() {
this.count++; }, } }) //为了调试方便, 用vm来接收Vue实例 let vm = new Vue({
el: "#app",//创建的vue实例挂载到id=app的div data: {
//数据池 message: "组件化编程-全局组件", } }); </script>
</body>
🍋局部组件
组件化编程3.html
<body>
<div id="app">
<h1>{
{message}}</h1>
<!--使用局部组件, 该组件是从挂载到app的vue中来的-->
<my_counter></my_counter><br/><br/>
<my_counter></my_counter><br/><br/>
<my_counter></my_counter><br/><br/>
</div>
<script src="vue.js"></script>
<script> //定义一个组件, 组件的名称为 buttonCounter //扩展: 1.将来可以把常用的组件, 定义在某个commons.js中 // 2.如果某个页面需要使用, 直接import const buttonCounter = {
template: `<button v-on:click="click()">点击次数= {
{count}}次 [局部组件化]</button>`, data() {
//这里需要注意, 和原来的方式不一样!!! return {
count: 10, } }, methods: {
click() {
this.count++; }, } }; //为了调试方便, 用vm来接收Vue实例 let vm = new Vue({
el: "#app",//创建的vue实例挂载到id=app的div components: {
//引入某个组件, 此时my_counter就是一个组件, 它是一个局部组件, 它的适用范围就在当前的Vue实例中 "my_counter": buttonCounter, }, data: {
//数据池 message: "组件化编程-局部组件", } }); </script>
</body>
🍋全局组件VS局部组件
组件化编程2-进阶.html
全局组件是属于所有Vue实例, 因此可以在所有Vue实例中使用
<body>
<div id="app">
<h1>组件化编程-全局组件</h1>
<!--使用全局组件-->
<counter></counter><br/><br/>
<counter></counter>
</div>
<div id="app2">
<h1>组件化编程-全局组件-app2</h1>
<!--使用全局组件-->
<counter></counter><br/><br/>
<counter></counter>
</div>
<script src="vue.js"></script>
<script> Vue.component("counter", {
template: `<button v-on:click="click()">点击次数= {
{count}}次 [全局组件化]</button>`, data() {
return {
count: 10, } }, methods: {
click() {
this.count++; }, } }) let vm = new Vue({
el: "#app", }); let vm2 = new Vue({
el: "#app2", }); </script>
</body>
组件化编程3-进阶.html
局部组件, 作用范围只在引入这个组件的Vue实例中
<div id="app">
<h1>组件化编程-局部组件</h1>
<my_counter></my_counter><br/><br/>
<my_counter></my_counter>
</div>
<div id="app2">
<h1>组件化编程-局部组件-app2</h1>
<zzw_counter></zzw_counter><br/><br/>
<zzw_counter></zzw_counter>
</div>
<script src="vue.js"></script>
<script>
const buttonCounter = {
template: `<button v-on:click="click()">点击次数= {
{
count}}次 [局部组件化]</button>`,
data() {
return {
count: 10,
}
},
methods: {
click() {
this.count++;
},
}
};
let vm = new Vue({
el: "#app",
components: {
"my_counter": buttonCounter,
},
});
let vm2 = new Vue({
el: "#app2",
components: {
"zzw_counter": buttonCounter,
},
});
</script>
</body>
🍋注意事项
- 组件定义需要放置在new Vue()之前, 否则组件注册会失败
- 组件也是一个Vue实例, 也包括: data, methods, 生命周期函数等
- 组件渲染需要html模板, 所以增加了template属性, 值就是html模板
- data是一个函数, 不再是一个对象, 这样每次引用组件都是独立的对象/数据
🍋生命周期和监听函数
基本说明
- Vue实例有一个完整的生命周期, 也就是说从开始创建, 初始化数据, 编译模板, 挂载DOM, 渲染-更新-渲染, 卸载等一系列过程, 我们称为Vue实例的生命周期
- 钩子函数(监听函数): Vue实例在完整的生命周期过程中(比如设置数据监听, 编译模板, 将实例挂载到DOM, 在数据变化时更新DOM等), 也会运行叫做生命周期钩子(hook)的函数
- 钩子函数的作用: 就是在某个阶段, 给程序员一个做某些处理的机会
- Vue实例生命周期非常重要, Vue编程模型都是建立在此基础上
- 官网文档: https://v2.cn.vuejs.org/v2/guide/instance.html
🍋vue生命周期图示
- new Vue()
new 了一个Vue的实例对象, 此时就会进入组件的创建过程 - Init Events & Lifecycle
初始化组件的事件和生命周期函数 (Vue底层来做的, 无法干预) - beforeCreate
组件创建之后遇到的第一个生命周期函数, 这个阶段data和methods以及dom结构都未被初始化, 也就是获取不到data的值, 不能调用methods中的函数 - Init injections & reactivity
这个阶段中, 正在初始化data和methods中的方法 - created
这个阶段组件的data和methods中的方法已经初始化结束, 可以访问. 但dom结构未初始化, 页面未渲染
特别说明: 在这个阶段, 经常会发出Ajax请求 - 编译模板结构(在内存中, 由Vue底层实现的, 不用参与)
- 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实例生命周期和钩子函数/监听函数/生命周期函数 执行时机
- 重点展示几个重要的钩子函数(beforeCreate, created, beforeMount, mounted, beforeUpdate, updated)
- 在这几个钩子函数中, 数据模型是否加载/使用?
自定义方法是否加载/使用?
html模板(页面DOM)是否加载/使用?
html模板是否完成渲染(插值表达式是否更新)?
学习小技巧/起到大作用: 自己对某个知识有疑问, 可以设计一些小案例, 来验证
<body>
<!--这里可以视为用户看到的页面, 对应前面讲解的页面dom-->
<div id="app">
<span id="num">{
{num}}</span>
<button @click="num++">点赞!</button>
<h2>{
{name}}, 有{
{num}}次点赞</h2>
</div>
<script src="vue.js"></script>
<script> let vm = new Vue({
el: "#app", data: {
name: "Kristina", num: 0, }, methods: {
show() {
return this.name; }, add() {
this.num++; }, }, beforeCreate() {
//生命周期函数-创建Vue实例前 console.log("============beforeCreate============"); console.log("数据模型/数据池的数据 是否加载/是否能使用? [不能使用]", this.name, " ", this.num);//undefined undefined // console.log("自定义的方法 是否加载/是否能使用? [不能使用]", this.show());//Error in beforeCreate hook: "TypeError: this.show is not a function" console.log("用户的页面dom 是否被加载? [已经加载]", document.getElementById("num")); console.log("用户的页面dom 是否被渲染? [未被渲染]", document.getElementById("num").innerText);//{
{num}} }, created() {
//生命周期函数-创建Vue实例后 console.log("============created============"); console.log("数据模型/数据池的数据 是否加载/是否能使用? [可以使用]", this.name, " ", this.num);//Kristina 0 console.log("自定义的方法 是否加载/是否能使用? [可以使用]", this.show());//Kristina console.log("用户的页面dom 是否被加载? [已经加载]", document.getElementById("num")); //内存模型还未编译, 外面的页面dom肯定不会被渲染 console.log("用户的页面dom 是否被渲染? [未被渲染]", document.getElementById("num").innerText);//{
{num}} //可以发出Ajax请求 //接收返回的数据 //再次更新data数据池的数据 //编译内存模板结构 //挂载 //...替换 }, beforeMount() {
//生命周期函数-挂载前 console.log("============beforeMount============"); console.log("数据模型/数据池的数据 是否加载/是否能使用? [可以使用]", this.name, " ", this.num);//Kristina 0 console.log("自定义的方法 是否加载/是否能使用? [可以使用]", this.show());//Kristina console.log("用户的页面dom 是否被加载? [已经加载]", document.getElementById("num")); //还没有把内存编译好的模板替换到用户页面的dom结构上, 仍然看不到渲染后的结果 console.log("用户的页面dom 是否被渲染? [未被渲染]", document.getElementById("num").innerText);//{
{num}} }, mounted() {
//生命周期函数-挂载后 console.log("============mounted============"); console.log("数据模型/数据池的数据 是否加载/是否能使用? [可以使用]", this.name, " ", this.num);//Kristina 0 console.log("自定义的方法 是否加载/是否能使用? [可以使用]", this.show());//Kristina console.log("用户的页面dom 是否被加载? [已经加载]", document.getElementById("num")); //把内存中的模板替换到el上, 即挂载点上 console.log("用户的页面dom 是否被渲染? [已经渲染]", document.getElementById("num").innerText);//0 }, beforeUpdate() {
//生命周期函数-页面数据更新前 console.log("============beforeUpdate============"); console.log("数据模型/数据池的数据 是否加载/是否能使用? [可以使用]", this.name, " ", this.num);//Kristina 0 console.log("自定义的方法 是否加载/是否能使用? [可以使用]", this.show());//Kristina console.log("用户的页面dom 是否被加载? [已经加载]", document.getElementById("num")); console.log("用户的页面dom 是否被更新? [未被更新]", document.getElementById("num").innerText);//0 //验证前如果数据有错误, 需要修正数据 //举个例子 // if (this.num < 10) {
// this.num = 10; // } }, updated() {
//生命周期函数-页面数据更新后 console.log("============updated============"); console.log("数据模型/数据池的数据 是否加载/是否能使用? [可以使用]", this.name, " ", this.num);//Kristina 0 console.log("自定义的方法 是否加载/是否能使用? [可以使用]", this.show());//Kristina console.log("用户的页面dom 是否被加载? [已经加载]", document.getElementById("num")); console.log("用户的页面dom 是否被更新? [已经更新]", document.getElementById("num").innerText);//1 }, }) </script>
</body>
🍋作业布置
- 请简述Vue实例的生命周期流程
🍋Vue2 Cli 脚手架
为什么需要Vue Cli 脚手架?
目前开发模式的问题
- 开发效率低
- 不够规范
- 维护和升级, 可读性差
需求: 使用Vue脚手架进行模块化开发, 输入不同的url, 切换不同页面
🍋环境配置, 搭建项目
- 搭建Vue脚手架工程, 需要使用到NPM(node package manager), npm是随node.js安装的一款包管理工具, 类似于Maven. 所有要先安装Node.js
- 为了更好的兼容, 这里安装
node.js 10.16.3. - 如果以前安装过node.js, 为防止版本冲突, 先卸载之.
- 下载地址: https://nodejs.org/en/blog/release/v10.16.3 [网址进不去, 考虑连接手机热点]
- 安装. 路径 不要有空格, 不要有中文. 比如:D:\program\nodejs10.16
- 验证是否安装成功
如果看不到效果, 退出cmd, 重新开一个窗口测试即可
- 先删除以前的cli版本<不论是之前未下载或没有下载>
npm uninstall vue-cli -g 安装淘宝镜像-cnpm
npm install -g cnpm@7.1.1 –registry=https://registry.npm.taobao.org
淘宝镜像已经更换域名
修改npm至新的淘宝镜像源:
npm config set registry http://registry.npmmirror.com
查看npm源地址有没有换成功:
npm config get registry
通过配置淘宝镜像并安装使用cnpm
npm install -g cnpm@7.1.1 –registry=https://registry.npmmirror.com
说明: npm 和 cnpm 的区别
- 两者之间只是node中包管理器的不同, 都可以使用
- npm是node官方的包管理器. cnpm是个中国版的npm, 是淘宝定制的 cnpm (gzip压缩支持)命令行工具, 代理默认的npm
- 如果因为网络原因无法使用npm下载, 那么这个cnpm就派上用场了
- 小结: npm和cnpm只是下载的地址不同, npm是从国外下载东西, cnpm是从国内下载东西
- 安装webpack和webpack-cli. 指令: npm install webpack@4.41.2 webpack-cli@4.9.2 -D
这里指定了webpack的版本, webpack是一个打包工具
报错执行: npm init –yes - 安装脚手架 cnpm install -g @vue/cli@4.0.3
- 确认Vue-Cli 版本 vue -V
- 创建目录 D:\idea_project\zzw_vue_project, 并cmd到该目录
- 使用webpack创建vue脚手架项目
vue init webpack vue_project_qs
可能会报的错误
- 运行: npm install -g @vue/cli-init
- 如果出现了 downloading template…, 等待一分钟. 如果没有反应
(1) 退出窗口, 重新来一次
(2) 连接手机热点, 换网络

如果报告端口占用的错误, 就把端口让出来, 重新运行命令

🍋IDEA配置项目
- 将Vue脚手架项目, 直接拖到IDEA, 就可以打开
- 配置NPM
启动
成功访问
🍋vue项目结构分析
🍋项目执行流程
🍋路由器作业
<template>
<div>
<h1>{
{ msg }}</h1>
</div>
</template>
<script> export default {
name: "HelloMary", data() {
//数据池 return {
msg: "HelloMary" } } } </script>
配置路由
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld.vue'
//@指的是src目录
import HelloMary from "@/components/HelloMary.vue"
import Zzw from "@/components/Zzw.vue"
Vue.use(Router)
export default new Router({
routes: [ //路由表
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
//配置的一组路由
path: '/hello',
name: 'HelloMary',
component: HelloMary
}
]
})
HelloWorld.vue
<template>
<div class="hello">
<img src="@/assets/logo.png"/>
<h1>{
{ msg1 }}</h1>
<h2>{
{ msg2 }}</h2>
<a href="https://www.baidu.com" target="_blank">{
{ msg3 }}</a>
</div>
</template>
<script> export default {
//默认导出组件 name: 'HelloWorld', data () {
//数据池 return {
msg1: '网站首页-赵志伟', msg2: '网站首页-赵志伟', msg3: '点击进入百度' } } } </script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped> h1, h2 {
font-weight: normal; } ul {
list-style-type: none; padding: 0; } li {
display: inline-block; margin: 0 10px; } a {
color: #42b983; } </style>
🍋路由器应用实例
配置自己的组件 Zzw.vue
<!--模板: 表示页面视图html-->
<template>
<div>
<h1>{
{ msg }}</h1>
<table>
<tr>
<td colspan="3">第1行第1列</td>
</tr>
<tr>
<td rowspan="2">第2行第1列</td>
<td>第2行第2列</td>
<td>第2行第3列</td>
</tr>
<tr>
<td>第3行第2列</td>
<td>第3行第3列</td>
</tr>
<tr>
<td rowspan="2">第4行第1列</td>
<td>第4行第2列</td>
<td>第4行第3列</td>
</tr>
<tr>
<td>小猫咪<img src="@/assets/1.gif" width="100"></td>
<td>第5行第3列</td>
</tr>
</table>
</div>
</template>
<!--定义数据和操作方法, 默认导出-->
<script> export default {
name: "Zzw", data() {
return {
msg: "Welcome to Zzw!" } }, } </script>
<!-- 样式,css 可以修饰页面视图 0表示上下边距; auto表示左右居中 -->
<style scoped> div {
background-color: beige; width: 600px; margin: 0 auto; } table, td {
border: solid red 1px; width: 600px; height: 50px; border-collapse: collapse; /*边界合并*/ } h1 {
color: red; } </style>
配置路由
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld.vue'
//@指的是src目录
import HelloMary from "@/components/HelloMary.vue"
import Zzw from "@/components/Zzw.vue"
Vue.use(Router)
export default new Router({
routes: [ //路由表
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/hello',
name: 'HelloMary',
component: HelloMary
},
{
//配置的一组路由
path: "/zzw",
name: "Zzw",
component: Zzw
}
]
})
App.vue 项目主体单页
<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
2.ElementUI是组件库, 是网站快速成型的工具
🍋基本使用
在Vue2项目中, 使用ElementUI组件. Vue3使用ElementPlus
2.在mian.js中引入ElementUI
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
🍋课后作业
如果自己的代码里有data数据池, methods, template, 那么只需引入data里的数据, methods里的方法和template里的代码即可
- 做出斑马纹表格
- 做出树形控件 – 描述产品分类菜单
🍋Axios
注意: axios底层地址是 promise
🍋基本介绍
1.axios是独立于vue的一个项目, 不是vue的一部分
2.axios通常和Vue一起使用, 实现ajax操作
3.Axios 是一个基于 promise 的HTTP库
🍋学习文档
https://javasoho.com/axios/
🍋Axios库文件
1.使用axios需要引入axios库文件
2.可以直接引入
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
3.也可以下载axios.min.js, 在本地引入
<script src="vue.js"></script>
<script src="axios.min.js"></script>
🍋 Axios应用实例
需求说明/图解
●需求: 在Vue项目中使用Axios, 从服务器获取json数据, 显示在页面
代码实现
2.创建D:\idea_project\zzw_javaweb\axios\data\response.data.json
{
"success": true,
"message": "成功",
"data": {
"items": [
{
"name": "牛魔王",
"age": 900
},
{
"name": "红孩儿",
"age": 400
},
{
"name": "齐天大圣",
"age": 890
},
{
"name": "唐玄奘",
"age": 80000
}
]
}
}
3.把vue.js库文件 和 axios.min.js库文件 拷贝到项目路径下
4.创建D:\idea_project\zzw_javaweb\axios\axios_quick_start.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>axios的应用实例</title>
</head>
<body>
<!--页面视图-->
<div id="app">
<h1>{
{msg}}</h1>
<table border="1px" width="300px">
<tr>
<td>名字</td>
<td>年龄</td>
</tr>
<tr v-for="monster in monsterList">
<td>{
{monster.name}}</td>
<td>{
{monster.age}}</td>
</tr>
</table>
</div>
<script src="vue.js"></script>
<script src="axios.min.js"></script>
<script> let vm = new Vue({
el: "#app", data: {
msg: "妖怪信息列表", monsterList: [],//表示妖怪的信息数组 }, methods: {
//定义方法 list() {
//发出ajax请求, 获取数据 axios /* 解读 1. axios.get() 表示发出ajax请求 2. http://localhost:63342/axios/data/response.data.json 表示请求的是url 要根据实际情况来填写 3. axios发出ajax请求的基本语法 axios.get(url).then(箭头函数).then(箭头函数)...catch(箭头函数) (1)如果get请求成功就进入第一个then() (2)可以在 第一个then()中处理成功回调的数据, 还可以继续发出axios的ajax请求 (3)如果有异常, 会进入到 catch(箭头函数) 4. list方法在生命周期函数created() 中调用 */ axios.get("http://localhost:63342/axios/data/response.data.json") .then((responseData) => {
//要想准确拿到数据, 要一次一次的console.log()取 console.log("responseData=", responseData); //使用JSON.stringify(json), 把json对象转成字符串, 方便观察 console.log("responseData=", JSON.stringify(responseData)); // console.log("responseData.data=", responseData.data); // console.log("responseData.data.data=", responseData.data.data); console.log("responseData.data.data.items=", responseData.data.data.items); //将妖怪列表数组信息, 绑定到data数据池的monsterList //小技巧, 一定要学会看返回的数据格式 this.monsterList = responseData.data.data.items; //可以再次发出ajax请求, 故意发出了第二次ajax请求 // return axios.get("http://localhost:63342/axios/data/response.data.json"); }) // .then(responseData => {
// console.log("第二次ajax请求返回的数据 responseData.data.data.items=", responseData); // }) .catch(err => {
console.log("异常=", err); }); }, }, created() {
//生命周期函数 this.list(); }, }) </script>
</body>
</html>
完成测试
1.在浏览器进入运行界面
2.查看效果
🍋注意事项和细节
1.将JSON对象转成字符串, 通过JSON.stringify(responseData)
2.格式化输出JSON字符串, 方便观察分析

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/116497.html








如果看不到效果, 退出cmd, 重新开一个窗口测试即可







启动
成功访问





