Vue语法

目录

1 声明式渲染功能

api
vue只要管控了元素,用{{}}就能得到所需要的值

<div id="app">
        //数据绑定{{}} 获取那么值显示
        <h1>{{name}}</h1>
    </div>

    <script src="./node_modules/vue/dist/vue.js"></script>

    <script>
    //声明式渲染功能
        var vm=new Vue({
            //el: 管控
            el:"#app",
            //data里放对象
            data:{
                name:"张三"
            },
        });
    </script>

页面可修改显示的值
在这里插入图片描述

2 常用内置指令

  1. v:text : 更新元素的 textContent
  2. v-html : 更新元素的 innerHTML
  3. v-if : 如果为 true, 当前标签才会输出到页面
  4. v-else: 如果为 false, 当前标签才会输出到页面
  5. v-show : 通过控制 display 样式来控制显示/隐藏
  6. v-for : 遍历数组/对象
  7. v-on : 绑定事件监听, 一般简写为@
  8. v-bind : 强制绑定解析表达式, 可以省略 v-bind
  9. v-model : 双向数据绑定
  10. ref : 指定唯一标识, vue 对象通过$els 属性访问这个元素对象
  11. v-cloak : 防止闪现, 与 css 配合: [v-cloak] { display: none }

2.1.v-on 绑定事件

v-on可以写成@

<div id="app">
  <input type="text" v-model="num">
  
  <!--v-on:click 简写为@click -->
   <button v-on:click="num ++">点赞</button>
   <button v-on:click="quxiao">取消点赞</button>
   
        //数据绑定{{}} 获取那么值显示
        <h1>{{name}}</h1>
    </div>

    <script src="./node_modules/vue/dist/vue.js"></script>

    <script>
    //声明式渲染功能
        var vm=new Vue({
            //el: 管控
            el:"#app", //绑定元素
            //data里放对象
            data:{ //封装数据
                name:"张三"
            },
            methods: { //封装方法
                quxiao(){
                    this.num--;
                }
            },
        });
    </script>

在这里插入图片描述

v-on:click.prevent="dianji"或者 @click.prevent="dianji"

修饰符:
.stop - 调用 event.stopPropagation()。阻止事件冒泡到父类
.prevent - 调用 event.preventDefault()。阻止默认事件发生
.capture - 添加事件侦听器时使用 capture 模式。 使用事件捕获模式
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
.native - 监听组件根元素的原生事件。
.once - 只触发一次回调。
.left - (2.2.0) 只当点击鼠标左键时触发。
.right - (2.2.0) 只当点击鼠标右键时触发。
.middle - (2.2.0) 只当点击鼠标中键时触发。
.passive - (2.3.0) 以 { passive: true } 模式添加侦听器

2.2 v-text 不转义

<div id="app">
       <span v-text="msg"></span>
    </div>

    <script src="./node_modules/vue/dist/vue.js"></script>

    <script>
      new Vue({
          el:"#app",
          data:{
            msg:"<h1>hello</h1>"
          },
      })

        
    </script>

在这里插入图片描述

2.3 v-html 转义

<div id="app">
       <span v-html="msg"></span>
    </div>

    <script src="./node_modules/vue/dist/vue.js"></script>

    <script>
      new Vue({
          el:"#app",
          data:{
            msg:'<a href="http://www.baidu.com">百度一下</a>'
          },
      })
    </script>

在这里插入图片描述

2.4 v-bind 给html绑定属性

v-bind 可以写成 :
class和style绑定,要更改为对象,class属性为true则显示

 <div id="app">
      <a v-bind:href="link">点击</a>

 		<!--class style-->
      <span v-bind:class="{active:iserror}"
       v-bind:style="{color: color1,'font-size': size}">ok</span>
    </div>

    <script src="./node_modules/vue/dist/vue.js"></script>

    <script>
      var vm=new Vue({
          el:"#app",
       	  data:{
            link:"http://www.baidu.com",
            iserror:true,
            color1:'red',
            size:'80px'

          },
      })
      })

        
    </script>

跳转百度
在这里插入图片描述

2.5 v-model 双向绑定

v-model代表输入框与vue里num绑定,模型变化,引起视图变化

<div id="app">
  <input type="text" v-model="num">
        //数据绑定{{}} 获取那么值显示
        <h1>{{name}}</h1>
    </div>

    <script src="./node_modules/vue/dist/vue.js"></script>

    <script>
    //声明式渲染功能
        var vm=new Vue({
            //el: 管控
            el:"#app",
            //data里放对象
            data:{
                name:"张三"
            },
        });
    </script>

在这里插入图片描述

<div id="app">
        <input type="checkbox" v-model="language" value="java">java
        <br>
        <input type="checkbox" v-model="language" value="js">js
        <br>
        <input type="checkbox" v-model="language" value="python"> python
        <br>
        选中了 {{language.join(",")}}
    </div>

    <script src="./node_modules/vue/dist/vue.js"></script>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                language:[]
            },
        })


    </script>

在这里插入图片描述

2.6 v-for

 <div id="demo">
    <h2>测试: v-for 遍历数组</h2>
    <ul>
      <li v-for="(item,index) in items" :key="item.message">
        {{parentMessage}}-----{{index}}----{{item.message}}
        <button @click="deleteI(index)">删除</button>
        <button @click="updateI(index,{message:'up'})">更新</button>
        <button @click="addI(index,{message:'add'})">插入</button>
      </li>
    </ul>


    <h2>测试: v-for 遍历对象</h2>
    <ul>
      <li v-for="(value,name,index) in object">
        {{parentMessage}}----{{index}}---- {{name}}----{{value}}
      </li>
    </ul>

    <h2>测试: v-for 遍历对象</h2>
    <ul>
      <li v-for="(value,name,index) in items[0]">
        {{parentMessage}}----{{index}}---- {{name}}----{{value}}
      </li>
    </ul>


  </div>

  <script type="text/javascript" src="../js/vue.js"></script>
  <script type="text/javascript">
    new Vue({
      el: '#demo',
      data: {
        parentMessage: 'Parent',
        items: [{
            message: 'Foo'
          },
          {
            message: 'Bar'
          }
        ],
        object: {
          title: 'How to do lists in Vue',
          author: 'Jane Doe',
          publishedAt: '2016-04-10'
        }

      },
      methods: {
        deleteI(index) {
          this.items.splice(index, 1)
        },
        updateI(index, newi) {
          this.items.splice(index, 1, newi);
        },
        addI(index, newi) {
          this.items.splice(index, 0, newi);
        }
      },

    })
  </script>

在这里插入图片描述
在这里插入图片描述

2.6.1 数组循环

<ul>
     <li v-for="(item,index) in items" :key="item.message">
       {{parentMessage}}-----{{index}}----{{item.message}}
       <button @click="deleteI(index)">删除</button>
       <button @click="updateI(index,{message:'up'})">更新</button>
       <button @click="addI(index,{message:'add'})">插入</button>
     </li>
   </ul>
   

key:来区分不同数据,提高vue渲染效率,必须是唯一值
其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名
index:下标

2.6.2 对象

<h2>测试: v-for 遍历对象</h2>
   <ul>
     <li v-for="(value,name,index) in object">
       {{parentMessage}}----{{index}}---- {{name}}----{{value}}
     </li>
   </ul>

   <h2>测试: v-for 遍历对象</h2>
   <ul>
     <li v-for="(value,name,index) in items[0]">
       {{parentMessage}}----{{index}}---- {{name}}----{{value}}
     </li>
   </ul>

key:来区分不同数据,提高vue渲染效率,必须是唯一值
value:值
name:key
index:下标

2.6.3 显示过滤/排序后的结果

<div id="demo">
    <input type="text" v-model="searchName">
    <ul>
      <li v-for="(p, index) in filterPersons" :key="index">
        {{index}}---{{p.name}}---{{p.age}}
      </li>
    </ul>
    <div>
      <button @click="setOrderType(2)">年龄升序</button>
      <button @click="setOrderType(1)">年龄降序</button>
      <button @click="setOrderType(0)">原本顺序</button>
    </div>
  </div>

  <script type="text/javascript" src="../js/vue.js"></script>
  <script type="text/javascript">
    new Vue({
      el: '#demo',
      data: {
        searchName:'',
        orderType:0,
        persons: [{
            name: 'Tom',
            age: 18
          },
          {
            name: 'Jack',
            age: 17
          },
          {
            name: 'Bob',
            age: 19
          },
          {
            name: 'Mary',
            age: 16
          }
        ]
      },
      computed: {
        filterPersons() {
          //取出相关数据
          const {persons,searchName,orderType} = this

          let arr;
          //filter过滤数据
         // arr = persons.filter(p => p.name.indexOf(searchName)!==-1)
          arr=persons.filter(function(p){
              return p.name.indexOf(searchName)!=-1
          })

          //排序
          if(orderType !=0){
            arr.sort(function(p1,p2){
              if(orderType ==1){
                return p1.age-p2.age
              }
              if(orderType ==2){
                return p2.age-p1.age
              }
            })
           // arr.sort((p1,p2) => p1.age-p2.age)
          }
         
          return arr;
        }
      },
      methods: {
        setOrderType(orderType){
          this.orderType=orderType
        }
      },

    })
  </script>

在这里插入图片描述
在这里插入图片描述

2.7 v-if和v-else-if和v-else 条件渲染

<div id="app">
        <li v-for="(user,index) in users">
            <span v-for="(v,k,index) in user">{{k}}--{{v}}--{{index}};</span>
            <span v-if="user.gender=='男'">是男的</span>
            <span v-else-if="user.gender=='女'">是女的</span>
        </li>
    </div>

    <script src="./node_modules/vue/dist/vue.js"></script>

    <script>
        var vm = new Vue({
            el: "#app",
            data: {
                users:[{name:"名字1",age:1,gender:"男"},
                    {name:"名字2",age:2,gender:"女"}
                ]
            },
        })
    </script>

在这里插入图片描述

2.7.1 v-if 与 v-show的区别

<div id="demo">
  <p v-if="ok">表白成功</p>
  <p v-else>表白失败</p>

  <hr>
  <p v-show="ok">求婚成功</p>
  <p v-show="!ok">求婚失败</p>

 <button @click='ok=!ok'>按钮</button>
</div>

<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
  new Vue({
    el: '#demo',
    data: {
      ok:false
    },
  })
</script>

在这里插入图片描述

2.8 ref : 指定唯一标识, vue 对象通过$els 属性访问这个元素对象

<body>

<div id="example">
  <p ref="msg">abcd</p>
  <button @click="hint">提示</button>
</div>

<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
  new Vue({
    el: '#example',
    data: {
    },
    methods: {
      hint () {
        alert(this.$refs.msg.innerHTML)
      }
    }
  })
</script>

在这里插入图片描述

2.9 v-cloak 防止闪现

<body>

<div id="example">
  <p v-clock="msg">{{msg}}</p>
  <button @click="hint">提示</button>
</div>

<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
alert('---')
  new Vue({
    el: '#example',
    data: {
    	msg: 'aaa'
    },
    methods: {
      hint () {
        alert(this.$refs.msg.innerHTML)
      }
    }
  })
</script>

在第一次执行时
在这里插入图片描述
添加样式后防止闪现

<style>
    [v-clock]{
      display: none;
    }
  </style>

3 注册自定义指令(全局指令和局部指令)

  1. 注册全局指令
    Vue.directive(‘my-directive’, function(el, binding){
    el.innerHTML = binding.value.toupperCase()
    })
  2. 注册局部指令
    directives : {
    ‘my-directive’ : {
    bind (el, binding) {
    el.innerHTML = binding.value.toupperCase()
    }
    }
    }
  3. 使用指令
    v-my-directive=‘xxx’
<!--
需求: 自定义2个指令
  1. 功能类型于v-text, 但转换为全大写
  2. 功能类型于v-text, 但转换为全小写
-->
<div id="text1">
  <p v-upper-text="msg"></p>
  <p v-lower-text="msg"></p>
</div>

<div id="text2">
  <p v-upper-text="msg"></p>
  <p v-lower-text="msg"></p>
</div>

<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
  // 注册一个全局指令
  // el: 指令所在的标签对象
  // binding: 包含指令相关数据的容器对象
  Vue.directive('upper-text',function(el,binding){
    //转大写toUpperCase()
      el.textContent=binding.value.toUpperCase()
  })
  new Vue({
    el: '#text1',
    data: {
      msg: 'abSSDSdsf'
    },
    //局部自定义指令
    directives:{
      'lower-text':function(el,binding){
        //转小写toLowerCase()
        el.textContent=binding.value.toLowerCase()
        
      }
    }
  })

  new Vue({
    el: '#text2',
    data: {
      msg: 'SDAsdsS'
    }
  })
 
</script>

在这里插入图片描述

4 自定义插件

api
js页面编写自定义插件:
javascript中: (function(){})()是匿名函数du,主要利用函数内的变量作用域,避免产生全局变量,影响整体页面环境,增加代码的兼容性
(function(){})是一个标准的函数定义,但是没有复制给任何变量。所以是没有名字的函数,叫匿名函数。没有名字就无法像普通函数那样随时随地调用了,所以在他定义完成后就马上调用他,后面的括号()是运行这个函数的意思

(function(){
    const MyPlugin = {}
    MyPlugin.install = function (Vue, options) {
        // 1. 添加全局方法或 property属性
        Vue.myGlobalMethod = function () {
          // 逻辑...
          console.log('Vue函数对象的myGlobalMethod()')
     
        }
      
        // 2. 添加全局资源
        Vue.directive('my-directive',function(el,binding){
            el.textContent=binding.value.toUpperCase()
        })
          
        // 4. 添加实例方法
        <!--添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现-->
        Vue.prototype.$myMethod = function () {
          // 逻辑...
          console.log('添加方法myMethod()')
        }
      }
      window.MyPlugin=MyPlugin
})()

页面

<body>
  <div id="test">
    <p v-my-directive='msg'></p>
  </div>
  
  <!--自定义js插件要在vue下面-->
  <script type="text/javascript" src="../js/vue.js"></script>
  <script type="text/javascript" src="own.js"></script>
  <script type="text/javascript">
  
	<!--全局方法 Vue.use() 使用插件。它需要在你调用 new Vue() 启动应用之前完成-->
    Vue.use(MyPlugin)

    const vm = new Vue({
      el: '#test',
      data: {
        msg: 'have'
      },
    })
    Vue.myGlobalMethod();
    vm.$myMethod();
  </script>

5 计算属性(computed)和侦听器(watch)

<div id="app">
        <li>西游记  价格:{{xyjprice}} 数量:<input type="number" v-model="xyjnum"></li>
        <li> 水浒传  价格:{{shzprice}} 数量:<input type="number" v-model="shznum"></li>
        <li> 总价格 :{{total}}</li>
        {{msg}}
    </div>

    <script src="./node_modules/vue/dist/vue.js"></script>

    <script>
       let vm= new Vue({
            el:"#app",
            data:{
                xyjprice:99,
                shzprice:88,
                xyjnum:1,
                shznum:1,
                msg:""
            },
            //计算属性
            computed: {
                total(){
                    return  this.xyjprice*this.xyjnum+this.shzprice*this.shznum;
                }
              
            },
            //侦听器
            watch: {
                xyjnum(newnum,oldnum){
                    if(newnum>=3){
                        this.msg="超出限值";
                        this.xyjnum=3;
                    }
                   else if(newnum<=0){
                        this.msg="不能小于0";
                        this.xyjnum=0;
                   }
                    else{
                        this.msg="";
                    }
                }
            },
        })

    </script>

在这里插入图片描述
例:
在这里插入图片描述
在这里插入图片描述

5.1计算属性(computed) set和get用法

计算属性:
通过getter/setter实现对属性数据的显示和监听,计算属性存在缓存,多次读取只执行一次getter
在这里插入图片描述

在这里插入图片描述

6 过滤器(全局)

<div id="app">
       <li v-for="user in users":key="user.name">

            {{user.name}}-{{user.age}}- {{user.gender | genderFilter}}--
            {{user.gender | gFilter}}

       </li>
    </div>

    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        //全局过滤器
        Vue.filter("gFilter",function(val){
            if(val==1){
                return "男(全局)";
            }
            else{
                return "女(全局)";
            }
        })

        var vm = new Vue({
            el: "#app",
            data: {
                users:[{name:"名字1",age:1,gender:1},
                    {name:"名字2",age:2,gender:2}
                ]
            },
            //局部过滤器
            filters:{
                genderFilter(val){
                    if(val==1){
                        return "男";
                    }
                    else{
                        return "女";
                    }
                }
            }
        })
    </script>

在这里插入图片描述

7 组件(全局和局部)

组件是可复用的 Vue 实例,在注册组件时一定要通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用

<div id="app">
        
        <click></click>
        <click></click>
        <click></click>
        <one-component></one-component>
    </div>

    <script src="./node_modules/vue/dist/vue.js"></script>

    <script>

        //全局
        Vue.component("click",{
            template : `<button v-on:click="count++">全局点击{{count}}下</button>`,
           data() {
               return {
                   count : 1
               }
           },
        });

        //局部
        const oneComponent={
            template : `<button v-on:click="count++">局部点击{{count}}下</button>`,
           data() {
               return {
                   count : 1
               }
           },
        }

        let vm= new Vue({
            el:"#app",
            data:{
            },
          components:{
           "oneComponent":oneComponent
          },
        })
    </script>

在这里插入图片描述

8 事件处理(绑定监听、事件修饰符)

<div id="example">

  <h2>1. 绑定监听</h2>
  <button @click="test1">test1</button>
  <button @click="test2('abc')">test2</button>
  <button @click="test3('abcd', $event)">test3</button>

  <h2>2. 事件修饰符</h2>
  <a href="http://www.baidu.com" @click.prevent="test4">百度一下</a>
  <div style="width: 200px;height: 200px;background: red" @click="test5">
    <div style="width: 100px;height: 100px;background: blue" @click.stop="test6"></div>
  </div>

  <h2>3. 按键修饰符</h2>
  <input type="text" @keyup.13="test7">
  <input type="text" @keyup.enter="test7">

</div>

<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
  new Vue({
    el: '#example',
    data: {

    },
    methods: {
      test1(event) {
        alert(event.target.innerHTML)
      },
      test2 (msg) {
        alert(msg)
      },
      test3 (msg, event) {
        alert(msg+'---'+event.target.textContent)
      },

      test4 () {
        alert('点击了链接')
      },

      test5 () {
        alert('out')
      },
      test6 () {
        alert('inner')
      },

      test7 (event) {
        console.log(event.keyCode)
        alert(event.target.value)
      }
    }
  })
</script>

8.1 绑定监听

v-on:xxx=“fun”
@xxx=“fun”
@xxx=“fun(参数)”
默认事件形参: event
隐含属性对象: $event

 <button @click="test3('abcd', $event)">test3</button>
 <script type="text/javascript">
new Vue({
  el: '#example',
  data: {
  },
  methods: {
    test3 (msg, event) {
      alert(msg+'---'+event.target.textContent)
    },
  }
})
</script>

在这里插入图片描述

8.2 事件修饰符

.prevent : 阻止事件的默认行为 event.preventDefault()
.stop : 停止事件冒泡 event.stopPropagation()

未添加时:
在这里插入图片描述

添加修饰符以后:

在这里插入图片描述

9 事件 $on $once $off $emit

参考 13.2.2 自定义事件 实例

  1. vm. o n ( e v e n t , c a l l b a c k ) 监 听 当 前 实 例 上 的 自 定 义 事 件 。 事 件 可 以 由 v m . on( event, callback ) 监听当前实例上的自定义事件。事件可以由 vm. on(event,callback)vm.emit 触发。回调函数会接收所有传入事件触发函数的额外参数。
vm.$on('test', function (msg) {
  console.log(msg)
})
vm.$emit('test', 'hi')
// => "hi"
  1. vm.$once( event, callback )
    用法:
    监听一个自定义事件,但是只触发一次。一旦触发之后,监听器就会被移除。
  2. vm.$off( [event, callback] )
    用法:
    移除自定义事件监听器。
    如果没有提供参数,则移除所有的事件监听器;
    如果只提供了事件,则移除该事件所有的监听器;
    如果同时提供了事件与回调,则只移除这个回调的监听器。
  3. vm.$emit( eventName, […args] )
    触发当前实例上的事件。附加参数都会传给监听器回调。

10 vue对象的生命周期

在这里插入图片描述

钩子函数触发的行为在此阶段可以做的事情
beforeCreate(创建前)vue实例的挂载元素$el和数据对象data都为undefined,还未初始化加loading事件
created(创建后)vue实例的数据对象data有了,$el还没有结束loading、请求数据为mounted渲染做准备
beforeMount(载入前)vue实例的$el和data都初始化了,但还是虚拟的dom节点,具体的data.filter还未替换。
mounted(载入后)vue实例挂载完成,data.filter成功渲染配合路由钩子使用
beforeUpdate(更新前)data更新时触发结束loading、请求数据为mounted渲染做准备
updated(更新后)data更新时触发数据更新时,做一些处理(此处也可以用watch进行观测)
beforeDestroy(销毁前)组件销毁时触发
destroyed(销毁后)组件销毁时触发,vue实例解除了事件监听以及和dom的绑定(无响应了),但DOM节点依旧存在组件销毁时进行提示

vue对象的生命周期
1). 初始化显示
* beforeCreate()
* created()
* beforeMount()
* mounted()
2). 更新状态
* beforeUpdate()
* updated()
3). 销毁vue实例: vm.$destory()
* beforeDestory()
* destoryed()
2. 常用的生命周期方法
created()/mounted(): 发送ajax请求, 启动定时器等异步任务
beforeDestory(): 做收尾工作, 如: 清除定时器

11 过滤&动画

地址

  1. vue动画的理解
    操作css的trasition或animation
    vue会给目标元素添加/移除特定的class
  2. 基本过渡动画的编码
    1). 在目标元素外包裹
    2). 定义class样式
    1>. 指定过渡样式: transition
    2>. 指定隐藏时的样式: opacity/其它
  3. 过渡的类名
    xxx-enter-active: 指定显示的transition
    xxx-leave-active: 指定隐藏的transition
    xxx-enter: 指定隐藏时的样式
<style>
    /*指定过渡样式*/
    .xxx-enter-active, .xxx-leave-active {
      transition: opacity 1s
    }
    /*指定隐藏时的样式*/
    .xxx-enter, .xxx-leave-to {
      opacity: 0;
    }


    .move-enter-active {
      transition: all 1s
    }

    .move-leave-active {
      transition: all 3s
    }

    .move-enter, .move-leave-to {
      opacity: 0;
      transform: translateX(20px)
    }
  </style>
</head>
<body>
<div id="demo">
  <button @click="show = !show">Toggle</button>
  <transition name="xxx">
    <p v-show="show">hello</p>
  </transition>
</div>

<hr>
<div id="demo2">
  <button @click="show = !show">Toggle2</button>
  <transition name="move">
    <p v-show="show">hello</p>
  </transition>
</div>


<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript">
  new Vue({
    el: '#demo',
    data: {
      show: true
    }
  })

  new Vue({
    el: '#demo2',
    data: {
      show: true
    }
  })

</script>

  1. 在目标元素外包裹
  2. 定义 class 样式
    指定过渡样式: transition
    指定隐藏时的样式: opacity/其它

12 自定义过滤器 (自定义日期)

moment日期插件注入
moment日期写法

  1. 理解过滤器
    功能: 对要显示的数据进行特定格式化后再显示
    注意: 并没有改变原本的数据, 可是产生新的对应的数据
  2. 编码
    1). 定义过滤器
    Vue.filter(filterName, function(value[,arg1,arg2,…]){
    // 进行一定的数据处理
    return newValue
    })
    2). 使用过滤器
    {{myData | filterName}}
    {{myData | filterName(arg)}}
<body>
<div id="test">
  <h2>显示格式化的日期时间</h2>
  <p>{{time}}</p>
  <p>最完整的: {{time | dateString}}</p>
  <p>最完整的: {{time | dateString2('YYYY-MM-DD')}}</p>
  <p>最完整的: {{time | dateString2('HH:mm:ss')}}</p>
</div>

<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/moment.js/2.22.1/moment.js"></script>
<script>
  Vue.filter('dateString',function(value){
      return moment(value).format('YYYY-MM-DD HH:mm:ss'); 
  })
  //如果有格式,显示有的,如果没有显示默认
  Vue.filter('dateString2',function(value,format='YYYY-MM-DD HH:mm:ss'){
      return moment(value).format(format); 
  })
  new Vue({
    el: '#test',
    data: {
        time : new Date(),
    },
    mounted () {
      setInterval(() => {
        this.time = new Date()
      }, 1000)
    }
  })
</script>

在这里插入图片描述

13 vue组件化编码

13.1 基本使用 components

App.vue

<template>
<div class="todo-wrap">
	//	3) 使用组件标签
       <todosHead/>
       <todosList/>
       <todosFoot/>
      </div>
<template/>
<script>
	//1) 引入组件
  import todosHead from './components/todosHead.vue'
  import todosList from './components/todosList.vue'
  import todosFoot from './components/todosFoot.vue'
  export default {
 //2) 映射成标签
  components: {
    todosHead,todosList,todosFoot
  }
}
<script>

13.2 组件间通信

13.2.1. props

  1. 此方式用于父组件向子组件传递数据
  2. 所有标签属性都会成为组件对象的属性, 模板页面可以直接引用
  3. 问题:
    a. 如果需要向非子后代传递数据必须多层逐层传递
    b. 兄弟组件间也不能直接 props 通信, 必须借助父组件才可以

    props声明类型
    在这里插入图片描述

实例
App.vue

<template>
	<div class="todo-wrap">
       <todosHead :addTodo="addTodo"/>
    </div>
<template/>
<script>
  import todosHead from './components/todosHead.vue'
  export default {
  methods: {
  //给todosHead页面传方法
   addTodo(todo){
   	//在数组中添加对象   unshift第一顺位添加
     this.todos.unshift(todo)
    }
  },
  components: {
    todosHead
  }
}
<script>

todosHead.vue

<template>
  <div class="todo-header">
    <input type="text" placeholder="请输入你的任务名称,按回车键确认" v-model="title" @keyup.enter="addItem"/>
  </div>
</template>

<script>
export default {
  props: {
    //声明addTodo为方法
    addTodo: Function
  },
  data() {
    return {
      title: ''
    }
  },
  methods: {
    addItem(){
      //1.检查输入的合法性
      const title=this.title.trim()
      if(!title){
        alert("请输入")
        return 
      }

      //2.根据输入生成todo对象
      const todo={
        title,
        complete:false
      }

      //3.todo对象添加todos中
        this.addTodo(todo)
      //4.清空
      this.title=''
    }
  },
}
</script>

在这里插入图片描述

13.2.2. 自定义事件

  1. 此方式只用于子组件向父组件发送消息(数据)
  2. 问题: 隔代组件或兄弟组件间通信此种方式不合适
// 通过 v-on 绑定
@delete_todo="deleteTodo"
// 触发事件(只能在父组件中接收)
this.$emit(eventName, data) //eventName方法名,参数data(可选)

实例
App.vue

<template>
	<div class="todo-wrap">
       <todosHead @addTodo="addTodo"/><!--@addTodo:自定义事件名,"addTodo" 回调函数-->
    </div>
<template/>
<script>
  import todosHead from './components/todosHead.vue'
  export default {
  methods: {
  //给todosHead页面传方法
   addTodo(todo){
   	//在数组中添加对象   unshift第一顺位添加
     this.todos.unshift(todo)
    }
  },
  components: {
    todosHead
  }
}
<script>

todosHead.vue

<template>
  <div class="todo-header">
    <input type="text" placeholder="请输入你的任务名称,按回车键确认" v-model="title" @keyup.enter="addItem"/>
  </div>
</template>

<script>
export default {
  props: {
    //声明addTodo为方法
    addTodo: Function
  },
  data() {
    return {
      title: ''
    }
  },
  methods: {
    addItem(){
      //1.检查输入的合法性
      const title=this.title.trim()
      if(!title){
        alert("请输入")
        return 
      }

      //2.根据输入生成todo对象
      const todo={
        title,
        complete:false
      }

      //3.todo对象添加todos中
        //触发addTodo自定义事件
        this.$emit('addTodo',todo)
      //4.清空
      this.title=''
    }
  },
}
</script>

或者使用$refs 传递函数
app.vue

<todosHead ref="header"/> 

 mounted() { //执行异步代码
      this.$refs.header.$on("header", this.addTodo)//指向header标签对象,$on监听名addTodo,回调函数addTodo
    },

13.2.3.PubSubJS 此方式可实现任意关系组件间通信(数据)

//安装
npm install --save pubsub-js
//查询
npm info pubsub-js
//App.vue导入
import PubSub from '../node_modules/pubsub-js'
//订阅消息
PubSub.subscribe('msg', function(msg, data){})
//发布消息
PubSub.publish('msg', data)

在这里插入图片描述

13.2.4. 此方式用于父组件向子组件传递标签数据slot

//子组件: Child.vue
<template>
<div>
<slot name="xxx">不确定的标签结构 1</slot>
<div>组件确定的标签结构</div>
<slot name="yyy">不确定的标签结构 2</slot>
</div>
</template>

//父组件: Parent.vue
<child>
<div slot="xxx">xxx 对应的标签结构</div>
<div slot="yyy">yyyy 对应的标签结构</div>
</child>

实例
原来,用solt组件传递只是测试,没有实现功能

App.vue

<div class="todo-wrap">
        <TodosHead @addTodos='addTodos'/><!--@addTodo:自定义事件名,"addTodo" 回调函数-->
        <TodosList :todos="todos"/>
         <TodosFoot :todos="todos" :selectAllTodos="selectAllTodos" :deleteCompleteTodos="deleteCompleteTodos"/> 
      </div>

TodosFoot.vue

 <div class="todo-footer">
    <label>
        <input type="checkbox" v-model="checkAll"/> 
    </label>
    <span>
      <span>已完成{{completeSize}}</span> / 全部{{todos.length}}
    </span>
    <button class="btn btn-danger" v-show="completeSize" @click="deleteAllCompleted">清除已完成任务</button>
  </div>

用solt
App.vue

<div class="todo-wrap">
        <TodosHead @addTodos='addTodos'/><!--@addTodo:自定义事件名,"addTodo" 回调函数-->
        <TodosList :todos="todos"/>
        <TodosFoot>
          <input type="checkbox" v-model="checkAll" slot="check"/> 
        </TodosFoot>
      </div>

TodosFoot.vue

 <div class="todo-footer">
    <label>
      <slot name="check"></slot> 
    </label>
    <span>
      <span>已完成{{completeSize}}</span> / 全部{{todos.length}}
    </span>
    <button class="btn btn-danger" v-show="completeSize" @click="deleteAllCompleted">清除已完成任务</button>
  </div>

14 抽取功能模块为工具类

在这里插入图片描述
工具类storageUtil.js

/*
向local中存储数据的工具模块
1. 向外暴露一个函数(功能)
   只有一个功能需要暴露
2. 向外暴露一个对象(包含多个功能)
   有多个功能需要暴露
 */
const TODOS_KEY='todos_key'
export default {
  saveTodos(todos){
    window.localStorage.setItem(TODOS_KEY),JSON.stringify(todos)
  },
  readTodos(){
    return JSON.parse(window.localStorage.getItem(TODOS_KEY) || '[]')
  }
}
//在App.vue中引入
 import storageUtil from './util/storageUtil.js'
 //data中获取方法
 todos: storageUtil.readTodos()  //封装工具类

todos: storageUtil.readTodos() //封装工具类

15vue-ajax(axios 的使用)

下载插件
npm install axios --save

// 引入模块
import axios from 'axios'

// 发送 ajax 请求
mounted() {
      const url='https://api.github.com/search/users?q=aaaa'
      axios.get(url).then(response =>{
        //成功
        const result=response.data
        const items= result.items[0]
        this.login=items.login
        this.refUtl=items.html_url

      }).catch(error => {
        alert('请求失败!')
      })
    },

16 vue-router路由

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。路由实际上就是可以理解为指向,就是我在页面上点击一个按钮需要跳转到对应的页面,这就是路由跳转;
中文文档
安装

//下载 
npm install vue-router --save

16.1使用步骤

  1. VueRouter(): 用于创建路由器的构建函数
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter) //用于创建路由器的构建函数
export default new VueRouter({   
  // 多个配置项
})
  1. 路由配置
routes:[
    {
    //一般路由
      path: '/about',
      component: About
    },
    {
      path: '/home',
      component: Home,
      //嵌套的子路由
      children:[
        {
          path: '/home/news',
          component: News
        },
        {
          path: '/home/message', //或者写为path: 'message',
          component: Message
        },
        {
          path: '/',
          redirect: '/home/news'
        }
      ]
    },
    {
    //自动跳转路由
      path: '/',
      redirect: '/about'
    },
  ]
  1. 注册路由器 main.js
import router from './router'
new Vue({
  router
})
  1. 使用路由组件标签
<!--生成路由链接    to----路由路径-->
    <router-link to="/about" class="list-group-item">About</router-link>
    <router-link to="/home" class="list-group-item">Home</router-link>
 
 	<!--keep-alive缓存路由组件对象, 可以提高用户体验-->
     <keep-alive>
         <!--用来显示当前路由组件界面-->
           <router-view></router-view>
      </keep-alive>

16.2向路由组件传递数据

16.2.1 路由路径携带参数(param/query)

  1. 配置路由
  children: [
            {
              path: '/home/message/messageDetal/:id',
              component: MessageDetal
            }
          ]
  1. 路由路径
<li v-for="message in messages" :key="message.id">
        <router-link :to="`/home/message/messageDetal/${message.id}`">{{message.title}}</router-link>
      </li>
  1. 路由组件中读取请求参数
this.$route.params.id

在这里插入图片描述

16.2.2 属性携带数据

父类

  <!--显示当前组件   msg自定义的参数-->
      <router-view  msg="abc"></router-view>

子类

<template>
  <div>
    <p>{{msg}}</p>
  </div>
</template>

<script>
export default {
  props: {
    msg: String //接收属性前,先声明
  },
}
</script>

16.3 缓存路由组件对象

  1. 默认情况下, 被切换的路由组件对象会死亡释放, 再次回来时是重新创建的
  2. 如果可以缓存路由组件对象, 可以提高用户体验
<keep-alive>
	<router-view></router-view>
</keep-alive>

16.4命名路由


const router = new VueRouter({
  routes: [
    {
      path: '/user/:userId',
      name: 'user',//命名
      component: User
    }
  ]
})

16.5 路由导航

在这里插入图片描述

命名路由后:


<router-link :to="`/home/message/messageDetal/${message.id}`">{{message.title}}</router-link>
等同于
<router-link :to="{ name: 'messageDetal', params: { id: `${message.id}` }}">{{message.title}}</router-link>

在这里插入图片描述
在这里插入图片描述
例子

<template>
  <div>
    <h1>about</h1>
    <hr>
    <p>{{msg}}</p>
    <input type="text" @keyup.enter="clickEnter">
  </div>
</template>

<script>
  import router from '../router'
export default {
  props: {
    msg: String
  },
  methods: {
    clickEnter(){
      const userId=1*1
      router.push({path:`home/message/messageDetal/${userId}`})
      //router.push({ name: 'messageDetal', params: { id: `${userId}` }})
    }
  },
}
</script>

链接跳转没问题
在这里插入图片描述

16.5.1 其他API

  1. this.$router.push(path): 相当于点击路由链接(可以返回到当前路由界面)

在这里插入图片描述

  1. this.$router.replace(path): 用新路由替换当前路由(不可以返回到当前路由界面)
    在这里插入图片描述

  2. this.$router.back(): 请求(返回)上一个记录路由

  3. this.$router.go(-1): 请求(返回)上一个记录路由

  4. this.$router.go(1): 请求下一个记录路由

<template>
  <div>
    <ul>
      <li v-for="message in messages" :key="message.id">
        <!-- <router-link :to="`/home/message/messageDetal/${message.id}`">{{message.title}}</router-link> -->
        <router-link :to="{ name: 'messageDetal', params: { id: `${message.id}` }}">{{message.title}}</router-link>
        <button @click="pushShow(message.id)">push</button>
        <button @click="replaceShow(message.id)">replace</button>
      </li>
    </ul>
    <button @click="$router.back()">返回</button>
    <hr>
    <router-view></router-view>
  </div>
</template>

<script>
  export default {
    data()
    {
      return {
        messages: []
      }
    },
    mounted()
    {
      window.setTimeout(() =>
      {
        const messages = [
          {
            id: 1,
            title: 'message01'
          },
          {
            id: 2,
            title: 'message02'
          },
          {
            id: 3,
            title: 'message03'
          }
        ]
        this.messages = messages
      }, 1000)
    },
    methods: {
      pushShow(id)
      {
        this.$router.push(`/home/message/messageDetal/${id}`)
      },
      replaceShow(id)
      {
        this.$router.replace(`/home/message/messageDetal/${id}`)
        
      },
    },
  }
</script>

特殊

1.filter过滤

dotos为数组 字段complete为boolean类型在这里插入图片描述

2.forEach 循环

todo中complete赋值为check
在这里插入图片描述

3.unshift()

给数组添加todo对象并放在第一个
在这里插入图片描述

4.splice()

删除数组中下标为index的,1表示个数
在这里插入图片描述

5.watch监听

官方文档
在这里插入图片描述
setItem(key,walue)
getItem(key)
跟集合map一样
在这里插入图片描述
会缓存,重新运行就没有了
在这里插入图片描述

6. @keyup.enter

为click事件 回车键确认
在这里插入图片描述

7. 鼠标移动事件

onmouseenter 鼠标移动进来
onmouseleave 鼠标移动出范围

在这里插入图片描述

8.reduce() 数组的计算方法

array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
在这里插入图片描述

测试代码

有需要可以去github自己下载
测试代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值