Vue - part1

1. MVVM 模式

1.1 MVC 模式

MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式。这种模式用于应用程序的分层开发

  • Model (模型) : 代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。
  • View(视图) : 代表模型包含的数据的可视化。
  • Controller(控制器) :控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。

1.2 MVC 模式实现

创建一个作为模型的 Student 对象StudentView 是一个把学生详细信息输出到控制台的视图类,StudentController 是负责存储数据到 Student 对象中的控制器类,并相应地更新视图 StudentView。MvcDemo 作为演示类。

  1. 创建模型
public class Student {
	private String id;
	private String name;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
  1. 创建视图
public class StudentView {
	public void printStudentDetails(String studentName,String studentId){
		System.out.println("Student: ");
		System.out.println("	Name: " + studentName);
		System.out.println("	Id: " + studentId );
	}
}
  1. 创建控制器
public class StudentController {
	private Student model;
	private StudentView view;
	
	public StudentController(Student model, StudentView view) {
		super();
		this.model = model;
		this.view = view;
	}
	
	public void setStudentName(String name){
		model.setName(name);
	}
	
	public String getStudentName(String name){
		return model.getName();
	}
	
	public void setStudentId(String id){
		model.setId(id);
	}
	
	public String getStudentId(String name){
		return model.getId();
	}
	
	public void updateView(){
		view.printStudentDetails(model.getName(), model.getId());
	}
}
  1. 使用 StudentController 方法来演示 MVC 设计模式的用法。
public class MvcDemo {
	public static void main(String[] args) {
		Student model = retrieveStudentDatabase();
		StudentView view = new StudentView();
		StudentController controller = new StudentController(model,view);
		controller.updateView();
	}	
	
	private static Student retrieveStudentDatabase(){
		Student student = new Student();
		student.setId("2018303858");
		student.setName("邹小胖");
		return student;
	}
}
  1. 输出页面
    在这里插入图片描述

1.3 MVVM模式

MVVM(Model-View-ViewModel)是一种软件架构设计模式,是一种简化用户界面的事件驱动编程方式。

  • View:视图层,也就是用户界面。前端主要由 HTML 和 CSS 来构建。
  • Model :数据模型,泛指后端进行的各种业务逻辑处理和数据操控,主要围绕数据库系统展开。
  • ViewModel :视图数据层。在这一层,前端开发者对从后端获取的Model 数据进行转换处理,做二次封装,以生成符合 View 层使用预期的视图数据模型。

View 层展现的不是 Model 层的数据,而是 ViewModel 的数据,由 ViewModel 负责与Model 层交互

MVVM 的核心是 ViewModel 层,负责转换 Model 中的数据对象来让数据变得更容易管理和使用,其作用如下:

  • 该层向上与视图层进行双向数据绑定
  • 向下与 Model 层通过接口请求进行数据交互

ViewModel 所封装出来的数据模型包括视图的状态和行为两部分,而 Model 层的数据模型是只包含状态的。
– 比如页面的这一块展示什么,那一块展示什么这些都属于视图状态(展示)
– 页面加载进来时发生什么,点击这一块发生什么,这一块滚动时发生什么这些都属于视图行为(交互)

1.4 MVVM 模式的实现者

  • Model:模型层,在这里表示 JavaScript 对象
  • View:视图层,在这里表示 DOM(HTML 操作的元素)
  • ViewModel:连接视图和数据的中间件,Vue.js 就是 MVVM 中的 ViewModel 层的实现者

在 MVVM 架构中,是不允许 数据 和 视图 直接通信的,只能通过 ViewModel 来通信,而 ViewModel就是定义了一个 Observer 观察者

  • ViewModel 能够观察到数据的变化,并对视图对应的内容进行更新
  • ViewModel 能够监听到视图的变化,并能够通知数据发生改变

2. Vue 初步认识

2.1 声明式编程

  1. 创建一个div元素,设置id属性
  2. 定义一个vue对象,将div挂载在vue对象上
  3. 在vue对象内定义变量message,并绑定数据
  4. 将message变量放在div元素上显示
  5. 修改vue对象中的变量message,div元素数据自动改变

2.2 Vue 实例

通过 new 一个 Vue 来创建一个实例,Vue 是一个构造函数。

当创建一个 Vue 实例时,可以传入一个选项对象(options),定义挂载元素、数据、方法等。

options选项:

  • el挂载元素:

    • 类型:String / HTMLElement
    • 作用:决定之后Vue实例会管理哪一个DOM
    • 注:该元素不能是 html 或 body
  • data数据:

    • 类型:Object / Function
    • 作用:Vue实例对应的数据对象
    • 当一个 Vue 实例被创建时,它向 Vue 的响应式系统中加入了其 data 对象中能找到的所有的属性。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
  • methods方法:

    • 类型:{ [key:string]: Function }

    • 作用:定义属于Vue的一些方法

    • 注:methods 中的方法名不能与 data 中的属性名重复

2.3 Vue实现(count计数器)

  1. 创建一个 HTML 文件 count.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>计数器</title>
</head>
<body>

</body>
</html>
  1. 引入 Vue.js
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
  1. 创建一个 Vue 实例
<script>
  const vue = new new Vue({
    // 绑定元素的Class
    el: ".div",
    // 数据对象中有一个名为 count 的属性,并设置了初始值 0
    data: {
      count: 0
    },
    // 有两个实现方法
    methods: {
      increament: function(){
        this.count++;
      },
      decreament: function(){
        this.count--;
      }
    }
  })
</script>
  1. 将数据绑定到页面元素 (视图层)
    只需要在绑定的元素中使用 双花括号{{ variable }} 将 Vue 创建的名为 count 属性包裹起来,即可实现数据绑定功能
<div class="div">
  <h2>当前计数:{{count}}</h2>
  <button @click="increament">+</button>
  <button @click="decreament">-</button>
</div>
  1. 由于 vue 是声明式编程,所以在开发者模式中console控制台,改变vue对象的count值( vm.varible 修改值),页面显示也随之改变。
    请添加图片描述
    请添加图片描述

3. 语法

3.1 插值语法

v-once

在某些情况下,我们可能不希望界面中 Mustach 中的值随意的跟随改变,就可以使用一个 Vue 的指令:v-once

  • 该指令后面不需要跟任何表达式
  • 该指令表示元素和组件只渲染一次,不会随着数据的改变而改变
<div class="app">
  <h2>{{message}}</h2>
  <h2 v-once>{{message}}</h2><!-- 只会渲染一次 -->
</div>
<script>
  const vue = new Vue({
    el: '.app',
    data: {
      message: '邹小胖'
    }
  })
</script>

v-once

v-html

从服务器请求到的数据本身就是一个 HTML 代码,如果直接通过 {{}} 来输出,会将 HTML 代码也一起输出,但如果希望按照 HTML 格式进行解析,并且显示对应的内容,可以使用 v-html 指令

v-html 指令后面往往会跟上一个 string 类型,会将 string 的 html 解析出来并且进行。
v-html

v-text

v-text 作用和 Mustache 比较相似,都是用于将数据显示在界面中,会覆盖原来的内容

v-text 通常情况下,接受一个 string 类型。
v-text

v-pre

v-pre 用于跳过这个元素和它子元素的编译过程,显示原本的 Mustache 语法,将代码原封不动的解析出来
v-pre

v-cloak

隐藏未编译的 Mustache 标签直到实例准备完毕。

主要用于单纯引入 vue.js 来使用时,会闪现出花括号

[v-cloak] {
  display: none;
}

可以直接放在最外层的 #app 上,也可以单个放在其内部的某个标签上

<div v-cloak id="app">

</div>

v-cloak


3.2 基础语法

v-bind 动态绑定sytle

v-bind 指令动态绑定属性,用于绑定一个或多个属性值。

<div class="app">
  <h5 v-bind:title="message"> 鼠标悬停几秒钟查看此处动态绑定状态 </h5>
  <a v-bind:href="aHref">vue.js官网</a>
</div>
<script>
  const vue = new Vue({
    el: '.app',
    data: {
      message: '邹小胖',
      aHref: 'https://cn.vuejs.org/'
    }
  })
</script>

语法糖(简写方式): 省略v-bind,直接写:(冒号)

<h5 :title="message"> 鼠标悬停几秒钟查看此处动态绑定状态 </h5>
<a :href="aHref">vue.js官网</a>

v-bind


v-if 条件判断

条件判断语句:

  • v-if
  • v-else-if
  • v-else
<div id="app">
  <h4 v-if="type === 'A'">A</h4>
  <h4 v-else-if="type === 'B'">B</h4>
  <h4 v-else-if="type === 'C'">C</h4>
  <h4 v-else>who?</h4>   
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script>
  const vue = new Vue({
    el: '#app',
    data: {
      type: 'A'
    }
  })
</script>

初始页面显示A,后在控制台分别输入vue.type=‘B’、‘C’、‘D’,会分别显示B、C、who?


v-on 事件监听

事件监听:在前端开发中,我们需要经常和用户进行交互,这个时候,就必须监听用户发生的事件,比如点击、拖拽、键盘事件等,在 Vue 中监听事件使用 v-on 指令。
语法糖: 省略v-on,直接写@。以 2.3 count计数器为例:

<!-- 常规写法 -->
<button v-on:click="increament">+</button>
<!-- 语法糖形式 -->
<button @click="decreament">-</button>

当通过 methods 中定义方法,以 @click 调用时,需要注意参数问题:

  • 如果该方法不需要额外参数,那么方法后的 () 可以不添加。
  • 如果方法本身中有一个参数,那么会默认将原生事件 event 参数传递进去。
    例:分别点击按钮1.2.3,显示内容如下图
<div class="app">
  <!-- undefined -->
  <button @click="btnClick()">按钮1</button>
  <!-- 123 -->
  <button @click="btnClick(123)">按钮2</button>
  <!-- MouseEvent对象:vue会默认将浏览器产生的event对象作为参数传到方法中 -->
  <button @click="btnClick">按钮3</button>
</div>
<script>
  const vue = new Vue({
    el: '.app',
    data: {
      count: 0
    },
    methods: {
      btnClick(num) {
        console.log(num);
      }
    }
  })
</script>

按钮1、2、3

  • 如果需要同时传入某个参数,同时需要 event 时,可以通过 $event 传入事件。
<div class="app">
  <button @click="btnClick(2,$event)">按钮</button>
</div>
<script>
  const vue = new Vue({
    el: '.app',
    data: {
      count: 0
    },
    methods: {
      btnClick(num,event) {
        console.log(num,event);
      }
    }
  })
</script>

num,event


v-for 循环

当我们有一组数据需要进行渲染时,我们就可以使用 v-for 来完成。
v-for 的语法类似于 JavaScript 中的 for 循环:item in items

  • 遍历数组
<div class="app">
  <ul>
    <li v-for="item in idols">{{item}}</li>
    <br>
    <li v-for="(item,index) in idols">{{index+1}}.{{item}}</li>
  </ul>
</div>
<script>
  const vue = new Vue({
    el: '.app',
    data: {
      idols: ['连淮伟','王琳凯']
    }
  })
</script>
  • 遍历对象
<div class="app">
  <ul>
    <li v-for="item in infos">{{item}}</li><br>
    <li v-for="(item,key) in infos">{{key}}:{{item}}</li> <br>
    <li v-for="(item,key,index) in infos">{{index+1}}.{{key}}:{{item}}</li>
  </ul>
</div>
<script>
  const vue = new Vue({
    el: '.app',
    data: {
      infos: {
        name: '邹小胖',
        age: 20,
        gender: '女',
      }
    }
  })
</script>

infos

v-model 表单绑定

v-model 指令来实现表单元素和数据的双向绑定
v-model解析:当我们在输入框输入内容时,因为 input 中的 v-model 绑定了 message,所以会实时将输入的内容传递给 message,message 发生改变,当 message 发生改变时,因为使用了 Mustache 语法,所以将 message 的值插入到 DOM 中,所以 DOM 会发生响应的改变,所以通过 v-model 实现了双向绑定。

  • 原理:
    v-model 其实是一个语法糖,它的背后本质上是包含两个操作:
    ① v-bind 绑定一个 value 属性
    ②v-on 指令给当前元素绑定 input 事件
<input type="text" v-model="message">
<!-- 等同于 -->
<input type="text" 
       :value="message" 
       <!-- event.target.value( ) 获取当前文本框的值(由事件触发时)-->
       @input="message = $event.target.value">
  • 结合radio使用
    radio
<div class="app">
  <label for="male">
    <input type="radio" v-model="gender" id="male" value=""></label>
  <label for="female">
    <input type="radio" v-model="gender" id="female" value=""></label>
  <h3>您选择的性别是:{{gender}}</h3>
</div>
<script>
  const app = new Vue({
    el: '.app',
    data: {
      gender: '男'
    }
  });
</script>
  • 结合checkbox使用(单选框)单选框
<div class="app">
  <!-- checkbox单选框 -->
  <label for="licence">
    <input type="checkbox" v-model="isAgree" id="licence">同意协议
  </label>
  <h3>您的选择是:{{isAgree}}</h3>
  <button :disabled="!isAgree">下一步</button>
</div>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '.app',
    data: {
      isAgree: false
    }
  });
</script>
  • 结合checkbox使用(多选框)
    在这里插入图片描述
<div class="app">
  <label for="sing">
    <input type="checkbox" v-model="hobbies" value=""></label>
  <label for="jump">
    <input type="checkbox" v-model="hobbies" value=""></label>
  <label for="rap">
    <input type="checkbox" v-model="hobbies" value="rap">rap
  </label>
  <label for="basketball">
    <input type="checkbox" v-model="hobbies" value="篮球">篮球
  </label>
  <h3>您的爱好是:{{hobbies}}</h3>
</div>
<script>
  const app = new Vue({
    el: '.app',
    data: {
      hobbies: []
    }
  });
</script>
  • 结合select使用(下拉框)
    下拉框
<div class="app">
  <!-- 选择一个值 -->
  <h3>请选择最喜欢的水果:</h3>
  <select name="" v-model="fruit">
    <option value="苹果">苹果</option>
    <option value="香蕉">香蕉</option>
    <option value="橘子">橘子</option>
    <option value="西瓜">西瓜</option>
    <option value="榴莲">榴莲</option>
  </select>
  <h3>您最喜欢的水果是:{{fruit}}</h3><br>

  <!-- 选择多个值 -->
  <h3>请选择喜欢的水果(可多选):</h3>
  <select name="" v-model="fruits" multiple>
    <option value="苹果">苹果</option>
    <option value="香蕉">香蕉</option>
    <option value="橘子">橘子</option>
    <option value="西瓜">西瓜</option>
    <option value="榴莲">榴莲</option>
  </select>
  <h3>您最喜欢的水果是:{{fruits}}</h3>
</div>
<script>
  const app = new Vue({
    el: '.app',
    data: {
      fruit: '苹果', //默认选中苹果
      fruits: []
    }
  });
</script>
  • input值绑定
    input值绑定
<div id="app">
  <label v-for="item in fruitList" :for="item">
    <input type="checkbox" :value="item" :id="item" v-model="fruit">{{item}}
  </label>
  <h3>你喜欢的水果:{{fruit}}</h3>
</div>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      fruitList: ['西瓜','菠萝','柚子','香蕉','草莓'],
      fruit: []
    }
  });
</script>

4 计算属性 computed

在模板中可以直接通过插值语法显示一些 data 中的数据,但是在某些情况下,可能需要对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示,这时可以使用计算属性 computed

4.1 基本使用

比如:现在有 firstName 和 lastName 两个变量,需要显示完整的名称,可能直接使用空格将其隔开

<h2>{{firstName}} {{lastName}}</h2>

或者使用加号拼接

<h2>{{firstName + '' +lastName}}</h2>

但是如果多个地方都需要显示完整的名称,我们就需要写多个 {{firstName}} {{lastName}}{{firstName + '' +lastName}} ,使代码看上去很不优雅。可以将{{firstName + '' +lastName}} 封装为一个函数,通过函数的方式调用,但其实最佳方案是使用计算属性

<div id="app">
  <!-- 方式1 -->
  <h2>{{firstName}} {{lastName}}</h2>
  <!-- 方式2 -->
  <h2>{{firstName + ' ' + lastName}}</h2>
  <!-- 方式3 -->
  <h2>{{fullName}}</h2> 
  <!-- 方式4 -->
  <h2>{{getFullName()}}</h2>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
<script>
  const vue = new Vue({
    el: '#app',
    data: {
      firstName: 'xiaopang',
      lastName: 'Zou'
    },
    computed: {
      fullName(){
        return this.firstName + ' ' + this.lastName;
      }
    },
    methods: {
      getFullName: function(){
        return this.firstName + ' ' + this.lastName;
      }
    }
  })
</script>

4.2 计算属性的 setter 和 getter

每个计算属性都包含一个 getter 和一个 setter,getter 用来读取值setter 用来设置值(但 setter 不常用)。

<div id="app">
  <h2>{{fullName}}</h2> 
</div>

<script>
  const vue = new Vue({
    el: '#app',
    data: {
      firstName: '邹',
      lastName: '小胖'
    },
    computed: {
      fullName:{
        set: function(newValue) {
          let newName = newValue.split(' ');
          this.firstName = newName[0];
          this.lastName = newName[1];
        },
        get: function() {
          return this.firstName + ' ' + this.lastName;
        }
      }
    }
  })
</script>

邹小胖-->连小伟

4.3 computed 与 methods 的区别

  1. computed 是属性调用,而 methods 是函数调用

  computed 定义的方法,我们是以属性访问的形式调用的,{{computedTest}},但是 methods 定义的方法,我们必须要加上()来调用,如{{methodTest()}}

  1. computed 带有缓存功能,而 methods 没有

  computed 依赖于 data 中的数据,只有在它的相关依赖数据发生改变时才会重新求值。
  我们可以将同一函数定义为一个方法而不是一个计算属性,两种方式的最终结果确实是完全相同的然而,不同的是计算属性是基于它们的响应式依赖进行缓存的,只在相关响应式依赖发生改变时它们才会重新求值,这就意味着只要 text 还没有发生改变,多次访问 getText 计算属性会立即返回之前的计算结果,而不必再次执行函数,而方法只要页面中的属性发生改变就会重新执行。


5. 组件化开发

组件化思想:如果将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展,但如果将一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。

任何的应用都会被抽象成一颗组件树。

5.1 注册组件

  1. 创建组件构造器Vue.extend()

    调用Vue.extend()创建的是一个组件构造器

    通常在创建组件构造器时,传入template代表我们自定义组件的模板。该模板就是在使用到组件的地方,要显示的HTML代码。

  2. 注册组件Vue.component()

    调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称。

    需要传递两个参数:①注册组件的标签名;②组件构造器

  3. 使用组件

    组件必须挂载在某个Vue实例下,否则它不会生效。

在这里插入图片描述注意:以上代码方式创建的组件是全局组件,即可以在多个 vue 的实例下使用,要改为局部组件,需要将注册方法写到具体的某个实例中。


5.2 组件分类

全局组件和局部组件

当我们通过调用 Vue.component() 注册组件时,组件的注册是全局的,这意味着该组件可以在任意 Vue 实例下使用;如果我们注册的组件是挂载在某个实例中, 那么就是一个局部组件。

全局和局部组件

父组件和子组件

组件和组件之间存在层级关系,而其中一种非常重要的关系就是父子组件的关系。
父子组件

5.3 注册组件语法糖

省去了调用Vue.extend() 的步骤,直接使用一个对象来代替。
语法糖注册全局组件和局部组件:

<div class="app">
  <my-cpn1></my-cpn1>
  <my-cpn2></my-cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
    // 1. 注册全局组件的语法糖
    Vue.component('my-cpn1', {
        template: `
            <div>
            <h2>组件标题1</h2>
            <p>组件1中的一个段落内容</p>
            </div>
            `
    })
    const app = new Vue({
        el: '.app',
        // 2. 注册局部组件的语法糖
        components: {
            'my-cpn2': {
                template: `
                    <div>
                    <h2>组件标题2</h2>
                    <p>组件2中的一个段落内容</p>
                    </div>
                    `
            }
        }
    })
</script>

5.4 注册组件模块分离

使用<script>标签

script
使用<template>标签
template

6. 插槽slot

slot 翻译为插槽,插槽的目的是让我们原来的设备具备更多的扩展性,让使用者可以决定组件内部的一些内容到底展示什么

在子组件中,使用特殊的元素 <slot> 就可以为子组件开启一个插槽,该插槽插入什么内容取决于父组件如何使用
slot

6.1 具名插槽

当子组件的功能复杂时,子组件的插槽可能并非是一个,比如我们封装一个导航栏的子组件,可能就需要三个插槽,分别代表左边、中间、右边。这个时候,我们就需要给插槽起一个名字,这就是具名插槽
具名插槽

6.2 slot实操

比如准备制作一个待办事项组件(todo),该组件由待办标题(todo-title)和待办内容(todo-items)组成,但这三个组件又是相互独立的,该如何操作呢?

第一步: 定义一个待办事件的组件

<template id="myCpn">
  <div>
    <div>待办事项</div>
    <ul>
      <li>学习Vue</li>
    </ul>
  </div>
</template>

第二步: 我们需要让待办事项的标题和值实现动态绑定,需要使用slot

  1. 将上面的代码流出两个插槽,即slot
<template id="myCpn">
  <div>
    <slot name="todo-title"></slot>
    <ul>
      <slot name="todo-items"></slot>
    </ul>
  </div>
</template>
  1. 定义一个名为 todo-title 的待办标题组件 和 todo-items 的待办内容组件。
components: {
  'cpn': {
    template: '#myCpn'
  },
  'todo-title': {
    props: ['title'],
    template: '<h4>{{title}}</h4>'
  },
  'todo-items': {
    props: ['item','index'],
    template: '<li>{{index+1}}.  {{item}}</li>'
  }
}
  1. 实例化 Vue 并初始化数据
const app = new Vue({
  el: '#app',
  data: {
    todoItems: ['Java','Python','Html']
  }
}
  1. 将这些值通过插槽插入
<div id="app">
  <cpn>
    <todo-title slot="todo-title" title="邹小胖需学习内容"></todo-title>
    <todo-items slot="todo-items" v-for="(item,index) in todoItems"
                :item="item" :index="index"></todo-items>
  </cpn>
</div>

slot

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值