VUE学习笔记1

1. Vuejs的内容概述

  1. Vue是一个渐进式的框架(渐进式意味着你可以将Vue作为你应用的一部分嵌入其中,带来丰富的交互体验)

  2. Vue有很多特点和Web开发中常见的高级功能

    • 解耦视图和数据
    • 可复用的组件
    • 前端路由技术
    • 状态管理
    • 虚拟DOM
  3. 官方网站:https://vuejs.bootcss.com/guide/

  4. 安装vue的方法
    在这里插入图片描述

1.1 Vuejs初体验
<body>
<div id="app">
    <h2>{{message}}</h2>
    <h1>{{name}}</h1>
</div>
<div>{{message}}</div>
<script src="../js/vue.js"></script>
<script>
    // 定义变量let 定义常量const
    let app=new Vue({
        el:'#app',  // 用于挂载要管理的元素
        data:{  // 定义数据
            message:'你好啊,栀虞!',
            name:'coderwhy'
        }
    })
</script>
</body>
1.2 Vue列表展示
<body>
<div id="app">
    <ul>
        <li v-for="item in movies">{{item}}</li>
    </ul>
</div>
<script src="../js/vue.js"></script>
<script>
    const app=new Vue({
        el:'#app',
        data:{
            message:'你好啊',
            movies:['星际穿越','大话西游','少年派','盗梦空间','天赋异禀']
        }
    })
</script>
</body>

案例:计数器

<body>
<div id="app">
    <h2>当前计数: {{counter}}</h2>
    <!--<button v-on:click="counter++">+</button>
    <button v-on:click="counter--">-</button>-->
    <button v-on:click="add">+</button>
    <button v-on:click="sub">-</button>
</div>
<script src="../js/vue.js"></script>
<script>
    // 语法糖:简写
    const app=new Vue({
        // el:document.querySelector('#app'),
        el:'#app',
        data:{
            counter:0
        },
        methods:{
            add:function (){
                console.log('add被执行');
                this.counter++;
            },
            sub:function (){
                // console.log('sub被执行');
                this.counter--;
            }
        }
    })
</script>
</body>
1.3 Vue的MVVM

Model View ViewModel

  • View:视图层,在前端开发中通常是DOM层,给用户展示各种信息
  • Model:数据层,可能是固定的死数据,更多的是来自服务器,从网络上请求下来的数据
  • ViewModel:视图模型层,是View和Model沟通得桥梁,一方面绑定数据,另一方面实现DOM监听
1.4 Vue的options选项

options包含选项详细解析:https://cn.vuejs.org/v2/api/

目前需掌握:

  • el
    • 类型:string|HTMLElement
    • 作用:决定之后Vue实例管理哪一个DOM
  • data
    • 类型:Object|Function
    • 作用:Vue实例对应的数据对象
  • methods
    • 类型:{[key:string]:Function}
    • 作用:定义属于Vue的一些方法,可以在其他地方调用,也可以在指令中调用
1.5 Vue的生命周期

声明周期:事物从诞生到消亡的整个过程。

Vue生命周期:https://segmentfault.com/a/1190000011381906

1.6 定义Vue的Template
  1. 先在HTML中写如下代码(WebStrom)
    在这里插入图片描述

  2. 赋值红框中的代码,点击File->Setting->Editor->Live Templates->Vue

    在这里插入图片描述

  3. 按照下列步骤进行,之后在html代码中输入vue然后点击tab键即可出现模板

在这里插入图片描述

2. 模板语法

2.1 插值操作
2.1.1 mustache语法

Mustache语法也就是双大括号

<body>
<div id="app">
  <h2>{{message}}</h2>
  <h2>{{message}},李银河!</h2>
  <!-- mustache语法中,不仅仅可以直接写变量,也可以写简单的表达式 -->
  <h2>{{firstName+' '+lastName}}</h2>
  <h2>{{firstName}} {{lastName}}</h2>
  <h2>{{counter*4}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      message:'你好啊',
      firstName:'zhi',
      lastName:'yu',
      counter:100
    }
  })
</script>
</body>
2.1.2 其他指令使用
  1. v-once

    • 该指令后面不需要跟任何表达式

    • 该指令表示元素和组件只渲染一次,不会随着数据的改变而改变

      <h2>{{message}}</h2>
      <h2 v-once>{{message}}</h2>
      
  2. v-html

    • 该指令后面往往会跟上一个string类型

    • 会将string的HTML解析出来并且进行渲染

      <div id="app">
        <h2>{{url}}</h2>
        <h2 v-html="url"></h2>
      </div>
      <script src="../js/vue.js"></script>
      <script>
        const app=new Vue({
          el:"#app",
          data:{
            url:'<a href="https://www.baidu.com">百度一下</a>'
          }
        })
      </script>
      
  3. v-text

    • 与mustache相似,都是用于将数据显示在界面中

    • 通常情况下,接收一个string类型

      <h2>{{message}},栀虞!</h2>
      <!-- 一般不用,不够灵活 -->
      <h2 v-text="message">,栀虞!</h2>
      
  4. v-pre

    • 用于跳过这个元素和它子元素的编译过程,用于显示原本的Mustache语法

      <h2>{{message}}</h2>	// 你好啊
      <h2 v-pre>{{message}}</h2>  // {{message}} 把h2里面的内容原封不动显示,不需要解析
      
  5. v-cloak

    • 在某些情况下,浏览器可能会直接显示出未编译的Mustache标签

    • 在vue解析之前,div有一个属性v-cloak,在vue解析之后,div中没有一个属性v-cloak

      <style>
          [v-cloak]{
              display: none;
          }
      </style>
      <div id="app" v-cloak>  // 在解析之前,div标签不展示
        <h2>{{message}}</h2>
      </div>
      
2.2 v-bind的使用

作用:动态绑定属性

预期:any(with argument) | Object(without argument)

参数:attOrProp(optional)

2.2.1 v-bind的基本使用

v-bind:用于绑定一个或多个属性值,或者想另一个组件传递props值

简写::

<div id="app">
  <!-- <img v-bind:src="imgURL" alt="">
  <a v-bind:href="aHref">百度一下</a>   -->
  <!-- 语法糖写法 -->
  <img :src="imgURL" alt="">
  <a :href="aHref">百度一下</a>  
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      imgURL:'https://p6.itc.cn/images01/20211219/90211482300a418b88376f41258850f2.jpeg',
      aHref:'https://www.baidu.com'
    }
  })
</script>
2.2.2 v-bind的动态绑定class
  1. 对象语法
<!-- 用法一:直接通过{}绑定一个类 -->
<h2 v-bind:class="{active:isActive}">{{message}}</h2>
<!-- 用法二:也可以通过判断,传入多个值 -->
<h2 v-bind:class="{active:isActive,line:isLine}">{{message}}</h2>
<!-- 用法三:和普通的类同时存在,并不冲突 -->
<h2 class="title" v-bind:class="{active:isActive,line:isLine}">{{message}}</h2>
<!-- 方法四:如果过于复杂,可以放在一个methods或者computed中  classes是一个计算属性-->
<h2 class="title" :class="classes">{{message}}</h2>
<div id="app">
  
  <!--<h2 class="active">{{message}}</h2>
  <h2 :class="active">{{message}}</h2>-->

  <!--<h2 v-bind:class="{类名1:boolean,类名2:boolean}"></h2>-->
  <!-- title是固定的,不可删除,后面的active与line是可以改变的 -->
  <h2 class="title" v-bind:class="{active:isActive,line:isLine}">{{message}}</h2>
  <button v-on:click="btnClick">按钮</button>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      message:'你好啊',
      isActive:true,
      isLine:true
    },
    methods:{
      btnClick:function (){
        this.isActive=!this.isActive;
      }
    }
  })
</script>
  1. 数组语法
<div id="app">
  <h2 class="title" :class="[active,line]">{{message}}</h2>
  <h2 class="title" :class="getClasses()">{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      message:'你好啊',
      active:'aaaa',
      line:'bbbb'
    },
    methods:{
      getClasses:function (){
        return [this.active,this.line];
      }
    }
  })
</script>
2.2.3 v-bind的动态绑定style
  1. 对象语法

    <div id="app">
      <!--<h2 :style="{key(属性名):value(属性值)}">{{message}}</h2>-->
      <!-- value值必须加单引号,否则会当成一个变量去解析 -->
      <h2 :style="{fontSize:'50px',color:'red'}">{{message}}</h2>
      <!-- finalSize当成一个变量使用 -->
      <h2 :style="{fontSize:finalSize+'px',color:colorLine}">{{message}}</h2>
      <!-- methods使用 -->
      <h2 :style="getStyles()">{{message}}</h2>
    </div>
    <script src="../js/vue.js"></script>
    <script>
      const app=new Vue({
        el:"#app",
        data:{
          message:'你好啊',
          finalSize:50,
          colorLine:'red',
        },
        methods:{
          getStyles:function (){
            return {fontSize:this.finalSize+'px',color:this.colorLine}
          }
        }
      })
    </script>
    
  2. 数组语法

    <div id="app">
      <h2 :style="[baseStyle,baseStyle1]">{{message}}</h2>
    </div>
    <script src="../js/vue.js"></script>
    <script>
      const app=new Vue({
        el:"#app",
        data:{
          message:'你好啊',
          baseStyle:{color:'red',fontSize:'50px'},
          baseStyle1:{backgroundColor:'pink'}
        }
      })
    </script>
    
2.3 计算属性的使用
2.3.1 计算属性的基本使用
<div id="app">
  <h2>{{firstName+' '+lastName}}</h2>
  <h2>{{firstName}} {{lastName}}</h2>

  <!-- 使用methods -->
  <h2>{{getFullName()}}</h2>
  <!-- 计算属性 -->
  <h2>{{fullName}}</h2>
  <h2></h2>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      firstName:'zhiyu',
      lastName:'Jemas'
    },
    computed:{
    //  计算属性(),定义函数,
      fullName:function () {
        return this.firstName+' '+this.lastName;
      }
    },
    methods:{
      getFullName:function (){
        return this.firstName+' '+this.lastName;
      }
    }
  })
</script>
2.3.2 计算属性的复杂操作
<div id="app">
  <h2>总价格:{{totalPrice}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      books:[
        {id:110,name:'计算机系统基础',price:120},
        {id:111,name:'代码大全',price:110},
        {id:112,name:'深入理解计算机原理',price:78}
      ]
    },
    computed:{
      totalPrice:function (){
        let result=0;
        /*for(let i=0;i<this.books.length;i++){
          result+=this.books[i].price;
        }*/
        for(let i in this.books){
          result+=this.books[i].price;
        }
        // for(let book of this.books){}
        return result;
      }
    }
  })
</script>
2.3.3 计算属性的setter和getter

一般情况下,一般没有set方法,只读属性

<div id="app">
  <h2>{{fullName}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      firstName:'Kobe',
      lastName:'Bryant'
    },
    computed:{
      /* 简介写法
      fullName:function (){
        return this.firstName+' '+this.lastName;
      }*/
      /*  原本写法  */
      fullName:{
        set:function (newValues){
          const names=newValues.split(' ');
          this.firstName=names[0];
          this.lastName=names[1];
        },
        get:function (){
          return this.firstName+' '+this.lastName;
        }
      }
    }
  })
</script>
2.3.4 计算属性和methods的对比
<div id="app">
  <!-- 1.直接拼接:语法过于繁琐,一般不采用 -->
  <h2>{{firstName}} {{lastName}}</h2>
  <!-- 2. 通过定义methods:多次打印相同的,会多次调用函数 -->
  <h2>{{getFullName()}}</h2>
  <!-- 3. 通过定义computed:计算属性会进行缓存,如果多次使用,计算属性只会调用一次,性能更高 -->
  <h2>{{fullName}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      firstName:'Kobe',
      lastName:'Bryant'
    },
    computed:{
      fullName:function (){
        return this.firstName+' '+this.lastName;
      }
    },
    methods:{
      getFullName:function (){
        return this.firstName+' '+this.lastName;
      }
    }
  })
</script>

3. ES6补充语法

3.1 块级作用域-let和var

ES5之前,因为if和for都没有块级作用域的概念,所以在很多时候,我们必须借助于function的作用域来解决应用外面变量的问题。

ES6中,接入了let,let它是由if和for的作用域的。

  1. 变量作用域:变量在什么范围内是可用的

  2. 块级作用域:

    • JS中使用var来声明一个变量时,变量的作用域主要是和函数的定义有关
    • 针对于其他块定义来说是没有作用域的,比如if/for等
  3. let和var的区别

    使用var声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象;

    使用let声明的变量,其作用域为该语句所在的代码块内,不存在变量提升;

    https://blog.csdn.net/harborian/article/details/102521610

3.2 三种方案对比
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
  // 1. 没有块级作用域引起的问题
  // 为什么闭包可以解决问题:函数是一个作用域
  // 2. 情况一:ES5中没有使用闭包(错误的方式)
  var btns=document.querySelectorAll('button');
  for(var i=0;i<btns.length;i++){
    btns[i].addEventListener('click',function (){
      console.log('第'+i+'个按钮被点击');
    })
  }
  // 3. 情况二:ES5中使用闭包
  var btns=document.querySelectorAll('button');
  for(var i=0;i<btns.length;i++){
    (function (i){
      btns[i].addEventListener('click',function (){
        console.log('第'+i+'个按钮被点击');
      })
    })(i)
  }
  // 4. 情况三:ES6中的let
  const btns=document.querySelectorAll('button');
  for(let i=0;i<btns.length;i++){
    btns[i].addEventListener('click',function (){
      console.log('第'+i+'个按钮被点击');
    })
  }
</script>
</body>
3.3 const的使用和注意点

当修饰的标识符不会被再次赋值时,就可以使用const来保证数据的安全性

建议:在开发中,优先使用const,只有在需要改变某一标识符的时候才使用let

注意:const值不可以再次赋值,const修饰的标识符必须赋值,常量的含义是指向的对象不能修改,但是可以改变对象内部的属性

<script>
  const obj={
    name:'zhiyu',
    age:18,
    height:165
  }
  console.log(obj);
  obj.name='huahua';
  console.log(obj);
</script>
3.4 对象字面量增强写法
  1. 属性的增强写法
  2. 函数的增强写法
<script>
  // 1. 属性的增强写法
  const name='zhiyu';
  const age=18;
  const height=1.88;
  // ES5的写法
  const obj={
    name:name,
    age:age,
    height:height
  };
  // ES6写法
  const obj1={
    name,
    age,
    height
  }
  console.log(obj1);
  // 2. 函数的增强写法
  // ES5写法
  const obj2={
    run:function (){},
    eat:function (){}
  }
  // ES6写法
  const obj3={
    run(){},
    eat(){}
  }
</script>

4. 事件监听v-on

4.1 v-on的基本使用和语法糖
  1. 作用:绑定事件监听器
  2. 缩写:@
  3. 预期:Function|Inline Statement|Object
  4. 参数:event
<div id="app">
  <h2>{{counter}}</h2>
<!--  <button v-on:click="counter++">+</button>-->
<!--  <button v-on:click="counter&#45;&#45;">-</button>-->
<!--  <button v-on:click="increment">+</button>-->
<!--  <button v-on:click="decrement">-</button>-->
  <button @click="counter++">+</button>
  <button @click="counter--">-</button>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      counter:0
    },
    methods:{
      increment(){
        this.counter++;
      },
      decrement(){
        this.counter--;
      }
    }
  })
</script>
4.2 v-on的参数传递问题

当通过methods中定义方法,以供@click调用时,需要注意参数问题:

  1. 如果该方法不需要额外参数,那么方法后的()可以不添加,但是如果方法本身有一个参数,默认将原生事件event参数传递进去
  2. 如果需要同时将某个参数传递进去,同时需要event时,可以通过$event传入事件
<div id="app">
<!--  事件调用的方法没有参数表-->
  <button @click="btn1Click">按钮1</button>
  <button @click="btn1Click()">按钮1</button>

<!--  在定义事件时,写函数时省略了小括号,但是方法本身是需要一个参数的,这时,vue会默认将浏览器生成的event事件对象作为参数传入到方法-->
<!--  <button @click="btn2Click()">按钮2</button>-->
<!--  <button @click="btn2Click">按钮2</button>-->
  <button @click="btn2Click(123)">按钮2</button>

<!-- 定义时,需要event对象,又需要其他参数 -->
  <button @click="btn3Click(123,$event)">按钮3</button>

</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{

    },
    methods:{
      btn1Click(){
        console.log("btn1Click");
      },
      btn2Click(event){
        console.log("------",event);
      },
      btn3Click(abc,event){
        console.log("+++++",abc,event);
      }
    }
  })
</script>
4.3 v-on的修饰符使用
  1. .stop:调用event.stopPropagation()
  2. .prevent:调用event.preventDefault()
  3. .{keyCode|keyAlias}:只当事件是从特定键触发时才触发回调
  4. .native:监听组件根元素的原生事件
  5. .once:只触发一次回调
<div id="app">
<!--  1. .stop修饰符的使用 调用event.stopPropagation()-->
  <div @click="divClick">aaaa
    <button @click.stop="btnClick">按钮</button>
  </div>
  <br>
<!--  2. .prevent-->
  <form action="baidu">
    <input type="submit" value="提交" @click.prevent="submitClick">
  </form>
<!--  3. .{keyCode|keyAlias}  例子:监听enter按键 -->
  <input type="text" @keyup.enter="KeyUp">

<!--  4. .once-->
  <button @click.once="btn2Click">按钮2</button>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{

    },
    methods:{
      divClick(){
        console.log("divClick");
      },
      btnClick(){
        console.log("btnClick");
      },
      submitClick(){
        console.log("submitClick");
      },
      KeyUp(){
        console.log("keyUp");
      },
      btn2Click(){
        console.log("btn2Click");
      }
    }
  })
</script>

5. 条件判断v-if

5.1 v-if v-else-if v-else的使用
<div id="app">
  <h2 v-if="isShow">{{message}}</h2>
  <h1 v-else>isShow为false时,显示我</h1>
<!--不建议这样使用-->
  <p v-if="score>=90">优秀</p>
  <p v-else-if="score>=80">良好</p>
  <p v-else-if="score>=60">及格</p>
  <p v-else>不及格</p>
<!--尽量这样使用-->
  <p>{{result}}</p>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      message:'你好啊',
      isShow:true,
      score:98
    },
    computed:{
      result(){
        let showMessage='';
        if(this.score>=90){
          showMessage='优秀';
        }else if(this.score>=80){
          showMessage='良好';
        }else if(this.score>=60){
          showMessage='及格';
        }else{
          showMessage='不及格';
        }
        return showMessage;
      }
    }
  })
</script>
5.2 v-show的使用
<div id="app">
<!--  
  v-if;当条件为false时,包含v-if指令的元素,根本不会存在dom中
  v-show:当条件为false时,v-show只是给我们的元素增加了一个行内样式:display:none
-->
  <h2 v-if="isShow">{{message}}</h2>
  <h2 v-show="isShow">{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      message:'你好啊',
      isShow:true
    }
  })
</script>

注意:当需要在显示与隐藏之间切换很频繁时,使用v-show,只有一次切换时,使用v-if

6. 循环遍历v-for

6.1 v-for遍历数组
<div id="app">
<!-- 1.在遍历的过程中没有使用索引值(下标值) -->
  <ul>
    <li v-for="item in names">{{item}}</li>
  </ul>
<!-- 2.在遍历的过程中,获取索引值 -->
  <ul>
    <li v-for="(item,index) in names">
      {{index+1}}.{{item}}
    </li>
  </ul>
<!-- 3.遍历对象 -->
<!-- 不建议使用的方法 -->
  <ul>
    <li>{{info.name}}</li>
    <li>{{info.age}}</li>
    <li>{{info.height}}</li>
  </ul>
<!-- 在遍历对象的过程中,如果只是获取一个值,获取的是value -->
  <ul>
    <li v-for="item in info">{{item}}</li>
  </ul>
<!-- 获取value和key (value,key,index) -->
  <ul>
    <li v-for="(value,key,index) in info">{{value}}-{{key}}-{{index+1}}</li>
  </ul>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      names:['why','kobe','james','curry'],
      info:{
        name:'why',
        age:18,
        height:1.88
      }
    }
  })
</script>
6.2 v-for绑定和非绑定key的区别

官方推荐:在使用v-for时,给对应的元素或组件加上一个:key属性

key的作用:是为了高效的更新虚拟DOM

<div id="app">
  <ul>
    <li v-for="item in letters" :key="item">{{item}}</li>
  </ul>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      letters:['A','B','C','D','E']
    },
    methods:{
      btnClick(){
        // 1. push方法:在数组元素后面添加元素,可添加多个
        // this.letters.push('aaa','bbb');

        // 2. 通过索引值修改数组中的元素,不可响应
        // this.letters[0]='F';

        // 3. pop(): 删除数组中的最后一个元素
        // this.letters.pop();

        // 4. shift():删除数组中的第一个元素
        // this.letters.shift();

        // 5. unshift():在数组最前面添加元素,可添加多个
        // this.letters.unshift("AAA",'BBB');

        // 6. splice(start,value,item):start表示开始操作的位置,value表示需要插入(0)/删除/替换的个数,item表示添加的值
        // this.letters.splice(2,0,"F","G");   添加
        // this.letters.splice(2,3,'m','n','l','x');  替换
        // this.letters.split(2,3);   删除

        // 7.sort():
        // this.letters.sort();

        // 8.reverse():翻转数组
        // this.letters.reverse();
         
        // set(要修改的值,索引值,修改后的值)
        Vue.set(this.letters,0,'bbbb');
      }
    }
  })
</script>

7. 表单绑定v-model

7.1 v-model的使用和原理
<div id="app">
<!-- 双向绑定方法一:常用 <input type="text" v-model="message">-->
<!-- 双向绑定方法二: <input type="text" :value="message" @input="valueChage">-->
<!-- 双向绑定方法三: -->
  <input type="text" :value="message" @input="message=$event.target.value">
<!-- 绑定textarea -->
  <textarea v-model="message"></textarea>
  <h2>{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      message:'你好啊'
    },
    methods:{
      valueChage(event){
        // 使用event.target.value获取input当前最新的内容
        this.message=event.target.value;
      }
    }
  })
</script>

v-model其实是一个语法糖,它的本质是包含两个操作:

  • v-bind绑定一个value属性
  • v-on指令给当前元素绑定input事件
7.2 v-model结合radio类型使用
<div id="app">
<!--   两个radio设置同样的name属性可以保持互斥,但是绑定同样的v-model,也有同样的效果-->
  <label for="male">
    <input type="radio" id="male" value="男" v-model="sex">男
  </label>
  <label for="female">
    <input type="radio" id="female" value="女" v-model="sex">女
  </label>
  <h2>您选择的性别是: {{sex}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      sex:'男'
    }
  })
</script>
7.3 v-model结合checkbox类型使用
<div id="app">
  <!-- checkbox单选框 -->
  <label for="agree">
    <input type="checkbox" id="agree" v-model="isAgree">同意协议
  </label>
  <h2>您选择的是: {{isAgree}}</h2>
  <button :disabled="!isAgree">下一步</button><br><br><br>

  <!-- checkbox多选框 -->
  <input type="checkbox" value="篮球" v-model="hobbies">篮球
  <input type="checkbox" value="足球" v-model="hobbies">足球
  <input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球
  <input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球
  <h2>您的爱好是: {{hobbies}}</h2>

  <!-- input中的值绑定 -->
  <label v-for="item in originHobbies" :for="item">
    <input type="checkbox" :value="item" :id="item" v-model="hobbies">{{item}}
  </label>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      isAgree:false,
      hobbies:[],
      originHobbies:['篮球','足球','乒乓球','羽毛球','台球','高尔夫球']
    }
  })
</script>
7.4 v-model结合select类型使用
<div id="app">
  <!-- 1. 选择一个 -->
  <select name="abc" v-model="fruit">
    <option value="苹果">苹果</option>
    <option value="香蕉">香蕉</option>
    <option value="石榴">石榴</option>
    <option value="榴莲">榴莲</option>
  </select>
  <h2>您选择的水果是: {{fruit}}</h2>
  <!-- 2. 选择多个 -->
  <select name="abc" v-model="fruits" multiple>
    <option value="苹果">苹果</option>
    <option value="香蕉">香蕉</option>
    <option value="石榴">石榴</option>
    <option value="榴莲">榴莲</option>
  </select>
  <h2>您选择的水果是: {{fruits}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      fruit:'香蕉',
      fruits:[]
    }
  })
</script>
7.5 v-model修饰符
<div id="app">
  <!-- 1.修饰符 lazy 可以让数据失去焦点或回车时才会更新-->
  <input type="text" v-model.lazy="message">
  <h2>{{message}}</h2>

  <!-- 2.修饰符 number:可以让输入框中输入的内容转为数字类型 -->
  <input type="number" v-model.number="age">
  <h2>{{typeof age}}</h2>

  <!-- 3.修饰符 trim:去除左右两边的空格 -->
  <input type="text" v-model.trim="name">
  <h2>您输入的名字: {{name}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
  const app=new Vue({
    el:"#app",
    data:{
      message:'你好啊',
      age:0,
      name:''
    }
  })
</script>

8. 组件化开发

8.1 组件化的实现和使用步骤

Vue组件化思想:

  • 他提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用
  • 任何的应用都会被抽象成一颗组件树

组件使用的步骤:

  1. 创建组件的构造器(调用Vue.extend()方法)
  2. 注册组件(调用Vue.component()方法)
  3. 使用组件(在Vue实例的作用范围内使用组件)
  <div id="app">
  <!-- 3. 使用组件 -->
    <my-cpn></my-cpn>
  </div>
  <div id="app2">
    <cpn></cpn>
  </div>
  <script src="../js/vue.js"></script>
  <script>
    // 1. 创建组件构造器对象
    const cpnC=Vue.extend({
      template:`
        <div>
          <h2>我是标题</h2>
          <p>我是内容,呵呵呵呵</p>
          <p>我是内容,哈哈哈哈哈哈</p>
        </div>`
    });
    // 2. 注册组件(全局组件,意味着可以在多个VUE实例中使用)
    Vue.component('my-cpn',cpnC);

    const app=new Vue({
      el:"#app",
      data:{
      },
      components:{   // 局部组件
        // cpn:使用组件的标签名
        cpn:cpnC
      }
    })
  </script>
8.2 父组件和子组件
<div id="app">
  <cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
  // 1. 创建第一个组件构造器(子组件)
  const cpnC1=Vue.extend({
    template:`
      <div>
        <h2>我是标题</h2>
        <p>我是内容,哈哈哈哈哈</p>
      </div>`
  })
  // 2. 创建第二个组件构造器(父组件)
  const cpnC2=Vue.extend({
    template:`
      <div>
        <h2>我是标题2</h2>
        <p>我是内容2,哈哈哈哈哈</p>
        <cpn1></cpn1>
      </div>
    `,
    components:{  // 注册组件
      cpn1:cpnC1
    }
  })

  // root组件
  const app=new Vue({
    el:"#app",
    data:{
    },
    components:{
      cpn2:cpnC2
    }
  })
</script>
8.3 注册组件的语法糖写法
<div id="app">
  <cpn1></cpn1>
  <cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
  // 注册全局组件的语法糖
  Vue.component('cpn1',{
    template:`
      <div>
        <h2>我是标题</h2>
        <p>我是内容,哈哈哈哈哈</p>
      </div>`
  })
  const app=new Vue({
    el:"#app",
    data:{
      message:'你好啊'
    },
    // 注册局部组件的语法糖
    components:{
      'cpn2':{
        template:`
          <div>
            <h2>我是标题</h2>
            <p>我是内容,哈哈哈哈哈</p>
          </div>`
      }
    }
  })
</script>
8.4 组件模板抽离的写法
<div id="app">
  <cpn></cpn>
</div>
<!--1.模板写法一:script标签 类型必须是text/x-template -->
<script type="text/x-template" id="cpn">
  <div>
    <h2>我是标题</h2>
    <p>我是内容,哈哈哈哈哈</p>
  </div>
</script>
<!-- 2.模板写法二:template标签 -->
<template id="cpn">
  <div>
    <h2>我是标题</h2>
    <p>我是内容,哈哈哈哈哈</p>
  </div>
</template>
<script src="../js/vue.js"></script>
<script>
  // 1,注册全局组件
  Vue.component('cpn',{
    template:`#cpn`
  })

  const app=new Vue({
    el:"#app",
    data:{
    }
  })
</script>
8.5 组件data必须是函数
  1. 组件不可以直接访问Vue实例中的data
  2. 组件模块有属于自己的HTMl模块,也应该有属于自己的数据data
  3. 组件data必须是函数,这个函数返回一个对象,对象内部保存着数据
<div id="app">
  <cpn></cpn>
</div>
<script type="text/x-template" id="cpn">
  <div>
    <h2>{{title}}</h2>
    <p>我是内容,哈哈哈哈哈</p>
  </div>
</script>
<script src="../js/vue.js"></script>
<script>
  Vue.component('cpn',{
    template:`#cpn`,
    data(){
      return {
        title:'abc'
      }
    }
  })
  const app=new Vue({
    el:"#app",
    data:{

    }
  })
</script>
8.6 父子组件的通信
  1. 通过props向子组件传递数据
    • 字符串数组,数组中的字符串就是传递时的名称
    • 对象,对象可以设置传递时的类型,也可以设置默认值等
  2. 通过事件向父组件发送信息
8.6.1 父传子props
<div id="app">
  <cpn :cmovies="movies" :cmessage="message"></cpn>
</div>
<template id="cpn">
  <div>
    <p>{{cmovies}}</p>
    <h2>{{cmessage}}</h2>
  </div>
</template>
<script src="../js/vue.js"></script>
<script>
  // 父组件向子组件传递信息:props
  const cpn={
    template:`#cpn`,
    // props:['cmovies','cmessage'],
    props:{
      // 1. 类型的限制
      // cmovies:Array,
      // cmessage:String
      // 2. 提供一些默认的值
      cmessage:{
        type:String,
        default:'aaaa',
        required:true  // 当required为true时,这个属性必须传,否则会报错
      },
      // 类型是对象或者数组时,默认值必须是一个函数
      cmovies:{
        type:Array,
        // default: [],  // 2.5.3以下不会报错
        default(){
          return []
        }
      }
    },
  }
  const app=new Vue({
    el:"#app",
    data:{
      message:'你好啊',
      movies:['海王','海贼王','海尔兄弟']
    },
    components:{
      cpn
    }
  })
</script>
8.6.2 props驼峰标识

例如:childMyMessage写成 child-my-message

<div id="app">
<!-- v-bind不支持驼峰 -->
  <cpn :c-info="info" :child-my-message="message"></cpn>
</div>
<template id="cpn">
  <div>
    <h2>{{cInfo}}</h2>
    <h2>{{childMyMessage}}</h2>
  </div>
</template>
<script src="../js/vue.js"></script>
<script>
  const cpn={
    template:`#cpn`,
    props:{
      cInfo:{
        type:Object,
        default() {
          return {};
        }
      },
      childMyMessage:{
        type:String,
        default:''
      }
    }
  }
  const app=new Vue({
    el:"#app",
    data:{
      message:'你好啊',
      info:{
        name:'why',
        age:18,
        height:1.88
      }
    },
    components:{
      cpn
    }
  })
</script>
8.6.3 子传父(自定义事件)

自定义事件的流程:

  • 在子组件中,通过$emit()来触发事件
  • 在父组件中,通过v-on来监听子组件事件
<!--父组件模板-->
<div id="app">
  <cpn @item-click="cpnClick"></cpn>
</div>
<!--子组件模板-->
<template id="cpn">
  <div>
    <button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
  </div>
</template>
<script src="../js/vue.js"></script>
<script>
  // 1. 子组件
  const cpn={
    template:`#cpn`,
    data(){
      return {
        categories:[
          {id:'aaa',name:'热门推荐'},
          {id:'bbb',name:'手机数码'},
          {id:'ccc',name:'家用家电'},
          {id:'ddd',name:'电脑办公'}
        ]
      }
    },
    methods:{
      btnClick(item){
        // 将item传入父组件 发射事件
        this.$emit('item-click',item)
      }
    }
  }
  // 2.父组件
  const app=new Vue({
    el:"#app",
    data:{
      message:'你好啊'
    },
    components:{
      cpn
    },
    methods:{
      cpnClick(item){
        console.log('cpnClick',item);
      }
    }
  })
</script>
8.7 父访问子-children-refs
  1. 父组件访问子组件:使用$ c h i l d r e n 或 children或 childrenrefs

    <div id="app">
      <cpn></cpn>
      <cpn ref="aaa"></cpn>
      <button @click="btnClick">按钮</button>
    </div>
    <template id="cpn">
      <div>我是子组件</div>
    </template>
    <script src="../js/vue.js"></script>
    <script>
      const app=new Vue({
        el:"#app",
        data:{
          message:'你好啊'
        },
        methods: {
          btnClick(){
            // 1.$children
            // console.log(this.$children);
            // for(let c of this.$children){
            //   console.log(c.name);
            //   c.showMessage();
            // }
            // console.log(this.$children[0].name)
    
            // 2.$refs => 对象类型  默认是一个空的对象,ref='aaa'
            console.log(this.$refs.aaa.name);
          }
        },
        components:{
          cpn:{
            template:`#cpn`,
            data(){
              return {
                name:'我是子组件的name'
              }
            },
            methods:{
              showMessage(){
                console.log('showMessage');
              }
            }
          }
        }
      })
    </script>
    
  2. 子组件访问父组件:使用$parent

    <div id="app">
      <cpn></cpn>
    </div>
    <template id="cpn">
      <div>
        <h2>我是cpn组件</h2>
        <ccpn></ccpn>
      </div>
    </template>
    <template id="ccpn">
      <div>
        <h2>我是ccpn子组件</h2>
        <button @click="btnClick">按钮</button>
      </div>
    </template>
    <script src="../js/vue.js"></script>
    <script>
      const app=new Vue({
        el:"#app",
        data:{
          message:'你好啊'
        },
        components:{
          cpn: {
            template: `#cpn`,
            data(){
              return {
                name:'我是cpn组件的name'
              }
            },
            components:{
              ccpn:{
                template: `#ccpn`,
                methods: {
                  btnClick(){
                    // 1.访问父组件
                    console.log(this.$parent);
                    console.log(this.$parent.name);
                    // 2.访问根组件
                    console.log(this.$root);
                    console.log(this.$root.message);
                  }
                }
              }
            }
          }
        }
      })
    </script>
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值