Vue2学习笔记1——B站

Vue.js 是一款轻量级的前端框架,以其MVVM模式和响应式数据绑定著称。本文深入介绍了Vue的基础知识,包括安装、简单使用、MVVM模式、指令(如v-if、v-for、v-bind和v-on)、计算属性、监听器、以及组件化开发。特别强调了v-model的双向数据绑定和生命周期钩子的理解,帮助开发者快速掌握Vue.js开发。
摘要由CSDN通过智能技术生成

1 vue介绍

Vue渐进式框架:

  • 可以将vue作为应用的一部分嵌入,带来更丰富的交互
  • Core+Vue-router+Vuex:全家桶1

vue特点:

  • 解耦数据和视图
  • 可复用组件
  • 前端路由
  • 状态管理
  • 虚拟DOM

vue.js自底向上逐层应用 ,只关心视图层(HTML+CSS+JS)直观展示,其他交给第三方:

  • 网络通信Axios
  • 页面跳转:vue-router
  • 状态管理:vuex
  • UI:ice.work elementUI AmazeUI iview
  • MV*模式

MVC:同步通信为主:Model View Controller
MVP:异步通信为主:Model View Presenter
MVVM:异步通信为主:Model View ViewModel

  • 构建工具:
    Babel:JS编译工具,主要用于浏览器不支持的ES新特性,比如编译TypeScrip
    Webpack:模块化打包,主要是打包、压缩、合并和按需加载

SOC原则:关注点分离原则
在这里插入图片描述
vue特点:引入计算属性

vue-element-admin:一个后台的前端解决方案

VUE的分层:
在这里插入图片描述
Model层:表示JS对象
VIew层:表示HTML
ViewModel:连接视图和模型的中间件,Vue.js就是MVVM的ViewModel实现者
注意:在MVVM架构中,不允许模型和视图直接通信,只能通过VIewModel来通信,而ViewModel就是定义了一个Observer,他能监听视图变化并通知数据发生改变;他能监听数据变化,并通知视图进行更新

VUE优点:体积小,生产版本:20kb,相比Augular56kb和React44kb,适配移动端好,易上手,文档全,集合Aungualr模块化和React虚拟DOM长处,且有自己的优点:计算属性并且开源

1.1 安装

有三种方式:

  1. cdn引入
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
  1. 下载引入
  2. npm安装(webpack和cli使用)
    注意:不推荐新手直接使用 vue-cli

1.2 简单使用

这里选择下载vue.js文件来引入,引入方式和引入其他js文件一样,放在script标签的src中,注意如果将vue其他代码放到了别的js中,在index入口必须先加载vue的框架,将其他的js放在后面加载!

es6:let和const
let为普通变量,可以重复赋值
const为常量,只能赋值一次
尽量不要使用var

Vue编程方式为声明式:使用声明式开发有利于数据和代码进行分离,数据改变页面自动重新渲染
如:在控制台中输入:app.message="123"则页面显示也被改变,这也称为响应式

案例:声明式渲染{{}}

<!DOCTYPE html>
<html lang="en">
<head>
    <script src="../js/vue.js"></script>
    <title>Document</title>
</head>
<body>
    <div id="app">{{message}}</div>
</body>
<script>
    const app = new Vue({
        el:"#app",
        data:{
            message:"abc"
        }
    })
</script>
</html>

案例:加减计数器(属性绑定v-bind和事件v-on

<!DOCTYPE html>
<html lang="en">
<head>
    <script src="../js/vue.js"></script>
</head>
<body>
    <div id="app">
        <h2 v-bind:title="message">当前计数:{{counter}}</h2>
        <button v-on:click="add">+</button>
        <button v-on:click="sub">-</button>
    </div>
</body>
<script>
    const app = new Vue({
        el:"#app",
        data:{
        	message:"123",
            counter:0
        },
        methods:{
            add: function(){
                this.counter++
            },
            sub: function(){
                this.counter--
            }
        }
    })
</script>
</html>

注意:v-on:click可以简写为@click
注意:v-开头的称为指令,是Vue提供的特殊属性

案例:条件表达式v-if

<div id="app-3">
  <p v-if="seen">现在你看到我了</p>
</div>
<script>
	var app3 = new Vue({
	  el: '#app-3',
	  data: {
	    seen: true
	  }
	})
</script>

案例:循环表达式

<div id="app-4">
  <ol>
    <li v-for="todo in todos">
      {{ todo.text }}
    </li>
  </ol>
</div>
<script>
	var app4 = new Vue({
	  el: '#app-4',
	  data: {
	    todos: [
	      { text: '学习 JavaScript' },
	      { text: '学习 Vue' },
	      { text: '整个牛项目' }
	    ]
	  }
	})
</script>

注意:app4.todos.push({ text: '新项目' })可以动态增加列表项目

this.message = this.message.split(‘’).reverse().join(‘’)
可以将字符串反转

案例:组件化开发

<div id="app-7">
  <ol>
    <!--
      现在我们为每个 todo-item 提供 todo 对象
      todo 对象是变量,即其内容可以是动态的。
      我们也需要为每个组件提供一个“key”,稍后再
      作详细解释。
    -->
    <todo-item
      v-for="item in groceryList"
      v-bind:todo="item"
      v-bind:key="item.id"
    ></todo-item>
  </ol>
</div>
<script>
Vue.component('todo-item', {
  props: ['todo'],
  template: '<li>{{ todo.text }}</li>'
})

var app7 = new Vue({
  el: '#app-7',
  data: {
    groceryList: [
      { id: 0, text: '蔬菜' },
      { id: 1, text: '奶酪' },
      { id: 2, text: '随便其它什么人吃的东西' }
    ]
  }
})
</script>

1.3 MVVM

分析M V VM
view层:el指定的模板(就是html)
model层:app里的js数据,一般是data属性
viewmodel层:即app对象,监听数据,且双向绑定,改变app里的数据,页面同时会改变(Proxy原理)

1.4 option之生命周期钩子

在new一个Vue对象时,需要传递一个option对象,该对象有很多属性可以定义
vue八大对象:

  • el 指示浏览器从哪里开始解析vue语法,可以是字符串或者html节点
  • data 数据,可以是对象或者函数(组件中data必须是函数)
  • methods(函数必须写在这里面)放置业务逻辑,js方法放在这里面,是键值对的回调方法集合
  • template 设置模板,会替换页面元素,包括占位符
  • render 虚拟dom
  • computed 计算属性
  • watch 监听data数据变换:watch:function(new,old){}
  • 生命周期钩子

1.4.1 生命周期钩子

有个知识点:outerHTML指包括root标签的html节点,innerHTML值root标签里的html节点

<div id="root">
	<h2>{{n}}</h2>
</div>
  • beforeMount:页面呈现的是未经编译的DOM结构,所有对DOM的操作不奏效
  • mounted:挂载完成,可以操作DOM,发送网络请求,开定时器等

如果写template字段,则会用该字段编译后的节点整个替换root标签节点(root节点没了),如果不写,则会使用el指定的标签作为根节点去解析(root节点存在)

在这里插入图片描述
注意:生命周期中的this都指向调用它的Vue实例

不要在选项 property 或回调上使用箭头函数
比如 created: () => console.log(this.a) 或 vm.$watch(‘a’, newValue => this.myMethod())
因为箭头函数并没有 this
this 会作为变量一直向上级词法作用域查找,直至找到为止,经常导致 Uncaught TypeError: Cannot read property of undefined 或 Uncaught TypeError: this.myMethod is not a function 之类的错误。

2 基本语法

模板语法:

  • 插值语法:在标签体之间用{{}}包裹来插入JS的表达式:<div>{{time}}</div>,只能接受表达式!
  • 指令语法:在标签内部属性前加上指令来声明标签表现形式,使用""包裹JS语句:<div v-bind:a="time">abc</div>,注意:其中用到的变量或者函数都必须是vue实例中有的,如果没有就会报错(如直接调用window.alert就会报错)

2.1 引入变量 v-bind v-html

  1. 引入变量 v-bind:模板标签中,标签属性使用v-bind:属性="属性变量"来引入,"属性变量"会自动被解析(可以解析简单的表达式:<div v-bind:id="'list-' + id"></div>),如果在数据模型中没有找到这个变量则该属性不会被渲染
    标签之间的使用{{属性变量}}来引入,在{{}}中可以写js语法
    特殊的: 使用v-bind=对象来传递一个对象给组件:v-bind=$attrs(将当前父组件传递过来的所有变量:$attrs中记录了当前组件被绑定的所有属性,原封不动传递给子组件)

v-bind:xxx.sync=“a”
绑定变量时可以有一个.sync修饰符,是一个语法糖,含义为监听内部的@update:xxx的方法(即监听内部对xxx属性的更新调用,this.$emit('update:xxx',100),并将其值赋值给外部的a变量
即::xxx.sync="a" 等价于:@update:xxx="value=>a=value"
如果使用v-model去绑定,则只能绑定value,因为默认绑定的是内部的value和input事件
即:value.sync="a"等价于:@update:value="value=>a=value"等价于v-model="a"

  1. 引入原始HTML v-html:使用指令:v-html,该指令的值为原始HTML
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>

其中:rawHtml变量的值为:<p style="color:red">123</p>会解析HTML显示
注意:切勿对用户提供的内容使用该指令,容易导致XSS攻击

2.2 指令

指令有很多种:

  1. 逻辑指令:其中包括:判断、选择、循环
  2. 事件指令:v-on
  3. 绑定指令:v-bind v-model(涉及到表单,内容单独列出来)
  4. 其他

判断指令通常用于切换渲染组件,需要注意的是组件的key。当组件没有key时,默认会在多种状态切换时如果有可复用的(相同元素)会直接复用!导致之前的输入遗留等(这也是优点,渲染高效)。
案例:输入遗留

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address">
</template>

在切换时会发现input中输入的值出现了遗留,如果想要切换时进行清空数据,则必须手动赋予组件key,表示唯一。
案例:

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address" key="email-input">
</template>

2.2.1 流程指令 v-if

v-if v-else-if v-else,常用于条件渲染,只有表达式为true时渲染该内容,false时不渲染

<h1 v-if="type=='A'">A</h1>
<h1 v-else>Oh no 😢</h1>

注意:可以使用<template>来包裹多个标签,该模板标签实际并不渲染

2.2.2 显示指令 v-show

v-show:一定渲染该标签,但是根据值决定是否显示标签(控制display)
注意:v-show 不支持 <template> 元素,也不支持 v-else

<h1 v-show="ok">Hello!</h1>

v-if还是v-show取决于切换频率,如果高切换频率,选择v-show,不用重复渲染,低切换频率选择v-if,节省时间

v-if和v-for一起使用时,v-for优先级更高。v-if会作用在v-for将要渲染的项上,不推荐

<!--只渲染未完成的 todo-->
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo }}
</li>

2.2.3 循环指令 v-for

v-for,遍历器,其中in可以使用of代替,建议渲染的对象加上key,便于复用提升性能,key不要绑定为索引

<div id="app">
	<!--遍历数组-->
	<li v-for="item in items">
		{{item.message}}
	</li>
	<li v-for="(item,index) in items">
		{{item.message}}---{{index}}
	</li>
	<!--遍历对象-->
	<li v-for="value in object">
	    {{ value }}
	</li>
	<li v-for="(value, key) in object">
	    {{ key }} : {{ value }}
	</li>
	<li v-for="(value, key, index) in object">
	    {{ key }} : {{ value }}
	</li>
</div>
<script>
    var vm = new Vue({
        el:'#app',
        data:{
            items:[
				{message:"abc"},
				{message:"aaa"},
				{message:"ooo"}
			],
			object: {
      			title: 'How to do lists in Vue',
      			author: 'Jane Doe',
      			publishedAt: '2016-04-10'
    		}
        }
    })
</script>

注意:for循环渲染时,如果被渲染数据顺序改变则默认策略为就地更新属性的值!!这种情况虽然比移动DOM效率高,但是如果每个循环项有自己的状态,会导致状态错误或者丢失!
解决方案:使用v-bind:key来绑定唯一key属性,该属性建议使用字符串或者数值来标识。

特殊的:v-for可以接受整数,会重复整数次,从1开始

<span v-for="n in 10">{{ n }} </span>
<!--输出结果:1 2 3 4 5 6 7 8 9 10-->

2.2.4 事件指令 v-on

v-on绑定事件,事件肯定是需要触发一个函数,而函数如果不带参数的话,可以不加括号,此时默认参数为事件对象,如果带参数则需要加括号,且事件参数需要显式传递:$event

<!--打印:event对象 undefiend-->
<div @click="run">123</div>
<!--打印:1 undefiend-->
<div @click="run(1)">123</div>
<!--打印:1 event对象-->
<div @click="run(1,$event)">123</div>
<script>
    var vm = new Vue({
        el:'#app',
        data:{},
        methods:{
			run: function(x,e){console.log(this.x,e)}
		}
    })
</script>

其他案例:

<div id="app">
<li v-on:click="say">
	点击这里
</li>
<button v-on:click="counter += 1">Add 1</button>
<p>The button above has been clicked {{ counter }} times.</p>
</div>

<script>
    var vm = new Vue({
        el:'#app',
        data:{message:"abc",counter:0},
        methods:{
			say: function(msg){alert(this.message+msg)}
		}
    })
</script>

注意:可以在命令值字符串中写简单的表达式

可以在事件绑定中传递参数:v-on:click="say('hi')",可以在函数中传递接收一个$event的参数,代表原始的DOM事件

事件冒泡和捕获相关知识

特殊的: 可以使用:v-on=$listeners,将父组件绑定给当前组件的所有事件对象:$listeners,传递给子组件,$listeners存了当前组件被绑定的所有事件

2.2.5 指令的动态参数

指令后有些可以带参数:v-bind:title如果写死了则不灵活,可以使用动态参数来获取参数:v-bind:[变量]

<!--如果attributeName的值为"href",则该指令相当于v-bind:href-->
<a v-bind:[attributeName]="url"> ... </a>

注意:动态参数会解析成变量,最终获取到一个字符串,任何不为字符串的都会出发警告,如果为null则会移除该属性。
注意:动态指令参数中不能有空格或者引号,如果要做复杂计算,可以使用计算属性代替,且不能使用大写字母,因为会被转换成小写。

2.2.6 事件修饰符

修饰符是告知指令执行的一些特殊方式,如.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault():如<form v-on:submit.prevent="onSubmit">...</form>

v-on事件修饰符有:.stop|.prevent|.captrue|.self|.once|.passive|.native

<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>

<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发,常用于移动端,优先响应滚动 -->
<!-- 而不会等待 `onScroll` 完成  -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div>

<!--一般用于自定义组件上,调用根元素的原生方法,而不是自定义属性-->
<abc @click.native="xxx"></abc>

事件修饰符书写顺序很重要!按照逻辑来

注意:这个 .passive 修饰符尤其能够提升移动端的性能,但是不要把 .passive 和 .prevent 一起使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive 会告诉浏览器你不想阻止事件的默认行为。

键盘事件@keyup或者@keydown,键修饰符:enter等等,可以用于监听特定按键的键盘事件:@keyup.enter监听回车键并回调

对于vue没有提供的按键,可以通过event.key的名字来使用,如@keyup.Enter同样可以
特别注意:对于两个单词拼起来的键名需要转换成小写用-链接:@keyup.caps-lock
特别注意:tab键由于本身功能会切换焦点,所以必须绑定回调在@keydown.tab中!!

对于系统修饰键:ctr alt shift meta
配合keyup使用:按下修饰键再按其他键,释放其他键时才会触发事件,常用组合:@keyup.ctrl.a标识ctrl+a按下后才触发
配合keydown使用:正常触发

2.2.7 指令缩写

对于常用的指令来说,使用缩写能加快开发速度,目前v-bindv-on提供了缩写

  1. v-bind
<!-- 完整语法 -->
<a v-bind:href="url">...</a>

<!-- 缩写 -->
<a :href="url">...</a>

<!-- 动态参数的缩写 (2.6.0+) -->
<a :[key]="url"> ... </a>
  1. v-on
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>

<!-- 缩写 -->
<a @click="doSomething">...</a>

<!-- 动态参数的缩写 (2.6.0+) -->
<a @[event]="doSomething"> ... </a>

2.2.8 v-once

一次性响应指令,只会渲染一次,改变数据后不会再次渲染

<div v-once>{{message}}</div>

2.2.9 v-html

将vue数据中的变量从字符串解析成html格式,永远不要在用户提交的地方使用该指令(XSS攻击)

<div v-html="url"></div>
<!-- url:<a href="http://www.baidu.com">baidu</a> -->

2.2.10 v-text

向其所在的标签中,渲染文本内容,其值当作文本插入到节点文本属性中,不做解析(可防止注入攻击)

<!--渲染结果就是msg变量代表的值,12345被替换了-->
<div v-text="msg">12345</div>

2.2.11 v-pre

跳过解析,直接输出,对于不需要解析的节点建议加上,可以加快编译速度

2.2.12 v-cloak

该属性作用是:在vue解析前存在,在vue解析后删除(Vue会删除标签中的该属性,解析前该属性作为正常html属性使用)。这样可以控制解析前的行为或者样式。如:使用选择器选择有该属性的标签,将其显示样式设置为none,当vue解析完成后,就可以正常显示

<div v-cloak>{{ message }}</div>
<style>[v-cloak] {display: none;}</style>

2.2.13 v-bind

使用v-bind可以动态绑定标签中的属性值!非常常用。注意:在标签属性中不能使用{{}}语法,且所有字符串会被认为是普通字符串,要想解析变量只能使用v-bind来动态赋值

2.2.14 自定义指令

模板中指令名称以v-开头,定义时无需
格式:

// 简写
directives:{
  abc(element,binding){
    // 此处element为真实dom,bingding为指令相关信息,操作真实dom即可改变渲染结果
  }
}
// 全写
directives:{
  abc:{
	  bind(){
		// 指令与元素成功绑定后调用,适用于元素值的操作
	  },
	  inserted(){
	    // 元素被插入到页面后调用,适用于有关DOM结构的操作,比如获取父元素,获取焦点等
	  },
	  update(){
	    // 指令所在模板重新解析时调用
	  }
  }
}

调用时机(简写形式):

  1. 指令与元素建立关系成功后,渲染到页面上前,会调用
  2. 指令所在的模板被重新解析时(每次重新渲染)

一些坑:

  1. 指令名不要大写(html中不区分大小写),可以使用连字符,不过定义指令时需要加引号
  2. 指令内部的this指向是window

定义全局指令:

Vue.directive('abc',{
	  bind(){},
	  inserted(){},
	  update(){}
})
// 简写
Vue.directive('abc',function(){})

2.3 计算属性

为了简化模板中的语法,减少逻辑部分而只负责展示,所以引入计算属性,对于任何复杂逻辑,都因该使用计算属性,且存在缓存,效率比较高

计算属性计算时机:

  1. 第一次读取时计算
  2. 依赖的数据发生改变时计算(当在一个函数内依赖的多个属性被改变了,也只会计算一次,因为JS是串行执行的)

注意:依赖的数据必须要备VUE管理才行

<div id="example">
  <p>逻辑放在模板中: "{{ message.split('').reverse().join('') }}"</p>
  <p>逻辑放在计算中: "{{ reversedMessage }}"</p>
</div>
<script>
var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 计算属性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 实例
      return this.message.split('').reverse().join('')
    },
    x(){console.log(123)}
  }
})
</script>

计算属性最大的优点是存在缓存!!即计算一遍,后面用到的地方可以直接使用不会再计算。除去该优点,其实所有的计算属性都可以使用函数来代替。
计算属性VS函数:当计算属性依赖的属性没有变化时,计算属性不会更新,这样获取速度更快,而如果是函数,则每次获取都会更新。
计算属性VS侦听属性:计算属性是一系列逻辑运算的结果,只要涉及的相关属性没有发生改变,则计算属性不会变,只需要定义一次,而侦听需要达到同样的结果需要对涉及的每个属性进行侦听定义,比较繁琐。同时计算属性依赖于返回值,即返回值必须是一个值!(类似于map和forEach)
计算属性的setter:计算属性也可以有setter,它显式的传入一个参数(计算值),然后根据该值可以自定义相关属性值

// 完整的计算属性定义
computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}

2.4 侦听器

使用watch来定义,当需要在数据变化时执行异步操作或者大开销操作时比较实用,可以监测data中的值和computed值

// html代码: <input v-model="question">
watch: {
    // 如果 `question` 发生改变,这个函数就会运行
    question: function (newQuestion, oldQuestion) {
      this.answer = 'Waiting for you to stop typing...'
      this.debouncedGetAnswer()
    },
    x(nv,ov){} //也可以这样简写,监视x属性变化,函数名和属性名相同
  },

注意:这里使用到了v-mode,该指令用于表单数据的双向数据绑定,相当于在vue实例的data中添加了该属性,无论是vue中的数据变化还是ui控件中该值变化都会触发进行同步

watch属性配置对象:

// 方法一
watch:{
	x:{
		immediate:true, // 表示初始渲染页面时是否更新,默认false
		handler(newValue,oldValue){} // 观测值变化时调用该函数
	}
}
// 方法二
vm.$watch('x',{
	immediate:true, // 表示初始渲染页面时是否更新,默认false
	handler(newValue,oldValue){} // 观测值变化时调用该函数
})
vm.$watch('x',function(newValue,oldValue){}) // 简写

当输入频繁时,希望停止输入一段时间才调用函数,即限定函数访问频率,可以使用debounce方法!

/**
* 空闲控制 返回函数连续调用时,空闲时间必须大于或等于 idle,action 才会执行
* @param fn   {Function}    相关执行函数
* @param delay {Number}  延迟时间,也就是阈值,单位是毫秒
* @return {function}    返回一个“去弹跳”了的函数
*/
debounce(fn,delay)
// 相关参考:https://www.cnblogs.com/songyz/p/10310491.html

对于debounce的实现,Lodash库有现成方法:_.debounce 是一个通过 Lodash 限制操作频率的函数。 this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)

2.4.1 数组更新检测

vue对数被侦听的数组的方法(只有方法,不包括方法外的改变,如直接拿到下表赋值)进行了包裹(Vue3中使用代理,更加全面,包括直接操作索引设置值也能检测到)
包括新增元素、切片、排序、反转(push|pop|shift|unshift|splice|sort|reverse)——原数组被改变(不包括filter,因为不影响原数组)
还有一部分原数组不变而返回新数组(filter|concat|slice),需要自己手动完成新旧数组替换。(有时不需要改变原数组但是要显示新数组,可以使用计算属性!)

注意:这种替换操作非常高效,会复用DOM

Vue.set(对象,索引,值)
这种方式也能响应式修改

2.4.2 深度侦听(监视)

对于多级数据:x:{y:{z:{m:10}}},如果想侦听其中的y的数据变化,写法:'x.y':{handler(nv,ov){}},注意要还原成字符串格式
对于引用类型数据进行侦听,侦听的是引用数据的地址值,无法监听其中数据变化,可以开启深度属性:deep:true

data:{
	x:{
		a:1,
		b:2
	}
},
watch:{
	x:{
		deep:true, // 此时无论x中a和b变化都会调用handler
		handler(){}
	}
}

2.5 样式类

样式分为class样式和内联style样式

在自定义组件上使用该样式语法,会作用在模板的根标签上

class样式语法:顾名思义,专门给css样式类class使用的语法,主要用于动态切换class,对class的绑定:v-bind:class
内联样式语法:专门用来为对象的style使用的语法

2.5.1 class对象语法

对象语法格式:{key:value},value是一个变量,该变量为bool值,指示key是否存在,key为class
该语法和普通class可以并存,最终结果会合并

<div v-bind:class="{ active: isActive }"></div>
<div
  class="static"
  v-bind:class="{ active: isActive, 'text-danger': hasError }"
></div>

如果isActive值为true,hasError值为false,则相当于<div class="static active"></div>
注意:绑定的数据对象也可以写在data中!或者使用计算属性获得结果

2.5.2 class数组语法

格式为:"[activeClass, errorClass]",数组中的值为变量,变量的值为class
特殊的:数组中可以使用三元表达式:<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>,且可以和对象语法混用:<div v-bind:class="[{ active: isActive }, errorClass]"></div>

2.5.3 style对象语法

对象语法格式:v-bind:style,绑定的是一个js对象,可以使用驼峰或者中横线分割命名(如果使用-命名,key要加引号)

<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
  activeColor: 'red',
  fontSize: 30
}
// 也可以直接绑定一个样式对象:
// <div v-bind:style="styleObject"></div>
data: {
  styleObject: {
    color: 'red',
    fontSize: '13px'
  }
}
// 也可以结合计算属性

对象语法中也可以使用数组,表示多重值!通常用来提供多个带前缀的值,只会渲染其中支持的一个

<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>

2.5.4 style数组语法

与class的数组语法相似:<div v-bind:style="[baseStyles, overridingStyles]"></div>

注意:当 v-bind:style 使用需要添加浏览器引擎前缀的 CSS property 时,如 transform,Vue.js 会自动侦测并添加相应的前缀。

2.6 表单输入绑定(v-model)

v-model指令用于表单输入元素的双向绑定,会忽略表单的默认值或者选定属性,全部从vue实例中读取!

内部使用:
text/textarea:value值、input事件
checkbox/radio:checked值、change事件
select:将value作为prop传给change
注意:输入法组合文字时不会触发更新,如果需要,可以使用input事件

v-model和sync修饰符,都可用于双向绑定,但是也有区别:https://zhuanlan.zhihu.com/p/338392152

原理:v-model相当于两个指令的组合:v-bind + 变更事件(input)

<input type="text" v-model="message">
<input type="text" :value="message" @input="message = $event.target.value">

案例:

<!--单行输入-->
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>

<!--注意:多行文本的输入值不在标签之间,而在标签属性中了-->
<textarea v-model="message" placeholder="add multiple lines"></textarea>
<p style="white-space: pre-line;">{{ message }}</p>

<!--复选框,绑定到单个数值,值为true/false-->
<input type="checkbox" id="checkbox" v-model="checked"><label for="checkbox">{{ checked }}</label>

<!--复选框,绑定到数组,值为value-->
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames"><label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames"><label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames"><label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>

<!--单选框,绑定到同一个值即可放入同组中,值为Value-->
<input type="radio" id="one" value="One" v-model="picked"> <label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked"> <label for="two">Two</label>
<br>
<span>Picked: {{ picked }}</span>

<!--下拉框,单选绑定数值,值为option中的内容,IOSBUG:初始值没匹配任何选项,默认第一个选项无法选中,可以人为让第一个选项为禁用以此来规避-->
<select v-model="selected">
  <option disabled value="">请选择</option>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>
<span>Selected: {{ selected }}</span>

<!--下拉框,多选绑定数组,值为option中内容,多选框不存在BUG-->
<select v-model="selected" multiple style="width: 50px;">
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

2.6.1 值绑定

以上表单组件在使用时,有些组件需要配合value属性,如单选框、复选框,而select组件也可以配合value(默认是option标签中的值),复选框在只有绑定单值时可以不用value,默认是true/false

特殊的有两个组件:复选框和下拉列表

复选框存在属性:true-value/false-value,下拉列表的optionvalue可以接收对象

<!--当选中时为yes,没有选中为no-->
<input
  type="checkbox"
  v-model="toggle"
  true-value="yes"
  false-value="no"
>

2.6.2 表单修饰符

  1. .lazy:将表单的数据绑定从input事件转换成change事件( input输入框的onchange事件,要在 input 失去焦点和回车的时候才会触发)
    <input v-model.lazy="msg">
  2. .number:强制输入转换成数字,注意:代码取值时也是数字,和type=number这点不同(获取到的是string),如果无法解析则返回原始值(这点没测出来)
    <input v-model.number="age" type="number">
  3. .trim:去除首尾的空白字符
    <input v-model.trim="msg">

2.7 过滤器 filters(vue3已经废弃)

过滤器其实就是一个函数,只是使用方法更为直观,只能用在两个地方:插值语法、v-bind中,用于简单处理数据!
定义一个过滤器:

// 在vue中和data同级别
filters: {
	abc(x){return x+"---"}
}

调用过滤器也很简单,只要在数据后加|即可,会将前面的数据传递给相应过滤器

// 此时abc只会收到一个参数param
{{param | abc}}
// 传参,此时func会收到两个参数value1和value2
{{value1 | func(value2)}}
// 过滤器可以串联,前一个过滤器的结果会传递给后者
{{value1 | func1 | func2}}

全局过滤器:定义在vue实例内部的filter字段中的为局部过滤器,只有当前实例可以使用,而在创建实例前使用Vue.filter(过滤器名,函数)方式定义的为全局过滤器,全局可用

Vue.filter("f1",function(){})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值