vue 从入门到精通之【vue数据视图】(一)

371 阅读6分钟

vue

Vue是"渐进式框架":vue.min.js只包含了vue的核心内容【例如:options api 、数据处理、template模板视图解析等操作】;真实项目中我们还会根据需求,导入

vuex实现公共状态管理

vue-router 实现SPA(single page application)单页面应用

element-ui/antdv/iview/vant/cube基于这些UI组件库快速创建项目

axios 实现数据通信

@vue/cli 基于vue的脚手架创建工程化项目

Vue是基于MVVM模式构建的框架,它本身实现了viewModel层实现监听数据/视图的变化,从而去渲染视图/修改数据。所有我们学习vue主要考虑两条主线:

  • Model数据层
  • View视图层

mvvm 和 mvc

  • vue MVVM双向数据绑定
  • angular (简称:ng) MVVM
  • react MVC 单向数据绑定

虚拟 DOM

Model数据层

指定视图:3种方式

let vm = new Vue({
	// 指定视图
	el: "#app"
});
let vm = new Vue({});
vm.$mount('#app');
let vm = new Vue({
	render:h=>{},
	template: `
	<div>
	最后把数据渲染在这个视图中
	</div>
	`
});

构建数据模型【需要在视图中渲染数据】

  1. 设置的数据直接挂载到vm实例对象上,vm.msg;
  2. 挂载到实例上的东西能够直接在视图中使用;
  3. 后期更改数据,vue会监听到数据的更改,通知视图按照最新的数据重新渲染;我们把修改后视图会重新渲染的数据称之为响应式数据(状态)
let vm = new Vue({
	// 指定视图
	// el: "#app",
	// 构建数据模型【需要在视图中渲染数据】
	/*
	(1)设置的数据直接挂载到vm实例对象上,vm.msg;
	(2)挂载到实例上的东西能够直接在视图中使用;
	 (3)后期更改数据,vue会监听到数据的更改,通知视图按照最新的数据重新渲染;我们把修改后视图会重新渲染的数据称之为响应式数据(状态)

	*/
	data: {
		msg: 'hello world1'
	}
});
vm.text = 'zf';//也是挂到实例上 vm.text
vm.$mount('#app');
setTimeout(() => {
	// 后期更改数据,vue会监听到数据的更改,通知视图按照最新的数据重新渲染;我们把修改后视图会重新渲染的数据称之为响应式数据(状态)
	vm.msg = '111 world1';//修改msg值,并且重新渲染
	// 修改后数据并不会重新渲染=>非响应数据
	vm.text = '3231';//修改text

	vm.$forceUpdate();//这个方法会强制让视图重新渲染
}, 1000)

响应式数据VS非响应式数据

  1. 都可以修改值
  2. 响应式数据在值修改之后,会通知视图重新渲染,因为其基于Object.defineProperty对其做了get/set劫持;当我们修改数据的时候,会触发set函数,在set函数中一方面会把值修改,一方面通知视图渲染;

在vue的项目中,我们只需要展开实例,看哪些数据做了get/set,做了劫持的数据就是响应数据。

new Vue的时候,在data中指定的数据,vue默认就会对其做了劫持处理,所有数据式响应式的;自己直接挂在实例上的式非响应式数据。

  • 在vue开发中,我们把需要的数据一般都写在data中,(哪怕现在不用,我们也在data中初始化一下),目的是让这些数据变成响应式数据
  • 而且对data中所有层级做深层次的监听劫持
  • 对于数组来讲,数组本身会做劫持,但是数组中的每一个索引项并没有做劫持,如果内容是对象,还会做劫持;修改数组值会触发重新渲染vm.arr=100,修改数组堆内存中的信息,不会触发重新渲染vm.arr[0]=100
    • vue为了解决这个问题,把数组中的7个方法(push/pop/shift/unshift/splice/sort/reverce)进行了重写,后期我们操作这7个方法,不仅可以修改数据中的某一项的内容,而且也会触发视图的重新渲染。

修改数据如何让视图重新渲染

vue.prototype

  • vm.$forceUpdate();//这个方法会强制让视图重新渲染;
  • vm.set([object],[key],[value]):针对于data中某个对象开始没有初始化某个属性,后期才加的(这个属性默认式非响应式的,该值视图不会重新渲染);$set可以在后续把对象中的这个属性设置为响应式的。

vue 实例

Vue 的实例:在入口文件中,基于 new Vue 创建的一个实例 “vm”

_vnode:编译完的虚拟 DOM 对象「最后 vue 内部会把这个虚拟 DOM 对象,基于 DOM-DIFF 后,变为真实的 DOM,插入到页面中」

$children:记录所有子元素/子组件的实例,它是一个数组

el:编译后的内容挂载到这个容器中 基于options:{el:'#app'}指定,或者基于vm.$mount('#app')指定

$attrs:

$listeners:

$options:存储当前实例的一些配置项 components / directives / filters / render ...

$parent:获取其父元素/父组件的实例

$refs:存储设置的所有的 ref 的值「通过 ref 获取 DOM 元素,直接操作 DOM,也可以基于它获取调用的子组件实例」

$root:根 DOM 元素/实例

$scopedSlots:存储所有的作用域插槽

$slots:存储所有的插槽

$data:所有观察的数据对象

$props:所有接收的属性对象

Vue视图层

template中存在大量的指令,用来构建视图和完成相关的效果

指令

   v-text:把数据渲染到指定的容器中(真实开发中我们一般都是基于小胡子语法{{}}处理)v-html:可以识别html字符串,可以将字符串的标签进行渲染,其余两种方式只能当作字符渲染

   v-html

   v-show:[boolen]控制元素的显示隐藏(原理:控制display=none/block);不管结果是true还是false,元素都渲染出来了,只是display的值不同;
   
   v-if:[boolen]也可控制元素的显示隐藏,和v-show不一样,如果值是false元素是不进行渲染的(页面中没有这个元素),只有结果是true元素才会进行渲染
   
   ---对于频繁控制显示隐藏的操作,我们应该使用v-show,如果使用v-if会频繁的创建和销毁,这样性能较差;非频繁操作下,我们可以使用v-if,这样对于v-if=false的元素可以不进行编译渲染,提高编译渲染的速度!!
   
   v-else-if
   
   v-else
   
   v-for 「循环渲染的元素,需要设置唯一的key属性」
   
   v-on 实现事件绑定「简写 @」事件="要执行的方法"  缩写:@事件="方法" 原理:基于DOM2事件绑定实现的 addEventListener【好处:后期自己获取这个DOM元素对象进行事件绑定,也不会和@click绑定的方法冲突】
   
   v-bind 给某个属性动态绑定值 「简写 :」
   
   v-model 表单元素实现双向数据绑定「监听视图的改变,控制数据更新」
     
     a. 把状态值赋值给文本框的value
     
     b. 基于input事件,监听文本框内容改变,当内容改变的时候,去修改对应的状态值
   
   v-slot 插槽「简写 #」
   
   [下面的两个指令可以做优化]
   
   v-pre 编译的时候,有这个指令的元素/组件是无需进行编译的,真实项目中,我们完全可以把一些"静态内容"不进行任何编译,以此来优化视图编译的速度。
   
   v-once 只有第一次元素/组件进行渲染,后期重新渲染的时候,直接跳过编译,不进行渲染,适用于第一次动态绑定,后期不会再更新的内容
   
   v-cloak 在非工程化的vue项目中,在js没有加载出来之前,页面会呈现原始的语法({{}}),只有js加载完成,才能把template语法编译为真实DOM渲染到页面中;为了防止这种效果,在js没有编译之前是隐藏的,js编译完再让容器呈现出来,此时看到的都是编译好的效果。[v-colck]{display:none;}
   

小胡子语法

{{需要渲染的数据内容}}

事件和表单的修饰符

[事件] @click.stop.prevent="handle"

 .stop 阻止冒泡传播
 .prevent 阻止默认行为
 .capture 在捕获阶段触发
 .self 只有event.target事件源是本身自己操作的元素时候触发
 .once 事件只执行一次,第一次执行完移除事件绑定
 .passive
<div @click.self="handle">
  <button>按钮</button>
</div>
//只有点击的元素是div,才会执行handle;点击button,因为冒泡传播机制,也会触发div的点击行为,但是因为设置了.self修饰符,所以handle不执行!!

按键修饰符 @keyup.enter

  .enter  按下Enter键   改写为 .13
  .tab
  .delete
  .esc
  .space
  .up
  .down
  .left
  .right
  还可以自定义按键修饰符  Vue.config.keyCodes.f1 = 112 -> @keyup.f1='handle'

基于系统修饰符,实现组合按键 @keyup.alt.67的意思是Alt+C

   .ctrl
   .alt
   .shift
   .meta
   .exact 控制只有按下这个键才会触发「不能按其他键 精准控制」

[表单] input v-model.lazy='name'

   .lazy 把v-model默认是基于input事件监听内容改变的,改为基于change事件监听 
       ■ 【input】只要正在输入就会触发,不一定输入的内容进入到了文本框;
       ■ 【change】内容已经进入文本框,按下enter才会触发;比input性能消耗低,流畅度也低。
   .number 把输入的值{字符串类型}转换为数字类型 文本框默认输入的内容是字符串,.number vue内部会把其变成数字【如果出现非有效数字,则会把其干掉】
   .trim 去除字符串的首尾空格
   select下拉框 v-model="city"
       ■ 拿city状态值和option中的value做比较,和谁一样,就默认选中谁
       ■ 拿监听下拉框的change事件,选中的是谁,就把哪一项的value赋值给city状态
  在radio单选框中 v-model="sex"
      ■ 会把v-model 状态值相同的作为同一组,一组中只能选中一个【可以自己设定name】;
      ■ 会根据sex状态值和value值做对比,相同的则有选中状态;
      ■ 监听每一个radio的change事件,把选定radio的value值赋值给状态sex
  在checkbox单选框中 v-model="hobby"
    

给元素设置样式 class style

  • :class="{box:true,active:true/false}" active是class的样式类名,它的值true/false决定元素是否拥有这个样式类名;
  • :class="['box',num>10?'active':'']";
  • style="color:red" :style="color:'red',fontSize:num>10?'20px':'14px'"