学习vue的第二天

一、组键
1、定义组件
Vue自定义组件分为两种:全局注册和局部注册,全局组件可以在任何地方引用,局部组件只能在当前Vue实例使用。
1)全局注册
使用Vue.component(tagName, options)来定义:
1)局部注册
在Vue实例中使用components属性来定义:

注意:HTML 特性是不区分大小写的,所有在定义组件时尽量使用中划线“-”来指定组件名。
即使,使用了驼峰标示命名如:myComponent,在页面引用时仍然要使用进行引用。

定义组件

2.is属性
在table标签中直接使用自定义组件,无法正常显示。DOM解析时会解析到

标签的外部:

原因是:table/ol/ul/select 这种html标签有特殊的结构要求,不能直接使用自定义标签。他们有自己的默认嵌套规则,比如:
table> tr> [th, td];
ol/ul > li;
select > option

模板

3.模板
当模板的html结构比较复杂时,直接在template属性中定义就不现实了,效率也会很低,此时我们可以使用模板,定义模板的四种形式:
1)直接使用字符串定义
2)使用

模板
  <!--2)使用<script type="text/x-template">-->
  <script type="text/x-template" id="tpl3">
     <ul>
          <li>01</li>
          <li>02</li>
      </ul>
  </script>
  
  <!--3)使用<template>标签-->
  <template id="tpl4">
     <ul>
          <li>011</li>
          <li>022</li>
      </ul>
  </template>

3.data属性
通过data属性指定自定义组件的初始数据,要求data必须是一个函数,如果不是函数就会报错。

模板
  <div id="app">
     <!--使用组件-->
     <my-hello></my-hello>
     <my-hello></my-hello>
     <my-hello></my-hello>
  </div>

4.props属性
Props属性
组件可以嵌套使用,叫做父子组件。那么父组件经常要给子组件传递数据这叫做父子组件通信。
父子组件的关系可以总结为 props 向下传递,事件向上传递。
父组件通过 props 给子组件下发数据,子组件通过事件给父组件发送消息。

 1、在父组件中定义数据
 2、在使用组件时,绑定父组件中的数据
 3、在子组件中通过props属性声明父组件中传递过来的参数
 4、在template属性中使用父组件中的参数
props属性

5.校验
子组件在接收父组件传入数据时, 可以进行props校验,来确保数据的格式和是否必传。可以指定一下属性:

  1. type: 指定数据类型 String Number Object …注意不能使用字符串数组,只能是对象大写形式
  2. required: 指定是否必输
  3. default: 给默认值或者自定义函数返回默认值
  4. validator: 自定义函数校验

非props属性
引用子组件时,非定义的props属性,自动合并到子组件上,class和style也会自动合并。

props属性
  <div id="app">
     <!--使用组件-->
     <my-hello class="item" style="font-size: 30px;color:pink;"  ></my-hello>
  </div>

6.非props属性
子组件在接收父组件传入数据时, 可以进行 props 校验,来确保数据的格式和是否必
传。可以指定一下属性:

  1. type: 指定数据类型 String Number Object …注意不能使用字符串数组,
    只能是对象大写形式

  2. required: 指定是否必输

  3. default: 给默认值或者自定义函数返回默认值

  4. validator: 自定义函数校验

     <html>
        <head>
           <meta charset="UTF-8">
           <title>props属性</title>
           <script type="text/javascript" src="../js/vue.js" ></script>
        </head>
        <body>
           <div id="app">
              <!--使用组件-->
              <my-hello :txt1="msg" :txt2="txt" :txt3="msg2" :txt5="money"></my-hello>
           </div>
     
        </body>
        
        <script type="text/javascript">
       /*定义组件需要在实例化vue之前*/
       Vue.component("my-hello",{
          // 声明父组件传递过来的参数
          // props:["txt1","txt2"], // 数组不能做校验
          // 对象可以做校验
          props:{
             // 基础类型检测 (`null` 指允许任何类型)
             txt1:[String, Number], // 可以支持多个
             txt2:String,
             // 必传且是字符串
             txt3:{
                required:true,
                type:String
             },
             // 数值且有默认值
             txt4:{
                type:Number,
                default: 100
             },
             // 自定义验证函数
             txt5:{
                validator:function(value){
                   return value > 10;
                }
             }
          },
          template:"<div>{{txt1}}:{{txt2}}---{{txt3}}---{{txt4}}----{{txt5}}</div>"
       });
       
       
       new Vue({
          el:"#app",
          data:{
             msg:"来自系统的消息",
             txt:"Hello Vue!",
             msg2:"Admin",
             num:10,
             money:19
          }
       });
       
    </script>
    

7.自定义事件
父组件给子组件传值使用props属性, 那么需要子组件更新父组件时,要使用自定义事件 o n 和 on和 onemit:
KaTeX parse error: Unexpected character: '' at position 48: …)或者-(a-b-c) ̲emit主动触发: e m i t ( 事 件 名 , 传 入 参 数 ) 主 动 挂 载 自 定 义 事 件 不 仅 可 以 绑 定 在 子 组 件 , 也 可 以 直 接 挂 载 到 父 组 件 , 使 用 emit(事件名,传入参数) 主动挂载 自定义事件不仅可以绑定在子组件,也可以直接挂载到父组件,使用 emit(,)使on绑定和$emit触发。

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>自定义事件</title>
      <script type="text/javascript" src="../js/vue.js" ></script>
   </head>
   <body>    
      <div id="app">
         <my-hello v-on:update-count="changecount()"></my-hello>
         {{count}}
      </div>
      
      
   </body>
   
   <script type="text/javascript">
      
      Vue.component("my-hello",{
         template:"<button v-on:click='update'>子组件Child</button>",
         methods:{
            update:function(){
               console.log("点击...");
               this.$emit("update-count","自定义事件");
            }
         }
      });
      
      
      var app = new Vue({
         el:"#app",
         data:{
            count:0
         },
         methods:{
            changecount:function(){
               this.count++;
            }
         }
      });
      // 主动挂载自定义事件
      app.$on("update-count",function(value){
         console.log(value);
         this.count++;
      });
      // 触发自定义事件
      app.$emit("update-count","这是自定义事件");
      
   </script>
</html>

二、插槽分发
1.slot插槽
1)子组件插槽

<template id="child-template"> 
<div> 
<div>我是子组件</div> 
<div>{{msg}}</div> 
<slot>我是默认内容,父组件不传入时我显示</slot> 
</div> 
</template> 
Vue.component('child', { 
template:'#child-template', 
props:['msg'] 
}); 

2)父组件插槽

<div id="app"> 
<child :msg="msgText"> 
<h4>父组件模板</h4> 
<h5>模板混入....</h5> 
</child> 
</div> 
<template id="child-template"> 
<div> 
<div>我是子组件</div> 
<div>{{msg}}</div> 
<slot>我是默认内容,父组件不传入时我显示</slot> 
</div> 
</template>

2.具名插槽
具名插槽slot, 就是给插槽起个名字。
在子组件定时可以定定义多个插槽,同时通过name属性指定一个名字,如:,父组件引用时使用< slot=‘header’>进行插槽选择。

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>slot插槽</title>
      <script type="text/javascript" src="../js/vue.js" ></script>
   </head>
   <body>
      <div id="app">
         <!--<my-hello></my-hello>-->
         <my-hello>
            <h3 slot="header">你好</h3>
            <p slot="footer">这是p元素</p>
         </my-hello>
      </div>
  
  <!--使用template标签-->
  <template id="tpl1">
     <div>
        <slot name="header">如果没有传递数据,默认显示这段文本</slot>
        <div>--------------------</div>
        <!--插槽,占位-->
        <slot name="footer">如果没有传递数据,默认显示这段文本</slot>
     </div>
  </template>
2.插槽作用域 作用域插槽slot-scope, 父组件通过插槽混入父组件的内容, 子组件也可以通过slot作用域向插槽slot内部传入数据,使用方式:, 父组件通过进行引用。 插槽作用域

你好----{{props.msg}}----{{props.txt}}

      <!--使用template标签-->
      <template id="tpl1">
         <div>
            <div>--------------------</div>
            <!--插槽,占位-->
            <slot msg="你好啊" txt="Hello">如果没有传递数据,默认显示这段文本</slot>
         </div>
      </template>
      
   </body>
   
   <script type="text/javascript">
      
      // 自定义组件
      Vue.component("my-hello",{
         template:"#tpl1",
      });
      var app = new Vue({
         el:"#app"       
      });
      
   </script>
</html>

三、动态组件
使用标签的is属性,动态绑定多个组件到一个挂载点,通过改变is绑定值,切换组件。
1.使用方式

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>动态组件</title>
      <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
   </head>
   <body>   
      <div id="app">
         <!--3、指定导航-->
         / <a href='#' @click.prevent="page='index'">首页</a>
         / <a href='#' @click.prevent="page='news'">新闻</a>
         / <a href='#' @click.prevent="page='login'">登陆</a>
         
         <!--2、使用component引用-->
         <component :is="page"> </component>
      </div>
   </body>
   
   <script type="text/javascript">
      // 1、定义组件
      Vue.component('index', {
          template:'<h5>首页</h5>'
      });
      Vue.component('news', {
          template:'<h5>新闻页</h5>'
      });
      Vue.component('login', {
          template:'<h5>登陆页</h5>'
      });
      
      new Vue({
         el:"#app",
         data:{
               page:'index'
           }
      });
   </script>
</html>

2.keep-alive
如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。为此可以添加一个 keep-alive 指令。

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>动态组件</title>
      <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
   </head>
   <body>
      <div id="app">
         <!--3、指定导航-->
         / <a href='#' @click.prevent="page='index'">首页</a>
         / <a href='#' @click.prevent="page='news'">新闻</a>
         / <a href='#' @click.prevent="page='login'">登陆</a>
         
         <!--2、使用component引用-->
         <keep-alive>
              <component :is="page"></component>
          </keep-alive>
      </div>
   </body>
   
   <script type="text/javascript">
      // 1、定义组件
      Vue.component('index', {
          template:'<h5>首页</h5>',
          // 当组件挂载时,触发(钩子函数)
          mounted: function () {
              console.log('挂载...首页');
          }
      });
      Vue.component('news', {
          template:'<h5>新闻页</h5>',
          mounted: function () {
              console.log('挂载...新闻页');
          }
      });
      Vue.component('login', {
          template:'<h5>登陆页</h5>',
          mounted: function () {
              console.log('挂载...登陆页');
          }
      });
      
      new Vue({
         el:"#app",
         data:{
               page:'index'
           }
      });
   </script>
</html>

3.refs属性
使用ref 给每个组件起一个固定的名字,方便后续直接引用操作,在父组件中使用$refs访问子组件。

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>动态组件</title>
      <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
   </head>
   <body>      
      <div id="app">
         <index ref="ind"></index>
      </div>
   </body>
   
   <script type="text/javascript">
      // 1、定义组件
      Vue.component('index', {
          template:'<div>{{count}}</div>',
             data:function(){
                return {count:0};
             }
      }); 
      
      var app = new Vue({
         el:"#app",
      });
      
      // 通过refs属性得到指定的自定义组件,修改对应的组件中的值
      app.$refs.ind.count=10;
   </script>
</html>

四、数据处理
1.watch属性
在 Vue 组件中,使用 watch 属性来监听数据的变化,同时可以指定监听那个属性。

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>watch属性</title>
      <script type="text/javascript" src="../js/vue.js" ></script>
   </head>
   <body>
      <div id="app">
         <p>
              firstName: 
              <input type="text" :value="firstName" @input="changeFirstName($event)">
          </p>
          <p>
              lastName: 
              <input type="text" :value="lastName" @input="changeLastName($event)" >
          </p>
          <h4>{{fullName}}</h4>
      </div>
   </body>
   <script type="text/javascript">
      var app = new Vue({
         el:"#app",
         data:{
            firstName:"Hello",
            lastName:"Kitty",
            fullName:"Hello Kitty"
         },
         methods:{
            changeFirstName:function(e){
               console.log(e.target.value);
               this.firstName = e.target.value;
            },
            changeLastName:function(e){
               this.lastName = e.target.value;
            }
         },
         watch:{
            firstName:function(newValue,oldValue){
               this.fullName = newValue + " " + this.lastName;
            },
            lastName:function(newValue,oldValue){
               this.fullName = this.firstName + " " + newValue;
            }
         }
         
      });
   </script>
</html>

2. s w t c h 除 了 在 组 件 内 部 使 用 w a t c h 也 可 以 使 用 内 部 命 令 swtch 除了在组件内部使用 watch 也可以使用内部命令 swtch使watch使watch 进行属性监听。
$watch第一个参数是需要监听的属性,第二个是回调函数用法和watch一样。需要取消监听只需拿到监听对象的引用,这个引用是返回一个函数对象,执行该对象就可以取消监听。
同时监听多个属性,可以不指定属性:

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>watch属性</title>
      <script type="text/javascript" src="../js/vue.js" ></script>
   </head>
   <body>
      <div id="app">
         {{firstName}} {{lastName}}
      </div>
   </body>
   <script type="text/javascript">
      var app = new Vue({
         el:"#app",
         data:{
            firstName:"Hello",
            lastName:"Kitty"
         }
      });
      // 监听指定属性
      /*app.$watch("firstName",function(newVal,oldVal){
         console.log(newVal,oldVal);
      });*/
      
      // 监听所有属性
      app.$watch(function(){
           return this.firstName + " " + this.lastName;
       },function(newVal,oldVal){
         console.log(newVal,oldVal);
      });
   </script>
</html>

3.Computed属性
computed计算属性用于定义比较复杂的属性计算
computed和methods区别:
计算属性使用computed定义, 方法使用methods定义
计算属性使用时不加括号执行符
计算属性是基于它们的依赖进行缓存的,计算属性只有在它的相关依赖发生改变时才会重新求值。否则返回之前计算好的值,性能更高!

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>computed属性</title>
      <script type="text/javascript" src="../js/vue.js" ></script>
   </head>
   <body>
      <div id="app">
         <p>
              firstName: 
              <input type="text" v-model="firstName">
          </p>
          <p>
              lastName: 
              <input type="text" v-model="lastName"  >
          </p>
          <h4>{{fullName}}</h4>
      </div>
   </body>
   <script type="text/javascript">
      var app = new Vue({
         el:"#app",
         data:{
            firstName:"Hello",
            lastName:"Kitty"
         },
         computed:{
            fullName:function(){
               return this.firstName + " " +this.lastName;
            }
         }
      });
      
   </script>
</html>

4.getter和setter
在 computed 中,同样可以指定 setter 进行数据更新。

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>getter和setter</title>
      <script type="text/javascript" src="../js/vue.js" ></script>
   </head>
   <body>
      <div id="app">
         <p>
              fullName: 
              <input type="text" v-model="fullName">
          </p>
          <h4>firstName:{{firstName}}</h4>
          <h4>lastName:{{lastName}}</h4>
      </div>
   </body>
   <script type="text/javascript">
      var app = new Vue({
         el:"#app",
         data:{
            firstName:"Hello",
            lastName:"Kitty"
         },
         computed:{
            fullName:{
               // getter 得到fullName的值
               get:function(){
                  return this.firstName + " " + this.lastName;
               },
               set:function(val){
                  var arr = val.split(" ");
                  this.firstName = arr[0];
                  this.lastName = arr[1];
               }
            }
         }
      });
      
   </script>
</html>

五、生命周期

每个 Vue 实例在被创建之前都要经过一系列的初始化过程。例如需要设置数据监听、
编译模板、挂载实例到 DOM、在数据变化时更新 DOM 等。同时在这个过程中也会运行一
些叫做生命周期钩子的函数,给予用户机会在一些特定的场景下添加他们自己的代码。
比如 created 钩子可以用来在一个实例被创建之后执行代码;
常用的生命周期钩子函数有:

  1. created: 实例创建完成后被立即调用

  2. mounted: 实例挂载完成后被立即调用

  3. beforeUpdate: 实例需要渲染之前调用

  4. updated: 实例更新后调用

  5. destroyed: Vue 实例销毁后调用

    getter和setter

六、自定义指令
1.自定义指令
全局指令:v-focus
局部指令:使用directive定义,第一个参数为指令名,使用时加上v-前缀才能生效。
inserted属性指当绑定元素插入到DOM时调用。

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>自定义指令</title>
      <script type="text/javascript" src="../js/vue.js" ></script>
   </head>
   <body>
      <div id="root">
         <input type="text" v-focus />
         <input type="text" v-focus2 />
      </div>
   </body>

   <script>
   
   //自定义全局指令v-focus
   Vue.directive('focus',{
       //当绑定元素插入到DOM调用
       inserted: function (el) {
           //元素获取焦点
           el.focus();
       }
   });
      
    var vm = new Vue({
        el:'#root',
       directives:{
           focus2:{
               inserted: function (el) {
                   //元素获取焦点
                   el.focus();
               }
           }
       }
    });
   
</script>
</html>

2.钩子函数
钩子函数的参数有三个:
1)el:当前指令绑定元素
2)binding:当前指令绑定的所有信息对象,有以下属性:
name:指令名,不包括 v- 前缀。
value:指令的绑定值,例如:v-my-directive=“1 + 1”, value 的值是 2。
oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression:绑定值的字符串形式。例如 v-my-directive=“1 + 1” ,expression 的值是 “1 + 1”。
arg:传给指令的参数。例如 v-my-directive:foo,arg 的值是 “foo”。
modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }。
3)vnode:Vue 编译生成的虚拟节点
4)oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated
钩子中可用。

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>自定义指令</title>
      <script type="text/javascript" src="../js/vue.js" ></script>
   </head>
   <body>
      <div id="root">
         <input type="text"  v-demo:str.a.ab="1+1"/>
      </div>
   </body>
   <script>
   
   //自定义全局指令v-focus
    Vue.directive('demo',{
        bind: function (el,binding) {
            console.log(el);
            console.log(binding);
        }
    });
      
    var vm = new Vue({
        el:'#root'
    });
   
</script>
</html>

3.图片懒加载
在图片未完成加载前,用随机的背景色占位,图片加载
完成后才直接渲染出来,用自定义指令可以非常方便的实现这个功能。

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>自定义指令</title>
      <script type="text/javascript" src="../js/vue.js" ></script>
      <style>
          .item, .item img{
              width: 200px;
              height: 120px;
              float: left;
          }
      </style>
   </head>
   <body>
      <div id="root">
         <div class="item" v-for="img in imgs" v-img="img.url"></div>
      </div>
   </body>
   
   
   <script>
      
      //定义全局自定义指令v-img
      Vue.directive('img',{
          bind: function (el,binding) {
              //生成随机颜色
              var color = parseInt(Math.random()*0xFFFFFF).toString(16);
              //设置当前元素的背景,提前进行占位等待图片加载
              el.style.background = '#'+color;
              //setTimeout模拟图片加载的延时情况
              setTimeout(function () {
                  //创建图片对象
                  var img = new Image();
                  //通过binding对象获取真实的图片url
                  img.src = binding.value;
                  //将图片元素插入DOM结构
                  el.appendChild(img);
                  //随机延时
              },Math.random()*3000+500);
          }
      });

       var vm = new Vue({
           el:'#root',
           data:{
              //定义模拟数据
              imgs:[
                  {url:'../img/01.jpg'},
                  {url:'../img/02.jpg'},
                  {url:'../img/03.jpg'},
                  {url:'../img/04.jpg'}
              ]
          }
       });  
</script>
</html>

七、过滤器

八、Vue允许自定义过滤器,可被用作一些常见的文本格式化。
过滤器可以用在两个地方:mustache 插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。
过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符指示:

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8">
      <title>过滤器</title>
      <script src="../js/vue.js" type="text/javascript" charset="utf-8"></script>
   </head>
   <body>
      <div id="app">
         
         {{msg | uppercase | length}}
         <br />
         {{msg | test("<--","--<")}}
         
      </div>
   </body>
   <script type="text/javascript">
      
      // 全局过滤器
      Vue.filter("uppercase",function(val){
         return val.toUpperCase();
      });
      
      
      var app = new Vue({
         el:"#app",
         data:{
            msg:"hello"
         },
         // 定义局部过滤器
         filters:{
            length:function(val){
               return val + " " + val.length;
            },
            test:function(val,a,b){
               return a + val + b;
            }
         }
      });
      
   </script>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值