赞
踩
目录
3. VM:视图模型(ViewModel) : Vue 实例对象
7.2 defineProperty的高级属性(getter/setter)
(5) self:只有event.target是当前操作的元素时才触发事件(一定程度上阻止冒泡)
(6)passive:事件的默认行为立即执行,无需等待事件回调执行完毕
(1)监视多级结构中某一个属性的变化:'numbers.a'
(1) 当我们写上key的时候,是不可以使用的key这个属性的
3.Vue.set(要添加到的地方,要添加的属性名,添加的属性值)方法【vm._data.student===vm.stduent】
(1) 修改数组中的数据方法一:使用Vue提供的方法进行操作
(2)在dta中将用户输入的信息封装成一个对象,然后直接输出对象即可
3.用户输入类型的控制(v-model.number="game")
4.延迟收集(v-model.lazy="userInfo.other")
5.去除前后的空格(v-model.trim="userInfo.account")
filter只能在插值语法和v-bind中使用,不能再v-model中使用
3.v-cloak :当网络较慢的时候,不让未解析的再页面上显示
1.函数式:函数名字(获取要进行操作的DOM元素,binding)
1.当指令名字出现“-”的时候:在directives中要加单引号
3.全局指令:Vue.directive(‘函数名',{})
动态构建用户界面的渐进式JavaScript框架
作者:尤雨溪
1.采用组件化模式,提高代码复用率,且让代码更好维护
2.声明式编码,让编码人员无需直接操作DOM,提高开发效率
3.使用虚拟DOM+Diff算法,尽量复用DOM节点
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <!-- 引入开发版Vue -->
- <script type="texe/javascript" src="./js/vue.js"></script>
- </head>
- <body>
- <script type="text/javascript">
- // 阻止vue在启动时生成生产提示
- Vue.config.productionTip=false
- </script>
- </body>
- </html>
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <!-- 引入开发版Vue -->
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
- <body>
- <!-- 初始vue:
- 1.想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对;
- 2.root容器中的代码依然符合html规范,只不过混入了一些特殊的Vue语法
- 3.root容器里的代码被称为【Vue模板】 -->
-
- <!-- 准备好一个容器 -->
- <div id="root">
- <h1>hello,{{ name }}</h1>
- </div>
- <script type="text/javascript">
- // 阻止vue在启动时生成生产提示
- Vue.config.productionTip=false
-
- new Vue({
- el:'#root', //el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串
- data:{ //data用于存储数据,数据共el所指定的容器去使用
- name:'小林'
- }
- })
- </script>
- </body>
- </html>
初始vue:
1.想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对;
2.root容器中的代码依然符合html规范,只不过混入了一些特殊的Vue语法
3.root容器里的代码被称为【Vue模板】
1.想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象
2.root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法
3.root容器里的代码被称为Vue模板
4.Vue实例与容器是一一对应的
5.真实开发中只有一个Vue实例,并且会配合着组件一起使用
6.{{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性
7.一旦data中的数据发生变化,那么模板中用到该数据的地方也会自动更新
html 中包含了一些 JS 语法代码,语法分为两种,分别为:
1. 插值语法(双大括 号表达式)
2. 指令(以 v-开头)
3.2 .插值语法:
功能:用于解析标签体内容
写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有区域
3.3 .指令语法:动态绑定值
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件…)
举例:<a v-bind:href="xxx">或简写为<a :href="xxx">,xxx同样要写js表达式,且可以直接读取到data中的所有属性
备注:Vue中有很多的指令,且形式都是v-???,此处我们只是拿v-bind举个例子
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <!-- 引入开发版Vue -->
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
- <body>
- <!--
- 1.插值语法:
- 功能:用于解析标签体内容
- 写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有区域
- 2.指令语法:
- 功能:用于解析标签(包括:标签属性、标签体内容、绑定事件…)
- 举例:<a v-bind:href="xxx">或简写为<a :href="xxx">,xxx同样要写js表达式,且可以直接读取到data中的所有属性
- 备注:Vue中有很多的指令,且形式都是v-???,此处我们只是拿v-bind举个例子 -->
-
- <!-- 准备好一个容器 -->
- <div id="root">
- <h1>插值语法</h1>
- <h3>您好,{{name}}</h3>
- <hr>
- <h1>指令语法</h1>
- <!-- 属性绑定:把原来的“url”当成js表达式 -->
- <!-- v-bind简写为:===: -->
- <!-- data中的数据只有name和schoo,要访问school里面的,要上前缀 -->
- <a v-bind:href="school.url">点我去访问jack----{{name}}</a>
- <hr>
- <a :href="url" :x="hello">点我去访问小林----{{school.name}}</a>
- </div>
- <script type="text/javascript">
- // 阻止vue在启动时生成生产提示
- Vue.config.productionTip=false
- new Vue({
- el:'#root',
- data() {
- return {
- name:'jack',
- school:{
- name:'小林',
- url:'http://www.baidu.com',
- hello:"您好"
- }
- }
- },
- })
- </script>
- </body>
- </html>
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <!-- 引入开发版Vue -->
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
- <body>
-
- <!-- 准备好一个容器 -->
- <div id="root">
- 单向数据绑定:<input type="text" v-bind:value="name">
- <!-- 简写 -->
- 单向数据绑定:<input type="text" :value="name">
- </div>
- <script type="text/javascript">
- // 阻止vue在启动时生成生产提示
- Vue.config.productionTip=false
- new Vue({
- el:'#root',
- data() {
- return {
- name:'小林'
- }
- },
- })
- </script>
- </body>
- </html>
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <!-- 引入开发版Vue -->
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
- <body>
-
- <!-- 准备好一个容器 -->
- <div id="root">
- 双向数据绑定:<input type="text" v-model:value="name">
- <!-- v-model:value可以简写为v-model,因为v-model默认收集的就是value值 -->
- 双向数据绑定:<input type="text" v-model="name">
- </div>
- <script type="text/javascript">
- // 阻止vue在启动时生成生产提示
- Vue.config.productionTip=false
- new Vue({
- el:'#root',
- data() {
- return {
- name:'小林'
- }
- },
- })
- </script>
- </body>
- </html>
Vue中有2种数据绑定的方式:
单向绑定(v-bind):数据只能从data流向页面
双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data
备注:
双向绑定一般都应用在表单类元素上(如:<input>、<select>、<textarea>等)
v-model:value可以简写为v-model,因为v-model默认收集的就是value值
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <!-- 引入开发版Vue -->
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
- <body>
- <!-- Vue中有2种数据绑定的方式:
- 单向绑定(v-bind):数据只能从data流向页面
- 双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data
-
- 备注:
-
- 双向绑定一般都应用在表单类元素上(如:<input>、<select>、<textarea>等)
- v-model:value可以简写为v-model,因为v-model默认收集的就是value值 -->
- <!-- 准备好一个容器 -->
- <div id="root">
- <!-- 普通写法 -->
- <!-- 单向数据绑定:<input type="text" v-bind:value="name">
- 双向数据绑定:<input type="text" v-model:value="name"> -->
-
- <!-- 简写 -->
- 单向数据绑定:<input type="text" :value="name">
- <!-- v-model:value可以简写为v-model,因为v-model默认收集的就是value值 -->
- 双向数据绑定:<input type="text" v-model="name">
- <br>
- <!-- 如下代码报错,因为v-model只能应用在表单类元素(输入类元素)上【就是要有value值上】 -->
- <h2 v-model:x=""name>您好</h2>
- </div>
- <script type="text/javascript">
- // 阻止vue在启动时生成生产提示
- Vue.config.productionTip=false
- new Vue({
- el:'#root',
- data() {
- return {
- name:'小林'
- }
- },
- })
- </script>
- </body>
- </html>
- const vm = new Vue({
- // el:'#root', //第一种写法
- data:{
- name:'JOJO'
- }
- })
- const vm = new Vue({
- data:{
- name:'JOJO'
- }
- })
- vm.$mount('#root')//第二种写法
- new Vue({
- el: '#root',
- //data的第一种写法:对象式
- data: {
- name: 'JOJO'
- }
- })
- new Vue({
- el: '#root',
- //data的第二种写法:函数式
- data() {//data:function(){
- return {
- name: 'JOJO'
- }
- }
- })
- data:function(){
- console.log(this);//此处的this是指vue实例对象
- }
-
- data:()=>{//箭头函数没有this实例对象
- console.log(this);//此处的this指的是window
- }
-
el有2种写法:
创建Vue实例对象的时候配置el属性
先创建Vue实例,随后再通过vm.$mount('#root')指定el的值
data有2种写法:
对象式
函数式
由Vue管理的函数,一定不要写箭头函数,否则this就不再是Vue实例了(而是window)
1. M:模型(Model) :对应 data 中的数据
2. V:视图(View) :模板(view),页面(DOM)
3. VM:视图模型(ViewModel) : Vue 实例对象
虽然没有完全遵循 MVVM 模型,但是 Vue 的设计也受到了它的启发。因此在文档中经常会使用 vm
(ViewModel 的缩写) 这个变量名表示 Vue 实例。
- data中所有的属性,最后都出现在了vm身上
- vm身上所有的属性 及 Vue原型身上所有的属性,在Vue模板中都可以直接使用
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>mvvm</title>
- <script src="./js/vue.js"></script>
- </head>
- <body>
-
-
- <!-- 1. M:模型(Model) :对应 data 中的数据
- 2. V:视图(View) :模板(view)
- 3. VM:视图模型(ViewModel) : Vue 实例对象
- data中所有的属性,最后都出现在了vm身上
- vm身上所有的属性 及 Vue原型身上所有的属性,在Vue模板中都可以直接使用 -->
- <div id="root">
- <h2>学校:{{name}}</h2>
- <h2>地址:{{address}}</h2>
- <!-- vm身上的可以直接使用(或者Vue身上的) -->
- <h2>vm身上的:{{$options}}</h2>
- <!-- 原型身上的也可以 -->
- <h1>原型身上的:{{$emit}}</h1>
- </div>
-
- <script>
- Vue.config.productionTip = false
- const vm=new Vue({
- el:'#root',
- data:{
- name:'gz',
- address:'广东省'
- }
- console.log(vm)//会出现data中的属性
- })
- </script>
- </body>
- </html>
- Object.defineProperty(person,'age',{
- value:18,
- // 控制属性是否可以枚举,默认值为false
- enumerable:true,
- // 控制属性是否可以被修改,默认值为false
- writable:true,
- // 控制属性是否可以被删除,默认值为false
- configurable:true
-
- })
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>回顾Object.defineProperty方法</title>
- <!-- let obj = {}
- //与我们使用 obj.name = 'zhangsna' 效果一样 但是用defineProperty定义的属性无法改变 或者删除
- Object.defineProperty(obj,'name',{
- value:'zhangsan'
- })
- console.log(obj); -->
-
- </head>
-
- <body>
- <script type="text/javascript">
- // 业务:当number改变的时候,person中的age跟着改变
- let number = 19
- let person = {
- name: '张三',
- sex: '男',
- }
- Object.defineProperties(person, 'age', {
- // 当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
- get() {
- console.log('有人读取age属性');
- return number
- },
- // 当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
- set(value) {
- console.log('有人修改age属性,且值为',value);
- number=value
- }
- })
-
-
- console.log(person);
- </script>
- </body>
-
- </html>
通过一个对象代理对另一个对象中的属性的操作(读/写)
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- </head>
- <body>
- <!-- 数据代理:通过一个对象代理对另一个对象中的属性的操作(读/写) -->
- <script type="text/javascript">
- // 业务:通过obj2对obj中的x进行修改
- let obj={x:100}
- let obj2={y:200}
-
-
- Object.defineProperties(obj2,'x',{
- get(){//获取obj中的x
- return obj.x
- },
- set(value){//将修改obj中的x
- obj.x=value
- }
- })
- </script>
- </body>
- </html>
Vue中的数据代理通过vm对象来代理data对象中属性的操作(读/写)
Vue中数据代理的好处:更加方便的操作data中的数据
基本原理:
1.通过object.defineProperty()把data对象中所有属性添加到vm上。
2.为每一个添加到vm上的属性,都指定一个getter/setter。
3.在getter/setter内部去操作(读/写)data中对应的属性。
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>mvvm</title>
- <script src="./js/vue.js"></script>
- </head>
- <body>
-
- <!-- 事件的基本使用:
- 使用v-on:xxx或@xxx绑定事件,其中xxx是事件名
- 事件的回调需要配置在methods对象中,最终会在vm上
- methods中配置的函数,==不要用箭头函数!==否则this就不是vm了
- methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象
- @click="demo和@click="demo($event)"效果一致,但后者可以传参 -->
-
- <div id="root">
- <h1>欢迎来到{{name}}</h1>
- <!-- <button v-on:click="showInfo">点我提示信息</button> -->
- <!-- v-on简写形式:@ -->
- <button @click="showInfo1">点我提示信息1(不传参)</button>
- <!-- 传入参数 直接在函数名后面加上小括号(但是这样会把event搞丢) -->
- <!-- <button @click="showInfo2(66)">点我提示信息2</button> -->
- <!-- 此处的$event:是要进行占位,防止传参把event搞丢 -->
- <button @click="showInfo2(66,$event)">点我提示信息2(传参)</button>
- </div>
-
- <script>
- Vue.config.productionTip = false
- const vm=new Vue({
- el:'#root',
- data:{
- name:'猫咖'
- },
- methods: {
- // showInfo:(event)=>{}
- // 如果使用箭头函数,则this指向window
- showInfo1(event){
- console.log(event);
- console.log(event.target);//拿到进行操作的对象
- console.log(this);//Vue实例对象--vm
- alert('同学1')
- },
- // 这里的number是传入的参数
- // a;:是事件(event)
- showInfo2(number,a){
- console.log(number);
- console.log(a);
- alert('同学2')
- }
- },
- })
- </script>
- </body>
- </html>
事件的基本使用:
使用v-on:xxx或@xxx绑定事件,其中xxx是事件名
事件的回调需要配置在methods对象中,最终会在vm上
methods中配置的函数,==不要用箭头函数!==否则this就不是vm了【变成window】
methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象
@click="demo和@click="demo($event)"效果一致,但后者可以传参
- <!-- 阻止默认事件(常用):@click.prevent:阻止跳转 -->
- <a href="http://www.baidu.com" @click.prevent="showInfo">点我提示信息</a>
-
- Vue.config.productionTip = false
- const vm=new Vue({
- el:'#root',
- data:{
- name:'猫咖'
- },
- methods: {
- showInfo(){
- // 阻止默认事件
- // e.preventDefault();
- alert('nh')
- }
- },
- })
- <!-- 阻止事件冒泡 -->
- <div class="demo1" @click="showInfo">
- <button @click.stop="showInfo">点我提示信息</button>
- </div>
-
- const vm=new Vue({
- el:'#root',
- data:{
- name:'猫咖'
- },
- methods: {
- showInfo(){
- // 阻止事件冒泡
- // e.stopPropagation();
- alert('nh')
- }
- },
- })
- <!-- 事件只触发一次 -->
- <button @click.once="showInfo">点我提示信息</button>
- <!-- 使用事件的捕获模式(由外往内) -->
- <div class="box1" @click.capture="showMsg(1)">
- div1
- <div class="box2" @click="showMsg(2)">
- div2
- </div>
- </div>
-
- <!-- 只有event.target是当前操作的元素时才触发事件 -->
- <div class="demo1" @click.self="showInfo">
- <button @click="showInfo">点我提示信息</button>
- </div>
- <!-- 事件的默认行为立即执行,无需等待事件回调执行完毕 -->
- <ul @wheel.passive="demo" class="list">
- <li>1</li>
- <li>2</li>
- <li>3</li>
- <li>4</li>
- </ul>
-
- const vm = new Vue({
- el: '#root',
- data: {
- name: '猫咖'
- },
- methods: {
- demo(){
- for (let i = 0; i < 100000; i++) {
- console.log('#')
- }
- console.log('累坏了')
- }
- },
- })
Vue中的事件修饰符:
prevent:阻止默认事件(常用)
stop:阻止事件冒泡(常用)
once:事件只触发一次(常用)
capture:使用事件的捕获模式
self:只有event.target是当前操作的元素时才触发事件
passive:事件的默认行为立即执行,无需等待事件回调执行完毕
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>mvvm</title>
- <script src="./js/vue.js"></script>
- </head>
- <body>
- <!--
- 1. Vue中常用的按键别名:
- 回车:enter
- 删除:delete (捕获“删除”和“退格”键)
- 退出:esc
- 空格:space
- 换行:tab (特殊,必须配合keydown去使用)
- 上:up
- 下:down
- 左:left
- 右:right
- 2.Vue未提供别名按键,可以使用按键原始key值去绑定,但是注意要转为(CapsLock转换为caps-lock)kebab-case(短横线命名)
- 3.系统修饰键(用法特殊):ctrl、alt、shift、meta---配合keydown使用
- (1)配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发
- (2)配合keydown使用:正常触发事件(Tab)
- 4. 可以使用keyCode去指定具体的按键,比如:@keydown.13="showInfo",但不推荐这样使用
- 5.Vue.config.keyCodes.自定义键名 = 键码,可以自定义按键别名
- -->
- <div id="root">
- <h1>欢迎来到{{name}}</h1>
- <input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo">
- </div>
-
- <script>
- Vue.config.productionTip = false
- // 定义一个别名按键
- Vue.config.keyCodes.huiche=13
- const vm=new Vue({
- el:'#root',
- data:{
- name:'猫咖'
- },
- methods: {
- showInfo(evnet){
- // console.log(evnet.keyCodes);//输出ASCII编码
- // 拿到按键的值
- // console.log(e.key);
- // 拿到文本框中的值
- console.log(evnet.target.value);
- }
- },
- })
- </script>
- </body>
- </html>
1. Vue中常用的按键别名:
回车:enter
删除:delete (捕获“删除”和“退格”键)
退出:esc
空格:space
换行:tab (特殊【因为tab是切换按钮的效果】,必须配合keydown去使用)
上:up
下:down
左:left
右:right
2.Vue未提供别名按键,可以使用按键原始key值去绑定,但是注意要转为(CapsLock转换为caps-lock)kebab-case(短横线命名)
3.系统修饰键(用法特殊):ctrl、alt、shift、meta---配合keydown使用
(1)配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发
(2)配合keydown使用:正常触发事件(Tab)
4. 可以使用keyCode去指定具体的按键,比如:@keydown.13="showInfo",但不推荐这样使用
5.Vue.config.keyCodes.自定义键名 = 键码,可以自定义按键别名
Vue.config.keyCodes.huiche=13;
- <!-- 阻止冒泡并且阻止链接跳转 -->
- <button href="http://www.baidu.com" @click.stop.prevent="showInfo">点我提示信息</button>
- <!-- ctrl.y:表示同时按下ctrl+y才起效 -->
- <input type="text" placeholder="按下回车提示输入" @keyup.ctrl.y="showInfo">
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>姓名案例_插值语法的实现</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
- <body>
- <!-- 准备一个容器 -->
- <div id="root">
- 姓:<input type="text" v-model:value="firstName">
- <br>
- 名:<input type="text" v-model:value="lastName">
- <br>
- 姓名:<span>{{firstName+'_'+lastName}}</span>
- </div>
- </body>
-
- <script type="text/javascript">
- Vue.config.productionTip = false
- new Vue({
- el:'#root',
- data: {
- firstName:'张',
- lastName:'三'
- },
- })
- </script>
- </html>
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>姓名案例——methods实现</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
- <body>
- <!-- 准备一个容器 -->
- <div id="root">
- 姓:<input type="text" v-model:value="firstName">
- <br>
- 名:<input type="text" v-model:value="lastName">
- <br>
- 姓名
- <!-- 使用():表示调用fullName的返回值进行展示 -->
- <span>{{fullName()}}</span>
- <br><br>
- <!-- <span>{{fullName}}</span> -->
- </div>
- </body>
-
- <script type="text/javascript">
- Vue.config.productionTip = false
- new Vue({
- el:'#root',
- data: {
- firstName:'张',
- lastName:'三'
- },
- methods: {
- // 当data中的数据发生改变的时候,页面中会重新渲染,所以fullName还调用多次
- fullName(){
- return this.firstName+'_'+this.lastName
- }
- },
- })
- </script>
- </html>
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>姓名案例——计算属性实现</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
- <body>
- <!-- 准备一个容器 -->
- <div id="root">
- 姓:<input type="text" v-model:value="firstName">
- <br>
- 名:<input type="text" v-model:value="lastName">
- <br>
- <!-- 计算属性有缓存机制:所以此时fullName就调用一次 -->
- 姓名:<span>{{fullName}}</span>
- 姓名:<span>{{fullName}}</span>
- 姓名:<span>{{fullName}}</span>
- 姓名:<span>{{fullName}}</span>
- 姓名:<span>{{fullName}}</span>
-
- </div>
- </body>
-
- <script type="text/javascript">
- Vue.config.productionTip = false
- const vm=new Vue({
- el:'#root',
- data: {
- // 属性
- firstName:'张',
- lastName:'三'
- },
- // vm._data中没有fullName
- // 计算属性,对象的形式
- // 计算属性直接丢给vm,不给data
- computed: {
- // 上面使用了5次fullName,此时fullName调用了5次
- fullName:{
- // get有什么作用?当有人读取fullName的时候,get就会被调用,且返回值就作为fullName的值
- // get什么时候被调用?
- // 1.初次读取fullName的时候
- // 2.所依赖的数据发生变化时
- // 虽然上面调用了5次fullName,但是实际上get就调用一次
- get(){//读取属性
- console.log('get被调用');
- // 此时this-->指向vm
- return this.firstName+'_'+this.lastName
- },
-
-
- // set不是必须写的
- // set什么时候调用?当fullName被修改的时候
- set(){//修改属性
- console.log('set',value);
- const arr=value.split('-')
- this.firstName=arr[0]
- this.lastName=arr[1]
- }
- }
- },
-
- })
- </script>
- </html>
当只对属性读取的时候(就是只有get的时候)才可与使用
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>姓名案例——计算属性简写</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
-
- <body>
-
-
- <!-- 准备一个容器 -->
- <div id="root">
- 姓:<input type="text" v-model:value="firstName">
- <br>
- 名:<input type="text" v-model:value="lastName">
- <br>
- 姓名:<span>{{fullName}}</span>
-
- </div>
- </body>
-
- <script type="text/javascript">
- Vue.config.productionTip = false
- const vm = new Vue({
- el: '#root',
- data: {
- // 属性
- firstName: '张',
- lastName: '三'
- },
- computed: {
- // 完整写法
- // fullName:{
- // get(){//读取属性
- // console.log('get被调用');
- // // 此时this-->指向vm
- // return this.firstName+'_'+this.lastName
- // },
- // set(){//修改属性
- // console.log('set',value);
- // const arr=value.split('-')
- // this.firstName=arr[0]
- // this.lastName=arr[1]
- // }
- // }
-
- // 当只有get,才可以使用简写
- // 简写
- fullName() {//此时fullName相当于get方法
- console.log('get被调用');
- // 此时this-->指向vm
- return this.firstName+'_'+this.lastName
- }
- },
-
- })
- </script>
-
- </html>
计算属性:
1.定义:要用的属性不存在,需要通过已有属性计算得来。
2.原理:底层借助了Objcet.defineproperty()方法提供的getter和setter。
3.get函数什么时候执行?
初次读取时会执行一次
当依赖的数据发生改变时会被再次调用
4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便
5.备注:
1.计算属性最终会出现在vm上,直接读取使用即可
2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
3.如果计算属性确定不考虑修改,可以使用计算属性的简写形式
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
- <body>
- <!-- 准备一个容器 -->
- <div id="root">
- <!-- <h2>天气预报{{isHot?'炎热':'凉爽'}}</h2> -->
- <!-- 使用计算属性 -->
- <!-- 注意点:如果页面没有使用Info,则当我们点击按钮,然后改变后,Vue插件上的值并没有改变 -->
- <h2>天气预报{{Info}}</h2>
- <!-- 使用methods -->
- <button @click="changeWeather">切换天气</button>
- <!-- 直接在标签中写 -->
- <!-- 绑定事件的时候:@xxx="yyy" yyy可以写一些简单的语句 -->
- <!-- <button @click="isHot=!isHot">切换天气</button> -->
- </div>
- </body>
-
- <script type="text/javascript">
- new Vue({
- el:'#root',
- data:{
- isHot:true
- },
- computed:{
- Info(){
- return this.isHot?'炎热':'凉爽'
- }
- },
- methods: {
- /* changeWeather(){
- // 此时的isHot为反过来的isHot
- this.isHot=!this.isHot
- }
- */$
- },
- })
- </script>
- </html>
- // 监视属性
- watch:{
- isHot:{
- // handler什么时候调用?当isHot发生改变的时候
- // handler接收两个参数
- // 第一个参数:被修改后的数值
- // 第二个参数:返回原来的值
- handler(newValue,oldValue){
- console.log('isHot被修改了',newValue,oldValue);
- },
- }
- }
- // 监视属性
- watch:{
- isHot:{
- // immediate默认值为false
- // 初始化时候让handler调用一下
- immediate:true
- }
- }
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
-
- <body>
- <!-- 准备一个容器 -->
- <div id="root">
- <h2>天气预报{{Info}}</h2>
- <button @click="changeWeather">切换天气</button>
- </div>
- </body>
-
- <script type="text/javascript">
- new Vue({
- el: '#root',
- data: {
- isHot: true
- },
- computed: {
- Info() {
- return this.isHot ? '炎热' : '凉爽'
- }
- },
- methods: {
- changeWeather() {
- // 此时的isHot为反过来的isHot
- this.isHot = !this.isHot
- }
- },
-
- // 监视属性
- watch: {
- // 可以监听普通属性
- isHot: {
- // handler什么时候调用?当isHot发生改变的时候
- // handler接收两个参数
- // 第一个参数:被修改后的数值
- // 第二个参数:返回原来的值
- handler(newValue, oldValue) {
- console.log('isHot被修改了', newValue, oldValue);
- },
- // immediate默认值为false
- // 初始化时候让handler调用一下
- immediate: true
- },
-
-
- // 也可以监听计算属性
- Info: {
- handler(newValue, oldValue) {
- console.log('Info被修改了', newValue, oldValue);
- },
- immediate: true
- }
- }
-
- })
- </script>
-
- </html>
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
-
- <body>
- <!-- 准备一个容器 -->
- <div id="root">
- <h2>天气预报{{Info}}</h2>
- <button @click="changeWeather">切换天气</button>
- </div>
- </body>
-
- <script type="text/javascript">
- new Vue({
- el: '#root',
- data: {
- isHot: true
- },
- computed: {
- Info() {
- return this.isHot ? '炎热' : '凉爽'
- }
- },
- methods: {
- changeWeather() {
- // 此时的isHot为反过来的isHot
- this.isHot = !this.isHot
- }
- },
-
- // 通过$watch进行监听
- //vm.$watch('监视对象',{监视触发事件})
- vm.$watch('isHot',{
- handler(newValue, oldValue) {
- console.log('Info被修改了', newValue, oldValue);
- },
- immediate: true
- })
- </script>
-
- </html>
监视属性watch:
1.当被监视的属性变化时,回调函数自动【handler】调用,进行相关操作
2.监视的属性必须存在,才能进行监视
3.监视有两种写法:
(1)创建Vue时传入watch配置
(2)通过vm.$watch监视
- new Vue({
- el: '#root',
- data: {
- isHot: true,
- numbers:{
- a:1,
- b:2
- }
- },
-
- // 深度监听
- watch: {
- // 监视多级结构中某一个属性的变化
- 'numbers.a':{
- handler(){
- console.log('a改变了');
- }
- }
- }
-
- })
- new Vue({
- el: '#root',
- data: {
- isHot: true,
- numbers:{
- a:1,
- b:2
- }
- },
-
- // 深度监听
- watch: {
- // 监视多级结构中所有属性的变化
- numbers:{
- // deep:默认值为false
- deep:true,
- handler(){
- console.log('numbers改变了');
- }
- }
- }
-
- })
深度监视:
(1)Vue中的watch默认不监测对象内部值的改变(一层)
(2)在watch中配置deep:true可以监测对象内部值的改变(多层)
备注:
(1)Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以
(2)使用watch时根据监视数据的具体结构,决定是否采用深度监视
当在watch中只有handler方法的时候才可以使用
- // 监视属性
- watch: {
- // 完整写法
- /* isHot: {
- // 深度监视
- deep:true,
- handler(newValue, oldValue) {
- console.log('isHot被修改了', newValue, oldValue);
- },
- immediate: true
- }
- */
-
- // 监视的简写形式
- isHot(newValue, oldValue){
- console.log('isHot被修改了', newValue, oldValue);
- }
- }
- const vm=new Vue({
- el: '#root',
- data: {
- isHot: true,
- numbers:{
- a:1,
- b:2
- }
- }
-
- // 完整写法【正常写法】
- vm.$watch('isHot',{
- deep:true,
- handler(newValue, oldValue) {
- console.log('isHot被修改了', newValue, oldValue);
- },
- immediate: true
- })
-
- // 监听的简写:当只有handler方法的时候才可以
- // 注意:不能写成箭头函数
- vm.$watch('isHot',function(newValue, oldValue){
- console.log('isHot被修改了', newValue, oldValue);
- })
官网例子:计算属性和侦听器 — Vue.js
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>姓名案例——watch实现</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
-
- <body>
-
-
- <!-- 准备一个容器 -->
- <div id="root">
- 姓:<input type="text" v-model:value="firstName">
- <br>
- 名:<input type="text" v-model:value="lastName">
- <br>
- 姓名:<span>{{fullName}}</span>
-
- </div>
- </body>
-
- <script type="text/javascript">
- Vue.config.productionTip = false
- const vm = new Vue({
- el: '#root',
- data: {
- // 属性
- firstName: '张',
- lastName: '三',
- fullName:'张-三'
- },
- watch:{
- // 由于oldValue没有用到所以不写
- firstName(newValue){
- this.fullName=newValue+'-'+this.lastName
- },
- lastName(newValue){
- this.fullName=this.firstName+'-'+newValue
- }
- }
-
- })
- </script>
-
- </html>
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>姓名案例——计算属性实现</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
- <body>
-
-
-
- <!-- 准备一个容器 -->
- <div id="root">
- 姓:<input type="text" v-model:value="firstName">
- <br>
- 名:<input type="text" v-model:value="lastName">
- <br>
- <!-- 计算属性有缓存机制:所以此时fullName就调用一次 -->
- 姓名:<span>{{fullName}}</span>
- 姓名:<span>{{fullName}}</span>
- 姓名:<span>{{fullName}}</span>
- 姓名:<span>{{fullName}}</span>
- 姓名:<span>{{fullName}}</span>
-
- </div>
- </body>
-
- <script type="text/javascript">
- Vue.config.productionTip = false
- const vm=new Vue({
- el:'#root',
- data: {
- // 属性
- firstName:'张',
- lastName:'三'
- },
- // vm._data中没有fullName
- // 计算属性,对象的形式
- // 计算属性直接丢给vm,不给data
- computed: {
- // 上面使用了5次fullName,此时fullName调用了5次
- fullName:{
- get(){//读取属性
- console.log('get被调用');
- // 此时this-->指向vm
- return this.firstName+'_'+this.lastName
- },
-
-
- // set不是必须写的
- // set什么时候调用?当fullName被修改的时候
- set(value){//修改属性
- console.log('set',value);
- const arr=value.split('-')
- this.firstName=arr[0]
- this.lastName=arr[1]
- }
- }
- },
-
- })
- </script>
- </html>
watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作
computed和watch之间的区别:
1.computed能完成的功能,watch都可以完成
2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作
两个重要的小原则:
1.所有被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象
2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数(在当前的函数中找不到vm,则向上查找),这样this的指向才是vm 或 组件实例对象。
适用于:样式的类名不确定,需要动态指定
- <body>
- <div id="root">
- <!-- 当点击名字的时候添加一个basic happy的样式 -->
- <!-- 绑定class样式-----字符串写法,适用于:样式的类名不确定,需要动态指定 -->
- <div class="basic" :class="mood" @click="changeMood">{{name}}</div>
-
- </div>
- <script type="text/javascript">
- new Vue({
- el:'#root',
- data:{
- name:'小林',
- mood:'normal',
- },
- methods: {
- changeMood(){
- const arr=['happy','sad','normal']
- // random产生的随机数0<=x<1(不包括1)
- // Math.random()*3--接收到[0,2)
- const index=Math.floor(Math.random()*3)
- this.mood=arr[index]
- }
- },
- })
- </script>
- </body>
适用于:要绑定的样式个数不确定,名字也不确定
- <body>
- <div id="root">
- <!-- 绑定class样式-----数组写法,适用于:要绑定的样式个数不确定,名字也不确定 -->
- <div class="basic" :class="classArr">{{name}}</div>
-
- </div>
- <script type="text/javascript">
- new Vue({
- el: '#root',
- data: {
- name: '小林',
- classArr: ['atguigu1', 'atguigu2', 'atguigu3']
- }
-
- })
- </script>
- </body>
适用于:要绑定的样式个数确定,名字也确定,但是要动态决定用不用
- <body>
- <div id="root">
- <!-- 绑定class样式-----对象写法,适用于:要绑定的样式个数确定,名字也确定,但是要动态决定用不用 -->
- <div class="basic" :class="classObj">{{name}}</div>
-
- </div>
- <script type="text/javascript">
- new Vue({
- el: '#root',
- data: {
- name: '小林',
- classObj:{
- atguigu1:false,
- atguigu2:false
- }
- }
- </script>
- </body>
class样式:
写法:class="xxx",xxx可以是字符串、对象、数组
字符串写法适用于:类名不确定,要动态获取
对象写法适用于:要绑定多个样式,个数不确定,名字也不确定
数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用
- <body>
- <div id="root">
-
- <div class="basic" :style="styleObj">{{name}}</div>
-
- </div>
- <script type="text/javascript">
- new Vue({
- el: '#root',
- data: {
- name: '小林',
- styleObj:{
- // 驼峰命名法
- fontSize:'40px',
- color:'red',
- backgroundColor:'orange'
- }
- },
-
-
- })
- </script>
- </body>
- <body>
- <div id="root">
- <!-- 绑定style样式---对象写法 -->
- <div class="basic" :style="styleObj">{{name}}</div>
-
- <!-- 绑定style样式---数组写法 -->
- <!-- 同时应用styleObj,styleObj2 -->
- <div class="basic" :style="[styleObj,styleObj2]">{{name}}</div>
-
- </div>
- <script type="text/javascript">
- new Vue({
- el: '#root',
- data: {
- name: '小林',
- styleObj:{
- // 驼峰命名法
- fontSize:'40px',
- color:'red',
- },
- styleObj2:{
- backgroundColor:'orange'
- }
- },
-
-
- })
- </script>
- </body>
style样式:
:style="{fontSize: xxx}"其中xxx是动态值
:style="[a,b]"其中a、b是样式对象
适用于:切换频率较高的场景
使用v-show实际上是使用了display:none
特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
高频率使用就使用:v-show
- <body>
-
- <div id="root">
- <!-- 使用v-show做条件渲染 -->
- <!-- 使用v-show实际上是使用了display:none -->
- <!-- 高频率使用就使用:v-show-->
- <h2 v-show="false">欢迎来到{{name}}</h2>
- <h2 v-show="1===1">欢迎来到{{name}}</h2>
- </div>
- <script type="text/javascript">
- new Vue({
- el: '#root',
- data: {
- name: '小林',
- },
- })
- </script>
- </body>
- <body>
-
- <div id="root">
- <!-- 使用v-if做条件渲染 -->
- <h2 v-if="1===1">欢迎来到{{name}}</h2>
- <h2 v-if="false">欢迎来到{{name}}</h2>
- </div>
- <script type="text/javascript">
- new Vue({
- el: '#root',
- data: {
- name: '小林',
- },
- })
- </script>
- </body>
- <body>
-
- <h2>当前的n值是:{{n}}</h2>
- <button @click="n++">点我n+1</button>
-
- <!-- v-else-if与v-else -->
- <div v-if="n===1">Angular</div>
- <div v-else-if="n===2">Angular</div>
- <div v-else-if="n===3">Vue</div>
- <!-- 后面一般不加上v-else,因为当不满足上面的等式,则直接渲染v-else中的东西 -->
- <div v-else="n===4">hh</div>
- </div>
- <script type="text/javascript">
- new Vue({
- el: '#root',
- data: {
- name: '小林',
- n:0
- },
- })
- </script>
- </body>
写法:
(1)v-if="表达式"
(2)v-else-if="表达式"
(3)v-else
适用于:切换频率较低的场景
特点:不展示的DOM元素直接被移除
注意:v-if可以和v-else-if、v-else一起使用,但要求结构不能被打断
v-if与template的配合使用:template只能和v-if一起使用,不能跟v-show
<!-- v-if与template的配合使用 --> <template v-if="n===1"> <h2>您好</h2> <h2>无论</h2> <h2>更多</h2> </template>
使用v-if的时候,元素可能无法获取到,而使用v-show一定可以获取到
- <body>
- <div id="root">
- <h2>人员列表</h2>
- <ul>
- <!-- p表示persons中的每一个数据 -->
- <!-- 如果使用v-for则一定要用key -->
- <li v-for="p in persons" :key="p.id">
- {{p.name}}--{{p.age}}
- </li>
- </ul>
- </div>
- </body>
-
- <script type="text/javascript">
- new Vue({
- el:'#root',
- data: {
- persons:[
- {id:'001',name:'张三',age:19},
- {id:'002',name:'李四',age:12},
- {id:'003',name:'王五',age:13}
- ]
- },
- })
- </script>
- <body>
- <div id="root">
- <h2>人员列表</h2>
- <ul>
- <!-- v-for循环的时候接收2个参数 -->
- <!-- 第一个参数:接收到数组中每一个数值 -->
- <!-- 第二个参数:是index索引值 -->
- <li v-for="(p,index) in persons" :key="index">
- {{p}}---{{index}}
- </li>
- </ul>
- </div>
- </body>
-
- <script type="text/javascript">
- new Vue({
- el:'#root',
- data: {
- persons:[
- {id:'001',name:'张三',age:19},
- {id:'002',name:'李四',age:12},
- {id:'003',name:'王五',age:13}
- ]
- },
- })
- </script>
- <body>
- <div id="root">
- <h2>人员列表</h2>
- <h1>遍历数组</h1>
- <ul>
- <!-- 可以将in改为of -->
- <li v-for="(p,index) of persons" :key="index">
- {{p}}---{{inedx}}
- </li>
- </ul>
- </div>
- </body>
-
- <script type="text/javascript">
- new Vue({
- el:'#root',
- data: {
- persons:[
- {id:'001',name:'张三',age:19},
- {id:'002',name:'李四',age:12},
- {id:'003',name:'王五',age:13}
- ]
- },
- })
- </script>
- <body>
- <div id="root">
- <h2>人员列表</h2>
- <ul>
- <!-- p表示persons中的每一个数据 -->
- <!-- 如果使用v-for则一定要用key -->
- <li v-for="p in persons" :key="p.id">
- {{p.name}}--{{p.age}}
- </li>
- </ul>
- </div>
- </body>
-
- <script type="text/javascript">
- new Vue({
- el:'#root',
- data: {
- persons:[
- {id:'001',name:'张三',age:19},
- {id:'002',name:'李四',age:12},
- {id:'003',name:'王五',age:13}
- ]
- },
- })
- </script>
- <body>
- <div id="root">
- <h2>人员列表</h2>
- <h1>遍历对象</h1>
- <h1>遍历对象</h1>
- <ul>
- <li v-for="(value,k) in car" :key="k">
- {{value}}---{{k}}
- </li>
- </ul>
- </div>
- </body>
-
- <script type="text/javascript">
- new Vue({
- el:'#root',
- data: {
- car:{
- name:'奔驰',
- price:90
- }
- },
- })
- </script>
- <body>
- <div id="root">
- <h2>人员列表</h2>
- <h1>遍历数组</h1>
- <ul>
- <h1>遍历字符串</h1>
- <ul>
- <li v-for="(char,k) in str" :key="k">
- {{char}}---{{k}}
- </li>
- </ul>
- </div>
- </body>
-
- <script type="text/javascript">
- new Vue({
- el:'#root',
- data: {
- str:'hello'
- },
- })
- </script>
- <body>
- <div id="root">
- <h2>人员列表</h2>
- <h1>遍历数组</h1>
- <ul>
- <h1>遍历指定次数</h1>
- <ul>
- <li v-for="(number,index) in 5" :key="index">
- {{number}}---{{index}}
- </li>
- </ul>
- </div>
- </body>
-
- <script type="text/javascript">
- new Vue({
- el:'#root',
- data: {
- persons:[
- {id:'001',name:'张三',age:19},
- {id:'002',name:'李四',age:12},
- {id:'003',name:'王五',age:13}
- ],
- car:{
- name:'奔驰',
- price:90
- },
- str:'hello'
- },
- })
- </script>
v-for指令:
1.用于展示列表数据
2.语法:<li v-for="(item, index) in xxx" :key="yyy">,其中key可以是index,也可以是遍历对象的唯一标识
3.可遍历:数组、对象、字符串(用的少)、指定次数(用的少)
面试题:react、vue中的key有什么作用?(key的内部原理)
1.虚拟DOM中key的作用:key是虚拟DOM中对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
2.对比规则:
(1)旧虚拟DOM中找到了与新虚拟DOM相同的key:
a.若虚拟DOM中内容没变, 直接使用之前的真实DOM
b.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM
(2)旧虚拟DOM中未找到与新虚拟DOM相同的key:
创建新的真实DOM,随后渲染到到页面
3.用index作为key可能会引发的问题:
(1).若对数据进行逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低
(2)若结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题
4.开发中如何选择key?
(1)最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值
(2)如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表,使用index作为key是没有问题的
computed能实现的,watch都能实现
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>列表过滤</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
-
- <body>
- <div id="root">
- <h2>人员列表</h2>
- <!-- persons一变就重新解析模板,整个列表就发生变化了 -->
- <!-- 收集用户输入:给输入框绑定双向数据绑定 -->
- <input type="text" placeholder="请输入名字" v-model="keyWord">
- <li v-for="(p,index) in filPersons" :key="index">
- {{p.name}}--{{p.age}}---{{p.sex}}
- </li>
- </div>
- </body>
-
- <script type="text/javascript">
- new Vue({
- el: '#root',
- data: {
- keyWord: '',
- persons: [
- { id: '001', name: '马冬梅', age: 19, sex: '女' },
- { id: '002', name: '周冬雨', age: 21, sex: '女' },
- { id: '003', name: '周杰伦', age: 11, sex: '男' },
- { id: '004', name: '温兆伦', age: 13, sex: '男' }
- ],
- // 是过滤器过滤出来的新数据
- // 如果不使用这个,则数据会越搜索越少
- filPersons: []
- },
- watch: {
- // 因为我们不关心上一个数据,所以不传入oldValue
- keyWord: {
- // 这里为什么要使用immediate,因为要页面一上来就直接刷新
- // 一刷新发现newValue为空字符串,所以indexOf为0,所以直接将所有数据进行展示【'abc'.indexOf('')===0|||'abc'.indexOf('a')===0】
- immediate:true,
- handler(newValue) {
- // console.log('kwyWord被改变',newValue);
- // filter:过滤器【过滤掉不想要的东西,返回的是全新的数组】
- this.filPersons = this.persons.filter((p) => {
- // return 返回的是要的内容
- // indexOf--如果返回-1,则表示不包含,如果返回值不为-1,则表示找到并返回索引值,如果返回值为0,则表示包含空字符串
- return p.name.indexOf(newValue) !== -1
- })
- }
- }
- }
- })
- </script>
-
- </html>
- <body>
- <div id="root">
- <h2>人员列表</h2>
- <!-- persons一变就重新解析模板,整个列表就发生变化了 -->
- <!-- 收集用户输入:给输入框绑定双向数据绑定 -->
- <input type="text" placeholder="请输入名字" v-model="keyWord">
- <li v-for="(p,index) in filPersons" :key="index">
- {{p.name}}--{{p.age}}---{{p.sex}}
- </li>
- </div>
- </body>
-
- <script type="text/javascript">
- new Vue({
- el: '#root',
- data: {
- keyWord: '',
- persons: [
- { id: '001', name: '马冬梅', age: 19, sex: '女' },
- { id: '002', name: '周冬雨', age: 21, sex: '女' },
- { id: '003', name: '周杰伦', age: 11, sex: '男' },
- { id: '004', name: '温兆伦', age: 13, sex: '男' }
- ]
- },
- computed:{
- // 默认只有get
- filPersons(){
- return this.persons.filter((p)=>{
- // keyWord怎么变我不用去监视
- return p.name.indexOf(this.keyWord)!==-1
- })
- }
- }
- })
- </script>
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>列表排序</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
-
- <body>
- <div id="root">
- <h2>人员列表</h2>
- <!-- persons一变就重新解析模板,整个列表就发生变化了 -->
- <!-- 收集用户输入:给输入框绑定双向数据绑定 -->
- <input type="text" placeholder="请输入名字" v-model="keyWord">
- <button @click="sortType=2">年龄升序</button>
- <button @click="sortType=1">年龄降序</button>
- <button @click="sortType=0">原顺序</button>
- <li v-for="(p,index) in filPersons" :key="index">
- {{p.name}}--{{p.age}}---{{p.sex}}
- </li>
- </div>
- </body>
-
- <script type="text/javascript">
- new Vue({
- el: '#root',
- data: {
- // 获取用户输入的名字
- keyWord: '',
- //0代表原顺序,1降序,2升序
- sortType:0,
- persons: [
- { id: '001', name: '马冬梅', age: 19, sex: '女' },
- { id: '002', name: '周冬雨', age: 21, sex: '女' },
- { id: '003', name: '周杰伦', age: 11, sex: '男' },
- { id: '004', name: '温兆伦', age: 13, sex: '男' }
- ]
- },
- // 计算属性
- computed:{//计算属性最终的结果都是return出来的
- // 默认只有get
- filPersons(){
- //先将搜索结果保存起来,才可以进行后续的排序,如果直接返回出去就无法操作搜索结果
- const arr=this.persons.filter((p)=>{
- // keyWord怎么变我不用去监视
- return p.name.indexOf(this.keyWord)!==-1
- })
- // 判断一下是否要排序
- if(this.sortType){
- // 记得排序的是过滤后的结果(arr)
- arr.sort((p1,p2)=>{
- // 判断此时是1还是2
- return this.sortType===1?p2.age-p1.age :p1.age-p2.age
- })
- }
- // 记得返回
- return arr
- }
- }
- })
-
-
- /*sort改变数组
- let arr=[1,2,4,5,6]
- arr.sort((a,b)=>{
- // a-b:表示升序
- // b-a:表示降序
- return a-b
- })
- console.log(arr);
- */
- </script>
-
- </html>
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
-
- <body>
-
- <!-- v-for指令:
- 1.用于展示列表数据
- 2.语法:<li v-for="(item, index) in xxx" :key="yyy">,其中key可以是index,也可以是遍历对象的唯一标识
- 3.可遍历:数组、对象、字符串(用的少)、指定次数(用的少) -->
-
- <div id="root">
- <h2>人员列表</h2>
- <button @click="updateMei">点击更新马冬梅的信息</button>
- <ul>
- <li v-for="p in persons" :key="p.id">
- {{p.name}}--{{p.age}}
- </li>
- </div>
- </body>
-
- <script type="text/javascript">
- new Vue({
- el: '#root',
- data: {
- persons: [
- { id: '001', name: '马冬梅', age: 19, sex: '女' },
- { id: '002', name: '周冬雨', age: 21, sex: '女' },
- { id: '003', name: '周杰伦', age: 11, sex: '男' },
- { id: '004', name: '温兆伦', age: 13, sex: '男' }
- ]
- },
- methods: {
- updateMei(){
- // 修改后Vue页面更新了
- // this.persons[0].age=10
- // this.persons[0].name='马老师'
-
- // Vue页面并没有更新
- this.persons[0]={ id: '001', name: '马老师', age: 10, sex: '女' }
- }
- },
- })
- </script>
-
- </html>
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- </head>
- <body>
- <script type="text/javascript">
- let data={
- name:'小林学校',
- address:'广东省'
- }
-
- // 创建一个监视的实例对象
- const obs=new Observer(data)
-
- // 创建一个vm实例对象
- let vm={}
- vm._data=data=obs
-
- function Observer(obj){
- // 汇总对象中所有的属性形成一个数组
- const keys=Object.keys(obj)
- // 遍历
- keys.forEach((k)=>{
- Object.defineProperties(this,k,{
- get(){
- return obj[k]
- },
- set(value){
- console.log(`${k}被改了,我要去解析模板了`);
- obj[k]=value
- }
- })
- })
- }
-
- // 使用下面这个方法会出现栈溢出
- /*
- Object.defineProperties(data,'name',{
- get(){
- return data.name
- },
- set(val){
- data.name=val
- }
- })
- */
- </script>
- </body>
- </html>
注意点:set中的target(第一个参数)中不允许出现vm或者vm.data。
- <!-- 表示当student.sex===true的时候展示 -->
- <h2 v-if="student.sex">性别:{{student.sex}}</h2>
-
- <script type="text/javascript">
- const vm=new Vue({
- el: '#root',
- data: {
- name:'小林学校',
- address:'广东省' ,
- student:{
- name:'tom',
- age:{
- rAge:19,
- sAge:20,
- },
- friends:[
- {name:'Tom',age:34},
- {name:'Jerry',age:33}
- ]
- }
- },
- methods: {
- addSex(){
- Vue.set(this.student,'sex','男')
- }
- },
- })
- </script>
- <!-- 表示当student.sex===true的时候展示 -->
- <h2 v-if="student.sex">性别:{{student.sex}}</h2>
-
- <script type="text/javascript">
- const vm=new Vue({
- el: '#root',
- data: {
- name:'小林学校',
- address:'广东省' ,
- student:{
- name:'tom',
- age:{
- rAge:19,
- sAge:20,
- },
- friends:[
- {name:'Tom',age:34},
- {name:'Jerry',age:33}
- ]
- }
- },
- methods: {
- addSex(){
- // Vue.set(this.student,'sex','男')
- this.set(this.student,'sex','男')
- }
- },
- })
- </script>
注意点:set中的target(第一个参数)中不允许出现vm或者vm.data。
vm.$set(vm._data.student,'sex','男')等价于vm.$set(vm.student,'sex','男')
解决方法:只能在data中创建一个对象,把要的数据放进去
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
-
- <body>
-
-
- <div id="root">
- <h1>学校信息</h1>
- <h2>学校名称:{{school.name}}</h2>
- <h2>学校地址:{{school.address}}</h2>
- <!-- leader是查看data中是否包含leader这个属性 -->
- <h2>小张是:{{school.leader}}</h2>
- <!-- 注意点:在Vue中如果a不存在,则访问a则报错 -->
- <!-- 如果a存在,b不存在,则a.b不报错 -->
- <hr>
- <h1>学生信息</h1>
- <button @click="addSex">添加一个性别属性,默认值为男</button>
- <h2>学生姓名:{{student.name}}</h2>
- <hr>
- <h2>学生真实年龄:{{student.age.rAge}}</h2>
- <hr>
- <h2>学生对外年龄:{{student.age.sAge}}</h2>
- <hr>
- <!-- 表示当student.sex===true的时候展示 -->
- <h2 v-if="student.sex">性别:{{student.sex}}</h2>
- <h2>朋友们</h2>
- <ul>
- <li v-for="(f,index) in student.friends" :key="index">
- {{f.name}}--{{f.age}}
- </li>
- </ul>
- </div>
- </body>
-
- <script type="text/javascript">
- const vm = new Vue({
- el: '#root',
- data: {
- school: {
- name: '小林学校',
- address: '广东省',
- },
- student: {
- name: 'tom',
- age: {
- rAge: 19,
- sAge: 20,
- },
- friends: [
- { name: 'Tom', age: 34 },
- { name: 'Jerry', age: 33 }
- ]
- },
-
- },
- methods: {
- addSex() {
- // Vue.set(this.student,'sex','男')
- this.$set(this.student, 'sex', '男')
- }
- },
- })
- </script>
-
- </html>
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
-
- <body>
-
-
- <div id="root">
- <h1>学校信息</h1>
- <h2>学校名称:{{school.name}}</h2>
- <h2>学校地址:{{school.address}}</h2>
- <!-- leader是查看data中是否包含leader这个属性 -->
- <h2>小张是:{{school.leader}}</h2>
- <!-- 注意点:在Vue中如果a不存在,则访问a则报错 -->
- <!-- 如果a存在,b不存在,则a.b不报错 -->
- <hr>
- <h1>学生信息</h1>
- <button @click="addSex">添加一个性别属性,默认值为男</button>
- <h2>学生姓名:{{student.name}}</h2>
- <hr>
- <h2>学生真实年龄:{{student.age.rAge}}</h2>
- <hr>
- <h2>学生对外年龄:{{student.age.sAge}}</h2>
- <hr>
- <h2>爱好</h2>
- <ul>
- <li v-for="(h,index) in student.hobby" :key="index">
- {{h}}
- </li>
- </ul>
- <!-- 表示当student.sex===true的时候展示 -->
- <h2 v-if="student.sex">性别:{{student.sex}}</h2>
- <h2>朋友们</h2>
- <ul>
- <li v-for="(f,index) in student.friends" :key="index">
- {{f.name}}--{{f.age}}
- </li>
- </ul>
- </div>
- </body>
-
- <script type="text/javascript">
- const vm = new Vue({
- el: '#root',
- data: {
- school: {
- name: '小林学校',
- address: '广东省',
- },
- student: {
- name: 'tom',
- age: {
- rAge: 19,
- sAge: 20,
- },
- hobby:['抽烟','喝酒','烫头'],
- friends: [
- { name: 'Tom', age: 34 },
- { name: 'Jerry', age: 33 }
- ]
- },
-
- },
- methods: {
- addSex() {
- // Vue.set(this.student,'sex','男')
- this.$set(this.student, 'sex', '男')
- }
- },
- })
- </script>
-
- </html>
官网:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8" />
- <title>Vue数据监视</title>
- <style>
- button{
- margin-top: 10px;
- }
- </style>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
- <body>
-
- <!-- 总结:
- Vue监视数据的原理:
- 1.vue会监视data中所有层次的数据
- 2.如何监测对象中的数据?
- 通过setter实现监视,且要在new Vue时就传入要监测的数据
- (1)对象中后追加的属性,Vue默认不做响应式处理
- (2)如需给后添加的属性做响应式,请使用如下API:
- Vue.set(target,propertyName/index,value)
- vm.$set(target,propertyName/index,value)
- 3. 如何监测数组中的数据?
- 通过包裹数组更新元素的方法实现,本质就是做了两件事:
- (1)调用原生对应的方法对数组进行更新
- (2)重新解析模板,进而更新页面
- 4.在Vue修改数组中的某个元素一定要用如下方法:
- (1)使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
- (2)Vue.set() 或 vm.$set()
- 特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象(data等) 添加属性 -->
-
- <div id="root">
- <h1>学生信息</h1>
- <button @click="student.age++">年龄+1岁</button><br/>
- <button @click="addSex">添加性别属性,默认值:男</button> <br/>
- <button @click="addFriend">在列表首位添加一个朋友</button> <br/>
- <button @click="updateFirstFriendName">修改第一个朋友的名字为:张三</button><br/>
- <button @click="addHobby">添加一个爱好</button> <br/>
- <button @click="updateHobby">修改第一个爱好为:开车</button><br/>
- <button @click="removeSmoke">过滤掉爱好中的抽烟</button> <br/>
- <h3>姓名:{{student.name}}</h3>
- <h3>年龄:{{student.age}}</h3>
- <!-- 添加:v-if="student.sex"--是当不设置性别的时候,不出现性别1这个对话 -->
- <h3 v-if="student.sex">性别:{{student.sex}}</h3>
- <h3>爱好:</h3>
- <ul>
- <li v-for="(h,index) in student.hobby" :key="index">
- {{h}}
- </li>
- </ul>
- <h3>朋友们:</h3>
- <ul>
- <li v-for="(f,index) in student.friends" :key="index">
- {{f.name}}--{{f.age}}
- </li>
- </ul>
- </div>
- </body>
-
- <script type="text/javascript">
- Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
-
- const vm = new Vue({
- el:'#root',
- data:{
- student:{
- name:'tom',
- age:18,
- hobby:['抽烟','喝酒','烫头'],
- friends:[
- {name:'jerry',age:35},
- {name:'tony',age:36}
- ]
- }
- },
- methods: {
- addSex(){
- // vm._data.student===this.student
- //Vue.set(this.student,'sex','男')
- this.$set(this.student,'sex','男')
- },
- // 在首位添加
- addFriend(){
- // friends中的是对象
- // 使用Array中的API
- //响应式,因为有set和get方法
- this.student.friends.unshift({name:'jack',age:70})
- },
- updateFirstFriendName(){
- // this.student.friends[0]=13//可以进行修改,但是Vue不承认
- // this.student.friends[0].name--是对象,所以有get和set
- this.student.friends[0].name = '张三'
- },
- addHobby(){
- this.student.hobby.push('学习')
- },
- updateHobby(){
- // 报错,因为操作了数组
- // this.student.hobby[0]='开车'
- // 方式一:
- this.student.hobby.splice(0,1,'开车')
- // 方式二:
- // this.set(this.student.hobby,0,'开车')
- // 方式三:
- // this.$set(this.student.hobby,0,'开车')
- },
- removeSmoke(){
- //将新的数组代替原来的数组
- this.student.hobby = this.student.hobby.filter((h)=>{
- return h !== '抽烟'
- })
- }
- }
- })
- </script>
- </html>
Vue监视数据的原理:
1.vue会监视data中所有层次的数据
2.如何监测对象中的数据?
通过setter实现监视,且要在new Vue时就传入要监测的数据
(1)对象中后追加的属性,Vue默认不做响应式处理
(2)如需给后添加的属性做响应式,请使用如下API:
Vue.set(target,propertyName/index,value)
vm.$set(target,propertyName/index,value)
3. 如何监测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事:
(1)调用原生对应的方法对数组进行更新【push等】
(2)重新解析模板,进而更新页面
4.在Vue修改数组中的某个元素一定要用如下方法:
(1)使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
(2)Vue.set() 或 vm.$set()
特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象(data等) 添加属性
- <!-- 因为这里需要获取value值 -->
- 学习<input type="checkbox" v-model="hobby" value="study">
- 打游戏<input type="checkbox" v-model="hobby" value="game">
- 吃饭<input type="checkbox" v-model="hobby" value="eat">
- <br/><br/>
-
- <script type="text/javascript">
- new Vue({
- el:'#root',
- data:{
- // 注意:hobby是一个多选项,所以hobby初始值是数组
- hobby:[],
- },
- })
- </script>
- <!-- 这里不需要获取value,只需要知道是true还是false -->
- <input type="checkbox" v-model="agree">阅读并接受<a href="http://www.baidu.com">《用户协议》</a>
-
-
- <script type="text/javascript">
- new Vue({
- el:'#root',
- data:{
- agree:''
- },
- })
- </script>
如果是多选框,则要注意一下几点:
(1)要给每一个input框添加一个value值
(2)要将v-model绑定的值设置为数组
- <button @click="submit">提交</button>
-
-
- <script type="text/javascript">
- new Vue({
- el:'#root',
- data:{
- },
- methods: {
- submit(e){
- e.preventDefault();
- }
- },
- })
- </script>
- <!-- type="number":用于控制文本框中只能输入number -->
- <!-- v-model.number="userInfo.age":使得收集到为number -->
- <!-- 上面两个同时使用 -->
- 年龄:<input type="number" v-model.number="userInfo.age"><br><br>
过滤器可以对前面你写的数据进行按照某种形式加工处理
将其下载下来
<script type="text/javascript" src="./dayjs.min.js"></script>
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>收集表单数据</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- <script type="text/javascript" src="./dayjs.min.js"></script>
- </head>
-
- <body>
- <div id="root">
- <h2>显示格式化后的时间</h2>
- <!-- 使用计算属性格式化时间 -->
- <h3>现在是:{{fmtTime}}</h3>
- </div>
- </body>
- <script type="text/javascript">
- new Vue({
- el: '#root',
- data: {
- time:1677890911030 //时间戳
- },
- computed: {
- fmtTime(){
- return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
- }
- },
- })
- </script>
-
- </html>
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>收集表单数据</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- <script type="text/javascript" src="./dayjs.min.js"></script>
- </head>
-
- <body>
- <div id="root">
- <h2>显示格式化后的时间</h2>
- <!-- methods实现格式化时间 -->
- <!-- 因为是方法,所以记得小括号 -->
- <h3>现在是:{{getFmtTime()}}</h3>
- </div>
- </body>
- <script type="text/javascript">
- new Vue({
- el: '#root',
- data: {
- time:1677890911030 //时间戳
- },
- methods: {
- getFmtTime(){
- return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
- }
- },
- })
- </script>
-
- </html>
- <!-- 过滤器实现 -->
- <!-- 不带参数的 -->
- <h3>现在是:{{time | timeformater}}</h3>
- <!-- 带参数的 -->
- <h3>现在是:{{time | timeformater('YYYY-MM-DD')}}</h3>
-
-
- filters:{
- // 过滤器的本质是一个函数
- // 这里写str的初始值是为了以防timeformater没有传入参数的
- timeformater(value,str='YYYY-MM-DD'){
- // 这个value指的是time
- console.log('@',value);
- // return 'hello'
- return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
- }
- }
注意点:time是一个一个传的,不会直接给mySlice
- <h3>现在是:{{time | timeformater('YYYY-MM-DD') | mySlice}}</h3>
-
- filters:{
- // 过滤器的本质是一个函数
- // 这里写str的初始值是为了以防timeformater没有传入参数的
- timeformater(value,str='YYYY-MM-DD'){
- // 这个value指的是time
- console.log('@',value);
- // return 'hello'
- return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
- },
- mySlice(value,str='YYYY-MM-DD'){
- // 截取前4位
- return value.slice(0,4)
- }
- }
注意点:是filter不是filters
必须写在new实例之前
- // 全局过滤器
- Vue.filter('mySlice',function(value){
- // 截取前4位
- return value.slice(0,4)
- })
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>收集表单数据</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- <script type="text/javascript" src="./dayjs.min.js"></script>
- </head>
-
- <body>
-
- <!-- 过滤器:
- 1.定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
- 2.语法:
- (1)注册过滤器:Vue.filter(name,callback) 或 new Vue{filters:{}}
- (2)使用过滤器:{{ xxx | 过滤器名}} 或 v-bind:属性 = "xxx | 过滤器名"
- 备注:
- 1.过滤器可以接收额外参数,多个过滤器也可以串联
- 2.并没有改变原本的数据,而是产生新的对应的数据 -->
-
- <div id="root">
- <h2>显示格式化后的时间</h2>
- <!-- 使用计算属性格式化时间 -->
- <h3>现在是:{{fmtTime}}</h3>
- <!-- methods实现格式化时间 -->
- <!-- 因为是方法,所以记得小括号 -->
- <h3>现在是:{{getFmtTime()}}</h3>
- <!-- 过滤器实现 -->
- <!-- 不带参数的 -->
- <h3>现在是:{{time | timeformater}}</h3>
- <!-- 带参数的 -->
- <h3>现在是:{{time | timeformater('YYYY-MM-DD') | mySlice}}</h3>
- </div>
-
- <div id="root2">
- <h1>{{msg}}</h1>
- <h2 :x="message | mySlice">动态绑定中使用过滤器</h2>
- </div>
-
-
- </body>
- <script type="text/javascript">
- Vue.config.productionsTip=false
- // 全局过滤器
- Vue.filter('mySlice',function(value){
- // 截取前4位
- return value.slice(0,4)
- })
- const vm1=new Vue({
- el: '#root',
- data: {
- time:1677890911030, //时间戳
- message:'您好'
- },
- computed: {
- fmtTime(){
- return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
- }
- },
- methods: {
- getFmtTime(){
- return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
- }
- },
- // 局部过滤器
- filters:{
- // 过滤器的本质是一个函数
- // 这里写str的初始值是为了以防timeformater没有传入参数的
- timeformater(value,str='YYYY-MM-DD'){
- // 这个value指的是time
- console.log('@',value);
- // return 'hello'
- return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
- },
- mySlice(value,str='YYYY-MM-DD'){
- // 截取前4位
- return value.slice(0,4)
- }
- }
- })
-
- const vm2=new Vue({
- el:'#root2',
- data:{
- msg:'hello'
- }
- })
-
- </script>
-
-
-
- </html>
filter只能在插值语法和v-bind中使用,不能再v-model中使用
过滤器产生的是一个新的结果,记得要重新赋值
之前学过的指令:
v-bind:单向绑定解析表达式,可简写为:
v-model:双向数据绑定
v-for:遍历数组 / 对象 / 字符串
v-on:绑定事件监听,可简写为@
v-if:条件渲染(动态控制节点是否存存在)
v-else:条件渲染(动态控制节点是否存存在)
v-show:条件渲染 (动态控制节点是否展示)
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>收集表单数据</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
-
- <body>
-
- <!--
- 之前学过的指令:
- v-bind:单向绑定解析表达式,可简写为:
- v-model:双向数据绑定
- v-for:遍历数组 / 对象 / 字符串
- v-on:绑定事件监听,可简写为@
- v-if:条件渲染(动态控制节点是否存存在)
- v-else:条件渲染(动态控制节点是否存存在)
- v-show:条件渲染 (动态控制节点是否展示)
- v-text指令:
- 作用:向其所在的节点中渲染文本内容
- 与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。 -->
-
- <div id="root">
- <div>{{name}}</div>
- <div v-text="name"></div>
- <div v-text="str"></div>
- </div>
-
-
-
- </body>
- <script type="text/javascript">
- Vue.config.productionsTip=false
- const vm1=new Vue({
- el: '#root',
- data: {
- name:'小坤',
- str:'<h3>您好</h3>'
- }
- })
-
- </script>
-
-
-
- </html>
v-text指令:
作用:向其所在的节点中渲染文本内容
注意点:v-text不会解析标签
与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。
- <!DOCTYPE html>
- <html lang="en">
-
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>收集表单数据</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
-
- <body>
-
-
-
- <div id="root">
- <!-- 可以解析标签 -->
- <div v-html="str"></div>
- <!-- 不可以解析标签 -->
- <div v-text="str"></div>
- </div>
-
-
-
- </body>
- <script type="text/javascript">
- Vue.config.productionsTip=false
- // 全局过滤器
- Vue.filter('mySlice',function(value){
- // 截取前4位
- return value.slice(0,4)
- })
- const vm1=new Vue({
- el: '#root',
- data: {
- name:'小坤',
- str:'<h3>您好</h3>'
- }
- })
-
- </script>
-
-
-
- </html>
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8" />
- <title>v-html指令</title>
- <script type="text/javascript" src="../js/vue.js"></script>
- </head>
- <body>
- <div id="root">
- <div>Hello,{{name}}</div>
- <div v-html="str"></div>
- <div v-html="str2"></div>
- </div>
- </body>
-
- <script type="text/javascript">
- Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
-
- new Vue({
- el:'#root',
- data:{
- name:'JOJO',
- str:'<h3>你好啊!</h3>',
- // document.cookie:获取当前网站是所有cookie
- str2:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>兄弟我找到你想要的资源了,快来!</a>',
- }
- })
- </script>
- </html>
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8" />
- <title>v-once指令</title>
- <script type="text/javascript" src="./js/vue.min.js"></script>
- </head>
- <body>
-
- <!-- v-once指令:
- 1.v-once所在节点在初次动态渲染后,就视为静态内容了
- 2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能 -->
-
- <div id="root">
- <h2 v-once>n初始化的值是:{{n}}</h2>
- <h2>n现在的值是:{{n}}</h2>
- <button @click="n++">点我n+1</button>
- </div>
- </body>
-
- <script type="text/javascript">
- Vue.config.productionTip = false
-
- new Vue({
- el:'#root',
- data:{
- n:1
- }
- })
- </script>
- </html>
v-once指令:
1.v-once所在节点在初次动态渲染后,就视为静态内容了
2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8" />
- <title>v-pre指令</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
- <body>
-
- <!-- v-pre指令:
- 1.跳过其所在节点的编译过程。
- 2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译 -->
-
- <div id="root">
- <h2 v-pre>Vue其实很简单</h2>
- <h2>当前的n值是:{{n}}</h2>
- <button @click="n++">点我n+1</button>
- </div>
- </body>
-
- <script type="text/javascript">
- Vue.config.productionTip = false
-
- new Vue({
- el:'#root',
- data:{
- n:1
- }
- })
- </script>
- </html>
v-pre指令:
1.跳过其所在节点的编译过程。
2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译
- <!DOCTYPE html>
- <html>
-
- <head>
- <meta charset="UTF-8" />
- <title>自定义指令</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
- <!--
- 需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。
- -->
-
- <body>
- <div id="root">
- <h2>当前的n值是:<span v-text="n"></span> </h2>
- <h2>放大10倍后的n值是:<span v-big="n"></span> </h2>
- <button @click="n++">点我n+1</button>
- </div>
- </body>
-
- <script type="text/javascript">
- Vue.config.productionTip = false
-
- new Vue({
- el: '#root',
- data: {
- n: 1
- },
- directives: {
- //big函数何时会被调用?1.指令与元素成功绑定时(一上来) 2.指令所在的模板被重新解析时
- // element:获取真实的DOM元素
- // binding:是一个对象,里面包含value
- big(element, binding) {
- // console.log(element,binding);
- console.log('big', this) //注意此处的this是window
- element.innerText = binding.value * 10
- }
- }
- })
- </script>
-
- </html>
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8" />
- <title>自定义指令</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
- <!--
- 需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。
- -->
- <body>
- <div id="root">
- <hr/>
- <input type="text" v-fbind:value="n">
- </div>
- </body>
-
- <script type="text/javascript">
- Vue.config.productionTip = false
-
- new Vue({
- el:'#root',
- data:{
- n:1
- },
- directives:{
- // 如果fbind是一个函数,则无法解决问题
- // 因为fbind被调用的情况只有2种:1.指令与元素成功绑定时(一上来)【bind】 2.指令所在的模板被重新解析时【update】
- // 所以将fbind写为对象
- // fbind中必须出现的3个函数[名字不能改变]
- fbind:{
- //指令与元素成功绑定时(一上来)
- // element指的是input
- bind(element,binding){
- element.value = binding.value
- },
- //指令所在元素被插入页面时
- inserted(element,binding){
- element.focus()
- },
- //指令所在的模板被重新解析时
- update(element,binding){
- element.value = binding.value
- }
- }
- }
- })
- </script>
- </html>
- <h2>放大10倍后的n值是:<span v-big-number="n"></span> </h2>
-
- directives: {
- //big函数何时会被调用?1.指令与元素成功绑定时(一上来) 2.指令所在的模板被重新解析时
- 'big-number'(element, binding) {
- console.log('big', this) //注意此处的this是window
- element.innerText = binding.value * 10
- }
- }
- // 全局指令
- Vue.directive('fbind2', {
- //指令与元素成功绑定时(一上来)
- bind(element, binding) {
- console.log('fbind-bind', this); //window
- element.value = binding.value
- },
- //指令所在元素被插入页面时
- inserted(element, binding) {
- console.log('fbind-inserted', this); //window
- element.focus()
- },
- //指令所在的模板被重新解析时
- update(element, binding) {
- console.log('fbind-update', this); //window
- element.value = binding.value
- }
- })
1.局部指令:
- new Vue({
- directives:{指令名:配置对象}
- })
- new Vue({
- directives:{指令名:回调函数}
- })
2.全局指令:
Vue.directive(指令名,配置对象)
Vue.directive(指令名,回调函数)
- Vue.directive('fbind',{
- //指令与元素成功绑定时(一上来)
- bind(element,binding){
- element.value = binding.value
- },
- //指令所在元素被插入页面时
- inserted(element,binding){
- element.focus()
- },
- //指令所在的模板被重新解析时
- update(element,binding){
- element.value = binding.value
- }
- })
bind(element,binding)
:指令与元素成功绑定时调用inserted(element,binding)
:指令所在元素被插入页面时调用update(element,binding)
:指令所在模板结构被重新解析时调用
指令定义时不加“v-”,但使用时要加“v-”
指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名
- new Vue({
- el:'#root',
- data:{
- n:1
- },
- directives:{
- 'big-number'(element,binding){
- element.innerText = binding.value * 10
- }
- }
- })
- <script type="text/javascript">
- Vue.config.productionTip = false
-
- const vm=new Vue({
- el: '#root',
- data: {
- opacity: 1
- },
- })
-
- // 通过外部的定时器实现(不推荐)
- setInterval(()=>{
- vm.opacity-=0.01
- if(vm.opacity<=0)
- vm.opacity=1
- })
- </script>
- // Vue完成模板的解析并把【初始】真实的DOM元素放入页面后(挂载完毕)调用mounted
- mounted() {
- // console.log('mounted');
- // setInterval中的this指的是window,但是往外找是mounted,应该是vm
- setInterval(() => {
- this.opacity -= 0.01
- if (this.opacity <= 0)
- this.opacity = 1
- })
- },
生命周期:
(1)又名:生命周期回调函数、生命周期函数、生命周期钩子
(2)是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数
(3)生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的
(4)生命周期函数中的this指向是vm 或 组件实例对象
- <!DOCTYPE html>
- <html>
-
- <head>
- <meta charset="UTF-8" />
- <title>自定义指令</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
-
- <body>
- <div id="root">
- <h2>当前的n值是:{{n}}</h2>
- <button @click="add">点我n+1</button>
- </div>
- </body>
-
- <script type="text/javascript">
- Vue.config.productionTip = false
-
- new Vue({
- el: '#root',
- // template:
- // `
- // <div>
- // <h2>当前的n值是:{{n}}</h2>
- // <button @click="add">点我n+1</button>
- // </div>
- // `,
- data: {
- n: 0
- },
- methods: {
- add() {
- this.n++
- }
- },
- // 无法获取data和methods
- beforeCreate() {
- console.log('beforeCreate');
- // console.log(this);//vm
- // debugger
- },
-
- // 获取data和methods,并且进行数据监测和数据代理
- created() {
- console.log('created');
- // console.log(this);//vm
- },
- // 页面呈现的是未经过Vue变量的DOM结构
- // 存在内存中
- beforeMount() {
- console.log('beforeMount');
- },
- // Vue完成模板的解析并把【初始】真实的DOM元素放入页面后(挂载完毕)调用mounted
- // 将内存中的虚拟DOM转为真正的DOM(经过Vue编译的DOM)
- // 对DOM的操作均有效,但是尽可能避免
- mounted() {
- console.log('mounted');
- },
- })
- </script>
-
- </html>
- <!DOCTYPE html>
- <html>
-
- <head>
- <meta charset="UTF-8" />
- <title>生命周期</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
-
- <body>
- <div id="root">
- <h2>当前的n值是:{{n}}</h2>
- <button @click="add">点我n+1</button>
- </div>
- </body>
-
- <script type="text/javascript">
- Vue.config.productionTip = false
-
- new Vue({
- el: '#root',
- // template:
- // `
- // <div>
- // <h2>当前的n值是:{{n}}</h2>
- // <button @click="add">点我n+1</button>
- // </div>
- // `,
- data: {
- n: 0
- },
- methods: {
- add() {
- this.n++
- }
- },
- // 此时数据是新的,但是页面是旧的
- beforeUpdate() {
- console.log('beforeUpdate');
- },
- // 此时数据是新的,页面也更新了
- updated() {
- console.log('updated');
- },
- })
- </script>
-
- </html>
在beforeDestroy 可以调用到data,methods,但是对数据的修改不起作用
// 此时vm中所有的data,methods,指令等还是可以使用的,但是实际上数据并不会被更新 // 此时:关闭定时器,取消订阅,解绑自定义事件 beforeDestroy() { console.log('befoeDestroy'); },
- <!DOCTYPE html>
- <html>
-
- <head>
- <meta charset="UTF-8" />
- <title>生命周期</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
-
- <body>
- <div id="root">
- <h2>当前的n值是:{{n}}</h2>
- <button @click="add">点我n+1</button>
- <button @click="bye">点我销毁</button>
- </div>
- </body>
-
- <script type="text/javascript">
- Vue.config.productionTip = false
-
- new Vue({
- el: '#root',
- data: {
- n: 0
- },
- methods: {
- add() {
- this.n++
- },
- bye(){
- console.log('bey');
- }
- },
- // 此时vm中所有的data,methods,指令等还是可以使用的,但是实际上数据并不会被更新
- // 此时:关闭定时器,取消订阅,解绑自定义事件
- beforeDestroy() {
- console.log('befoeDestroy');
- },
- // 此时,vm上的与组件的联系断开,并且事件监听器也断开
- destroyed() {
- console.log('destoryed');
- },
- })
- </script>
-
- </html>
完整视频:052_尚硅谷Vue技术_生命周期_总结_哔哩哔哩_bilibili
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8" />
- <title>引出生命周期</title>
- <script type="text/javascript" src="./js/vue.js"></script>
- </head>
- <body>
- <!--
- 常用的生命周期钩子:
- 1.mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等初始化操作
- 2.beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等收尾工作
- 关于销毁Vue实例:
- 1.销毁后借助Vue开发者工具看不到任何信息
- 2.销毁后自定义事件会失效,但原生DOM事件依然有效
- 3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了 -->
-
-
- <div id="root">
- <h2 :style="{opacity}">欢迎学习Vue</h2>
- <button @click="opacity = 1">透明度设置为1</button>
- <button @click="stop">点我停止变换</button>
- </div>
- </body>
-
- <script type="text/javascript">
- Vue.config.productionTip = false
-
- new Vue({
- el:'#root',
- data:{
- opacity:1
- },
- methods: {
- stop(){
- // 直接清除(暴力)
- this.$destroy()
- }
- },
- mounted(){
- console.log('mounted',this)
- this.timer = setInterval(() => {
- console.log('setInterval')
- this.opacity -= 0.01
- if(this.opacity <= 0) this.opacity = 1
- },16)
- },
- // 在清除vm之前,先将定时器清除
- // 为什么将这个写在beforeDestroy中,因为如果在destory中写,不知道是“他杀”还是“自杀”
- // 但是无论是什么“杀”,都要经过beforeDestroy
- beforeDestroy() {
- clearInterval(this.timer)
- console.log('vm即将驾鹤西游了')
- },
- })
- </script>
- </html>
mounted
:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等初始化操作
beforeDestroy
:清除定时器、解绑自定义事件、取消订阅消息等收尾工作
销毁后借助Vue开发者工具看不到任何信息
销毁后自定义事件会失效,但原生DOM事件依然有效
一般不会在
beforeDestroy
操作数据,因为即便操作数据,也不会再触发更新流程了
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。