(1)Vue 是一个前端框架, 易于构建用户界面
(2)Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或项目整合
(3)支持和其它类库结合使用
(4)开发复杂的单页应用非常方便
(5)Vue 是 Vue.js 的简称
官网: https://cn.vuejs.org/
git 地址: https://github.com/vuejs

解读 MVVM 思想(上图)
官网文档:https://cn.vuejs.org/v2/guide/index.html
下载: https://cn.vuejs.org/v2/guide/installation.html

注意:为了让 IDEA 识别 Vue 代码,需要安装插件 Vue.js

(1)创建新文件夹 D:\idea_java_projects\vue , 直接拖到 Idea 工具,使用 idea 打开
(2)将下载好的 vue.js 拷贝到 D:\idea_java_projects\vue\vue.js
(3)创建 D:\idea_java_projects\vue\vue_quick_start.html
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>vue快速入门</title>
- </head>
- <body>
- <!--
- 1. div元素不是必须的,也可以是其它元素,比如span,但是约定都是将vue实例挂载到div
- 2. 因为div更加适合做布局
- 3. id 不是必须为app , 是程序员指定,一般我们就使用app
- -->
- <div id="app">
- <!--
- 1. {{message}} : 插值表达式
- 2. message 就是从model的data数据池来获取
- 3. 当我们的代码执行时,会到data{} 数据池中去匹配数据, 如果匹配上, 就进行替换
- , 如果没有匹配上, 就输出空
- -->
- <h1>欢迎你{{message}}-{{name}}</h1>
- </div>
- <!--引入vue.js-->
- <script src="vue.js"></script>
- <script>
- /**
- * 1. 创建Vue对象
- */
- let vm = new Vue({
- el : "#app", // 将创建的vue实例挂载到 id=app 的div上
- data : { // data{}表示数据池,以k-v形式设置,根据需求设置
- message : "Hello-Vue",
- name : "小王"
- }
- })
- </script>
- </body>
- </html>
(4)运行效果如下

(1)注意代码顺序,要求 div 在前,script 在后,否则无法绑定数据
(2)从案例可以体会声明式渲染:Vue.js 采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统, 做到数据和显示分离
(3)Vue 没有繁琐的 DOM 操作,如果使用 jQuery,我们需要先找到 div 节点,获取到 DOM 对象,然后进行节点操作, 显然 Vue 更加简洁
(1)v-bind 指令可以完成基本数据渲染/绑定
(2)v-bind 简写形式就是一个冒号(:)
需求: 演示 v-bind 的使用, 可以绑定元素的属性
(1)把准备好的 1.jpg 拷贝到 D:\idea_java_projects\vue\1.jpg
(2)创建 D:\idea_java_projects\vue\单向数据渲染.html
- <!DOCTYPE html>
- <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
- <head>
- <meta charset="UTF-8">
- <title>单向数据渲染</title>
- </head>
- <body>
- <div id="app">
- <h1>{{message}}</h1>
- <!--
- 1. 使用插值表达式引用 data数据池数据是在标签体内
- 2. 如果是在标签/元素 的属性上去引用data数据池数据时,不能使用插值表达式
- 3. 需要使用v-bind, 因为v-bind是vue来解析, 默认报红,但是不影响解析
- 4. 如果不希望看到报红, 直接 alt+enter 引入 xmlns:v-bind
- -->
- <img v-bind:src="img_src" v-bind:width="img_width">
- <!--v-bind 简写形式就是一个冒号(:)-->
- <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{}表示数据池,以k-v形式设置,根据需求设置
- message : "单向数据渲染测试",
- img_src : "1.jpg",
- img_width : "200px"
- }
- })
- </script>
- </body>
- </html>
(3)效果如下

(1)插值表达式是用在标签体的
(2)如果给标签属性绑定值,则使用 v-bind 指令
v-model 可以完成双向数据绑定
需求:在输入框中输入信息,会更新到相应绑定的位置
(1)创建 D:\idea_java_projects\vue\双向数据渲染.html
- <!DOCTYPE html>
- <html lang="en" xmlns:v-model="http://www.w3.org/1999/xhtml">
- <head>
- <meta charset="UTF-8">
- <title>双向数据渲染</title>
- </head>
- <body>
- <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{}表示数据池,以k-v形式设置,根据需求设置
- message : "输入爱好",
- hobby :{
- val : "购物"
- }
- }
- })
- </script>
- </body>
- </html>
(2)完成测试

(1)使用 v-on 进行事件处理,比如: v-on:click 表示处理鼠标点击事件,v-on:blur 表示失去焦点事件
(2)事件调用的方法定义在 vue 对象声明的 methods 节点中
(3)v-on:事件名 可以绑定指定事件
(4)官方文档:https://cn.vuejs.org/v2/guide/events.html
需求: 演示 Vue 事件绑定操作
(1)创建 D:\idea_java_projects\vue\event.html
- <!DOCTYPE html>
- <html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
- <head>
- <meta charset="UTF-8">
- <title>事件绑定</title>
- </head>
- <body>
- <div id="app">
- <h1>{{message}}</h1>
- <!--
- 1. v-on:click 表示我们要给button元素绑定一个点击的事件
- 2. sayHi() 表示绑定的方法, 在方法池 methods{} 定义的
- 3. 底层仍然是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>
- // 创建的Vue实例可以不接收,也可以接收,方便我们调试信息
- let vm = new Vue({
- el : "#app",// el 接收element简写
- data : {
- message : "Vue事件处理案例"
- },
- // methods 是Vue的一个属性
- // 在{}中,可以写很多的方法,可以理解为方法池
- methods : {
- sayHi(){
- alert("hi")
- },
- sayOk(){
- alert("ok")
- }
- }
- })
- </script>
- </body>
- </html>
(1)如果方法没有参数,可以省略()[需要浏览器支持]
(2)v-on 指令的简写形式 @ [需要浏览器支持]
(1)修饰符 (Modifiers) 是以(.)指明的后缀,指出某个指令以特殊方式绑定。
(2)例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()即阻 止事件原本的默认行为
(3)事件修饰符
(4)键盘事件的修饰符
比如: 项目经常需要监听一些键盘事件来触发程序的执行,而 Vue 中允许在监听的时候添加键盘修饰符
<input v-on:keyup.13="submit">
绝大多数常用的按键码的别名:
.enter.tab.delete (捕获“删除”和“退格”键).esc.space.up.down.left.right(5)v-model 的修饰符
比如: 自动过滤用户输入的首尾空格
<input v-model.trim="msg">
(6)官 方 文 档 : https://cn.vuejs.org/v2/guide/events.html#%E4%BA%8B%E4%BB%B6%E4%BF%AE%E9%A5%B0%E7%AC%A6
需求:
(1)演示 v-on:submit.prevent 的使用, 如果没有输入名字,控制台输出 "请输入名字",否则输出 "提交表单"
(2)解惑, 为什么在开发中, 有时需要 , 让某个指令以特殊方式绑定, 比如表单提交
代码实现
(1) 创建 D:\idea_java_projects\vue\vue_modifier.html
- <!DOCTYPE html>
- <html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
- <head>
- <meta charset="UTF-8">
- <title>Vue修饰符使用</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/><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数据(对象)的属性, 可以动态生成
- },
- count: 0
- },
- methods: {//方法池
- onMySubmit() {
- //console.log("我们自己的表单提交处理...");
- //"", null, undefined都是false
- if(this.monster.name) {
- console.log("提交表单 name=", this.monster.name);
- //这里,程序员就可以根据自己的业务发出ajax请求到后端
- //得到数据后,在进行数据更新
- this.count = 666;
- } else {
- this.count = 0;
- console.log("请输入名字..");
- }
- }
- }
- })
- </script>
- </body>
- </html>
(2)效果如下
不输入名字直接提交

输入名字再提交

Vue 提供了 v-if 和 v-show 条件指令完成条件渲染/控制
(1)v-if 介绍
说明:0、null、undefined、""(空串) 、false 都认为是false
可以用 v-else-if 添加一个分支

(2)v-show
(3)官方文档:https://cn.vuejs.org/v2/guide/conditional.html
需求: 演示条件渲染使用(使用 v-if 和 v-show 实现)
(1)创建 D:\idea_java_projects\vue\v_if.html ,v-if实现
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>条件渲染演示 v-if</title>
- </head>
- <body>
- <div id="app">
- <input type="checkbox" v-model="sel">是否同意条款
- <h1 v-if="sel">你同意条款</h1>
- <h1 v-else>你不同意条款</h1>
- </div>
- <script src="vue.js"></script>
- <script>
- let vm = new Vue({
- el : "#app",
- data : {
- sel : false
- }
- })
- </script>
- </body>
- </html>
(2)创建 D:\idea_java_projects\vue\v_show.html ,v-show实现
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>条件渲染演示 v-show</title>
- </head>
- <body>
- <div id="app">
- <input type="checkbox" v-model="sel">是否同意条款
- <h1 v-show="sel">你同意条款</h1>
- <h1 v-show="!sel">你不同意条款</h1>
- </div>
- <script src="vue.js"></script>
- <script>
- let vm = new Vue({
- el : "#app",
- data : {
- sel : false
- }
- })
- </script>
- </body>
- </html>
(3)实现效果如下

(1)v-if 会确保在切换过程中,条件块内的事件监听器和子组件销毁和重建
(2)v-show 机制相对简单, 不管初始条件是什么,元素总是会被渲染,并且只是对 CSS 进行切换
(3)使用建议:如果要频繁地切换,建议使用 v-show ;如果运行时条件很少改变,使用 v-if 较好
Vue 提供了 v-for 列表循环指令,官方文档:https://cn.vuejs.org/v2/guide/list.html
(1)对数组进行遍历
可以用第二个参数作为索引


(2) 用 v-for 来遍历一个对象的 property


还可以用第三个参数作为索引
需求: 演示列表渲染使用(v-for)
(1) 创建 D:\idea_java_projects\vue\v_for.html
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>v-for 列表渲染</title>
- </head>
- <body>
- <div id="app">
- <!--
- 基本语法:
- <li v-for="变量 in 数字">{{ 变量 }}</li>-->
- <h1>简单的列表渲染</h1>
- <ul>
- <li v-for="i in 3">{{i}}</li>
- </ul>
- <!--
- 基本语法:
- <li v-for="(变量, 索引) in 值">{{ 变量 }} - {{ 索引 }}</li>
- -->
- <h1>简单的列表渲染-带索引</h1>
- <ul>
- <li v-for="(i,index) in 3">{{i}}-{{index}}</li>
- </ul>
- <h1>遍历数据列表</h1>
- <!-- 语法:
- <tr v-for="对象 in 对象数组">
- <td>{{对象的属性}}</td>
- </tr>
- -->
- <table width="400px" border="1px">
- <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>
- new Vue({
- el: '#app',
- data: { //数据池
- monsters: [
- {id: 1, name: '牛魔王', age: 800},
- {id: 2, name: '黑山老妖', age: 900},
- {id: 3, name: '红孩儿', age: 200}
- ]
- }
- })
- </script>
- </body>
- </html>
(2)效果

1. 在大型应用开发的时候,页面可以划分成很多部分,往往不同的页面,也会有相同的部 分。例如可能会有相同的头部导航。
2. 但是如果每个页面都独自开发,这无疑增加了我们开发的成本。所以我们会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发(如图)

3. 上图解读
如下, 点击一个按钮, 可以显示点击的次数
现在需求是,有多个按钮,都要进行点击统计

(1)创建 D:\idea_java_projects\vue\组件化编程1.html
- <!DOCTYPE html>
- <html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
- <head>
- <meta charset="UTF-8">
- <title>组件化编程</title>
- </head>
- <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/>
- </div>
- <script src="vue.js"></script>
- <script>
- new Vue({
- el: "#app",
- data: {//data数据池
- count: 10,
- count2: 10,
- count3: 10
- },
- methods: {//methods属性, 可以定义相应的方法
- click1() {
- this.count++;
- },
- click2() {
- this.count2++;
- },
- click3() {
- this.count3++;
- }
- }
- })
- </script>
- </body>
- </html>
(2)测试

(1) 创建 D:\idea_java_projects\vue\组件化编程2.html
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>组件化编程-全局组件</title>
- </head>
- <body>
- <div id="app">
- <h1>组件化编程-全局组件</h1>
- <!--使用全局组件-->
- <counter></counter>
- <br/>
- <counter></counter>
- <counter></counter>
- <counter></counter>
- <counter></counter>
- </div>
-
- <div id="app2">
- <h1>组件化编程-全局组件-app2</h1>
- <!--使用全局组件-->
- <counter></counter>
- <counter></counter>
- </div>
- <script src="vue.js"></script>
- <script>
- //1、定义一个全局组件, 名称为 counter
- //2. {} 表示就是我们的组件相关的内容
- //3. template 指定该组件的界面, 因为会引用到数据池的数据,所以需要是模板字符串
- //4. 要把组件视为一个Vue实例,也有自己的数据池和methods
- //5. 对于组件,我们的数据池的数据,是使用函数/方法返回[目的是为了保证每个组件的数据是独立], 不能使用原来的方式
- //6. 这时我们达到目前,界面通过template实现共享,业务处理也复用
- //7. 全局组件是属于所有vue实例,因此,可以在所有的vue实例使用
- Vue.component("counter", {
- template: `<button v-on:click="click()">点击次数= {{count}} 次【全局组件化】</button>`,
- data() {//这里需要注意,和原来的方式不一样!!!!
- return {
- count: 10
- }
- },
- methods: {
- click() {
- this.count++;
- }
- }
- })
- //创建Vue实例,必须有
- let vm = new Vue({
- el: "#app"//Vue实例的挂载点
- })
-
- let vm2 = new Vue({
- el: "#app2"//Vue实例的挂载点
- })
-
-
- </script>
- </body>
- </html>
(2)测试

(1) 创建 D:\idea_java_projects\vue\组件化编程3.html
说明:必须在vue实例中引入局部组件,才能使用该局部组件
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>组件化编程-局部组件</title>
- </head>
- <body>
- <div id="app">
- <h1>组件化编程-局部组件</h1>
- <!--使用局部组件 ,该组件是从挂载到app的vue中来的-->
- <my_counter></my_counter><br/>
- <my_counter></my_counter><br/>
- <my_counter></my_counter><br/>
- </div>
-
- <div id="app2">
- <h1>组件化编程-局部组件-app2</h1>
- <!--使用局部组件 -->
- <wwj_counter></wwj_counter><br/>
- <wwj_counter></wwj_counter><br/>
- </div>
- <script src="vue.js"></script>
- <script>
-
- //定义一个组件, 组件的名称为 buttonCounter
- //扩展
- //1. 可以把常用的组件,定义在某个commons.js中 export
- //2. 如果某个页面需要使用, 直接import
- const buttonCounter = {
- template: `<button v-on:click="click()">点击次数= {{count}} 次【局部组件化】</button>`,
- data() {//这里需要注意,和原来的方式不一样!!!!
- return {
- count: 10
- }
- },
- methods: {
- click() {
- this.count++;
- }
- }
- }
-
- //创建Vue实例,必须有
- let vm = new Vue({
- el: "#app",//Vue实例的挂载点
- components: { //引入/注册某个组件, 此时my_counter就是一个组件, 是一个局部组件,他的使用范围在当前vue
- my_counter: buttonCounter
- }
- })
-
- let vm2 = new Vue({
- el: "#app2",//Vue实例的挂载点
- components :{//引入/注册组件buttonCounter
- wwj_counter: buttonCounter
- }
- })
-
-
- </script>
- </body>
- </html>
(2)测试

(1)如果方法体, 只有简单的语句,比如 count++, 那么可以进行简写, 在组件化编程1.html 演示, 比如
- <!DOCTYPE html>
- <html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
- <head>
- <meta charset="UTF-8">
- <title>组件化编程</title>
- </head>
- <body>
-
- <div id="app">
- <!--非组件化方式-普通方式-->
- <button v-on:click="count++">点击次数= {{count}} 次</button><br/><br/>
- <button v-on:click="count++">点击次数= {{count2}} 次</button><br/><br/>
-
- </div>
- <script src="vue.js"></script>
- <script>
- new Vue({
- el: "#app",
- data: {//data数据池
- count: 10,
- },
-
- })
- </script>
- </body>
- </html>
(2)局部组件定义需要放置在 new Vue() 前,否则组件注册会失败
(1)Vue 实例有一个完整的生命周期,也就是说从开始创建、初始化数据、编译模板、挂载 DOM、渲染-更新-渲染、卸载等一系列过程,我们称为 Vue 实例的生命周期
(2)钩子函数(监听函数): Vue 实例在完整的生命周期过程中(比如设置数据监听、编译模 板、将实例挂载到 DOM 、在数据变化时更新 DOM 等), 也会运行叫做生命周期钩子的函数
(3)钩子函数的 作用就是在某个阶段, 给程序员一个做某些处理的机会

上图解读
(1) new Vue():new 了一个 Vue 的实例对象,此时就会进入组件的创建过程。
(2) Init Events & Lifecycle:初始化组件的事件和生命周期函数
(3) beforeCreate:组件创建之后遇到的第一个生命周期函数,这个阶段 data 和 methods 以及 dom 结构都未被初始化,也就是获取不到 data 的值,不能调用 methods 中的函数
(4) Init injections & reactivity:这个阶段中, 正在初始化 data 和 methods 中的方法
(5) created:这个阶段组件的 data 和 methods 中的方法已初始化结束,可以访问,但是 dom 结构未 初始化,页面未渲染
- 特别说明:在这个阶段,经常会发起 Ajax 请求,从后端获取到最新数据
(6) 编译模板结构(在内存)
(7) beforeMount:当模板在内存中编译完成,此时内存中的模板结构还未渲染至页面上,看不到真实的数据
(8) Create vm.$el and replace ‘el’ with it:这一步,在把内存中渲染好的模板结构替换至真实的 dom 结构也就是页面上
(9) mounted:此时,页面渲染好,用户看到的是真实的页面数据, 生命周期创建阶段完毕,进入到了运行中的阶段
(10) 生命周期运行中
10.1 beforeUpdate:当执行此函数,数据池的数据是新的,但是页面是旧的
10.2 Virtual DOM re-render and patch:根据最新的 data 数据,重新渲染内存中的模板结构,并把渲染好的模板结构,替换至页面 上
10.3 updated:页面已经完成了更新,此时,data 数据和页面的数据都是新的
(11) beforeDestroy:当执行此函数时,组件即将被销毁,但是还没有真正开始销毁,此时组件的 data、methods数据或方法 还可被调用
(12) Teardown……:注销组件和事件监听
需求:展示 VUE 实例生命周期和 钩子函数/监听函数/生命周期函数 执行时机
(1)重点研究几个重要的钩子函数 (beforeCreate, created, beforeMount, mounted, beforeUpdate, updated)
(2)验证在这几个钩子函数中, 数据模型/数据池是否加载/使用? 自定义方法是否加载/可用? html 模板是否加载/使用? html 模板是否完成渲染?
(1)创建 D:\idea_java_projects\vue\Vue\生命周期和钩子函数.html
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <div id="app">
- <span id="num">{{num}}</span>
- <button @click="num++">赞</button>
- <h2>{{name}},有{{num}}个人点赞</h2>
- </div>
- <script src="vue.js"></script>
- <script>
- new Vue({
- el:"#app",
- data : {//数据池
- name : "小王",
- num : 0
- },
- methods: {
- show(){
- return this.name;
- },
- add(){
- this.num++;
- }
- },
- beforeCreate(){//生命周期函数-创建vue实例前调用
- console.log("=============beforeCreate==========");
- console.log("数据模型/数据池的数据是否加载/使用?[no]", this.name, " ", this.num);
- // 会报错:Error in beforeCreate hook: "TypeError: this.show is not a function"
- //console.log("自定义方法是否加载/使用?[no]", this.show());
- console.log("用户页面dom是否加载/使用?[yes]", document.getElementById("num"));
- console.log("用户页面dom是否被渲染?[no]", document.getElementById("num").innerText);
- },
- created() {//生命周期函数-创建vue实例
- console.log("=============created==========");
- console.log("数据模型/数据池的数据是否加载/使用?[yes]", this.name, " ", this.num);
- console.log("自定义方法是否加载/使用?[yes]", this.show());
- console.log("用户页面dom是否加载/使用?[yes]", document.getElementById("num"));
- console.log("用户页面dom是否被渲染?[no]", document.getElementById("num").innerText);
- //可以发出Ajax
- //接收返回的数据
- //再次去更新data数据池的数据
- //编译内存模板结构
- //.....
- },
- beforeMount() {//生命周期函数-挂载前
- console.log("=============beforeMount==========");
- console.log("数据模型/数据池的数据是否加载/使用?[yes]", this.name, " ", this.num);
- console.log("自定义方法是否加载/使用?[yes]", this.show());
- console.log("用户页面dom是否加载/使用?[yes]", document.getElementById("num"));
- console.log("用户页面dom是否被渲染?[no]", document.getElementById("num").innerText);
-
- },
- mounted() {//生命周期函数-挂载后
- console.log("=============mounted==========");
- console.log("数据模型/数据池的数据是否加载/使用?[yes]", this.name, " ", this.num);
- console.log("自定义方法是否加载/使用?[yes]", this.show());
- console.log("用户页面dom是否加载/使用?[yes]", document.getElementById("num"));
- console.log("用户页面dom是否被渲染?[yes]", document.getElementById("num").innerText);
-
- },
- beforeUpdate() {//生命周期函数-数据池数据更新前
- console.log("=============beforeUpdate==========");
- console.log("数据模型/数据池的数据是否加载/使用?[yes]", this.name, " ", this.num);
- console.log("自定义方法是否加载/使用?[yes]", this.show());
- console.log("用户页面dom是否加载/使用?[yes]", document.getElementById("num"));
- console.log("用户页面dom数据是否被更新?[no]", document.getElementById("num").innerText);
- //验证数据==>修正
- // if(this.num < 10 ) {
- // this.num = 8;
- // }
- },
- updated() {//生命周期函数-数据池数据更新后
- console.log("=============updated==========");
- console.log("数据模型/数据池的数据是否加载/使用?[yes]", this.name, " ", this.num);
- console.log("自定义方法是否加载/使用?[yes]", this.show());
- console.log("用户页面dom是否加载/使用?[yes]", document.getElementById("num"));
- console.log("用户页面dom数据是否被更新?[yes]", document.getElementById("num").innerText);
-
- }
- })
- </script>
- </body>
- </html>
(2)测试

目前开发模式的问题
(1)开发效率低
(2)不够规范
(3)维护和升级, 可读性比较差
需求: 演示使用 Vue 脚手架进行模块化开发, 输入不同的 url, 切换不同页面.
Vue Cli 文档地址: https://cli.vuejs.org/zh/
(1)搭建 Vue 脚手架工程,需要使用到 NPM(node package manager), npm 是随 nodejs 安装 的一款包管理工具, 类似 Maven。所以需要先安装 Nodejs
(2)为了更好兼容 ,这里安装 node.js10.16.3(因为这里 只是演示 Vue 脚手架工程),后面进行 Vue3 的脚手架工程搭建, 再对 Node 升级
(3)如果以前安装过 node.js , 为防止版本冲突,先卸载之, 如果你没安装 nodejs, 就不用管
卸载步骤如下
打开控制面板,点击卸载程序

搜索node,点击卸载 (这里需要一段时间,耐心等待)
再次测试,卸载成功

(4)下载 node.js10.16.3 地址: https://nodejs.org/en/blog/release/v10.16.3/
往下翻找到电脑相应的配置进行下载
(5)下载完成之后 , 双击进行安装,直接下一步即可(可根据自己来选择安装路径,路径不要有空格、中文、特殊字符)
(6)验证是否安装成功, 如果看不到, 退出 cmd, 重新开一个窗口测试即可

(7)先删除以前的 cli 版本<不论是之前未下载或没有下载>(cmd中执行下面命令)
npm uninstall vue-cli -g

(8)安装淘宝镜像-cnpm
npm install -g cnpm@7.1.1 --registry=https://registry.npm.taobao.org

说明npm 和 cnpm 的区别
安装成功之后需要给cnpm配置环境变量,找到cnpm.cmd,我的是在D:\software\nodejs\node_cache
接下来,配置环境变量:
1. 右键点击计算机图标,选择“属性”。
2. 在弹出的窗口中,点击“高级系统设置”。
3. 在“系统属性”对话框中,转到“高级”选项卡,然后点击“环境变量”按钮。
4. 在“环境变量”窗口中,找到“系统变量”部分的“Path”变量,然后点击“编辑”。
5. 在“编辑环境变量”对话框中,点击“新建”并添加`cnpm.cmd`所在目录的完整路径,例如`D:\software\nodejs\node_cache`。
6. 记得在每个路径之间用英文分号(`;`)隔开。如果你已经有其他路径,确保在新路径前加上分号。
7. 点击“确定”关闭所有对话框,完成环境变量的修改。
(9) 安装 webpack 和 webpack-cli
npm install webpack@4.41.2 webpack-cli -D

(10)安装vue脚手架
cnpm install -g @vue/cli@4.0.3

(11)确认 Vue-Cli 版本
vue -V

(12)创建目录 vue_project, 并 cmd 到该目录
(13)使用 webpack 创建 vue 脚手架项目 (如果出现了 downloading template....,
- //安装一个全球插件
- npm install -g @vue/cli-init
-
- vue init webpack vue_project_start


(14)运行我们的vue项目
- cd vue_project_start
- npm run dev

(15)浏览器: http://localhost:8080
(1)使用 crtl+c 终止项目

(2)将 Vue 脚手架项目,直接拖到 IDEA,就可以打开
(3)配置 NPM






当我们输入 http://localhost:8080 , 你看到这个页面时怎么来的,这里涉及到如下文件
执行流程如下

(1)创建 vue_project\vue_project_quickstart\src\components\Yss.vue
- <template>
- <div>
- <h1>{{mes}}</h1>
- <table>
- <tr>
- <td>第1行第1列</td>
- <td>第1行第2列</td>
- <td>第1行第3列</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/2.png"></td>
- <td>第5行第3列</td>
- </tr>
- </table>
- </div>
- </template>
-
- <script>
- export default {
- name: "Yss",
- data(){
- return {
- mes : "Welcome to Yss"
- }
- }
- }
- </script>
-
- <!--css样式-->
- <style scoped>
- div {
- width: 900px;
- background-color: aliceblue;
- margin: 0 auto;
- }
- table,tr,td{
- border: 1px solid red;
- /*width: 600px;*/
- border-collapse:collapse;
- /*height: 50px;*/
- }
- table {
- margin: 0 auto;
- width: 600px;
- height: 380px;
- }
- h1 {
- color: red;
- }
- </style>
(2) 在 vue_project\vue_project_quickstart\src\router\index.js 添加路由
- {
- path: '/yss',
- name: 'Yss',
- component : Yss
- }
(3)把 vue_project\vue_project_quickstart\src\App.vue 默认logo注销

(4) 浏览器 http://localhost:8080/#/yss
(1)ElementUI 官网: https://element.eleme.cn/#/zh-CN
(2)一句话: ElementUI 是组件库,网站快速成型工具
(3)vue2 使用的是 ElementUI 组件库,vue3 使用的是 ElementPlus 组件库
在 Vue2 项目中, 使用 ElementUI 组件
(1)安装 element-ui 组件库, cmd 下进入到项目,指令 npm i element-ui@2.12.0 , 这里指定了版本

(2)修改 vue_project\vue_project_quickstart\src\main.js ,引入elementUI组件库
- // 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.vue'
- import router from './router/index.js'
- // 引入elementUI组件库
- import ElementUI from 'element-ui';
- import 'element-ui/lib/theme-chalk/index.css';
-
- //使用ElementUI插件
- Vue.use(ElementUI);
-
- Vue.config.productionTip = false
-
- /* eslint-disable no-new */
- new Vue({
- el: '#app',
- router: router, //指定router
- components: {
- 'App': App
- },
- template: '
' - })
(3)修 改 vue_project\vue_project_quickstart\src\components\Yss.vue , 引 入 element-ui 按钮组件, 从文档拷贝即可


(3)页面效果
(1)axios 是独立于 vue 的一个项目,不是 Vue 的一部分
(2)axios 通常和 Vue 一起使用,实现 Ajax 操作
(3)Axios 是一个基于 promise 的 HTTP 库
(4)学习文档:https://javasoho.com/axios/
(1)使用 axios 需要引入 axios 库文件
(2)可以直接引入
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
(3)也可以下载 axios.min.js ,在本地引入

下载方式:在页面 https://unpkg.com/axios/dist/axios.min.js 中右键另存为即可
(1) 新建一个 javascript 项目

(2)在该项目下创建 data/response_data.json
- {
- "success": true,
- "message": "成功",
- "data": {
- "items": [
- {
- "name": "牛魔王",
- "age": 800
- },
- {
- "name": "红孩儿",
- "age": 500
- },
- {
- "name": "蜈蚣精",
- "age": 200
- }
- ]
- }
- }
(3)将下面两个js文件复制到项目中(已附在文章顶部)
(4)创建 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="1" width="200">
- <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>
- 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在vue生命周期函数created() 中调用
- */
- axios.get("http://localhost:63342/axios/data/response_data.json")
- .then(responseData => {
- 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.item= ", responseData.data.data.items)
- //将妖怪列表数组信息, 绑定到 data数据池的 monsterList
- this.monsterList = responseData.data.data.items;
- })
- .catch(err => {
- console.log("异常=", err)
- })
- }
- },
- created() {
- this.list();
- }
- })
- </script>
- </body>
- </html>
(5)测试
(1)将 JSON 对象转成字符串 JSON.stringify(response)
(2)格式化输出 JSON 字符串,方便观察分析。到 https://www.json.cn/
(3)发生多次 ajax 请求的方式和 promise 相同