作者: admin

  • css3 图片 object-fit

    img 自适应 图片 css3 图片 新闻图片 图片 等比例 裁剪 布局 自适应 定位 自适应居中 垂直居中

    object-fit操作是保证图片不会破坏比例情况下进行

    //保证等比例显示出全图内容,
    1,宽比高大时:宽100%,高auto
    2, 高比宽大时:高100%,宽auto
    优点:图片内容显示完全
    缺点:就是容器会留部分空白
    object-fit: contain;

    定位:
    配合object-position:50% 50%使用可以移动图片位置

     

    //保证填满容器
    优点:图片占满容器,不会留空白处
    缺点:图片部分会被裁剪
    object-position: cover

     

     

    //保证填满容器又不会被裁剪
    缺点:破坏图片比例,图片扭曲(不推荐)
    object-fit: fill;

     

    案例:

    <div style="height: 200px;width: 200px;background: pink;">
      <img src="mm.jpg" style="object-fit: contain;width: 100%; height: 100%;">
    </div>

     

    img_edit

    http://www.zhangxinxu.com/study/201503/css3-object-fit.html

     

    用js实现,object-fit: contain效果

     

     /******最完美解决 图片在图片框内按宽高比例自动缩放!!!***/
    //Img:要放图片的img元素,onload时传参可用this
    
    //maxHeight :img元素的高度,像素(图片框 最大高度)
    
    //maxWidth:img元素的宽度,像素(图片框 最大宽度)
    function AutoSize(Img, maxWidth, maxHeight) {
       var image = new Image();
       //原图片原始地址(用于获取原图片的真实宽高,当<img>标签指定了宽、高时不受影响)
       image.src = Img.src; 
       // 当图片比图片框小时不做任何改变 
       if (image.width < maxWidth&& image.height < maxHeight) {
          Img.width = image.width;
          Img.height = image.height;
       }
       else //原图片宽高比例 大于 图片框宽高比例,则以框的宽为标准缩放,反之以框的高为标准缩放
       {
          if (maxWidth/ maxHeight <= image.width / image.height) //原图片宽高比例 大于 图片框宽高比例
          {
             Img.width = maxWidth; //以框的宽度为标准
             Img.height = maxWidth* (image.height / image.width);
          } 
          else { //原图片宽高比例 小于 图片框宽高比例
             Img.width = maxHeight * (image.width / image.height);
             Img.height = maxHeight ; //以框的高度为标准
          }
       }
    
    }
    
    
    调用:
    <img onload="AutoSize(this, $(this).width(), $(this).height())">
    
    

     

     

     

     

  • vue.js笔记

    目前在vue 2.5.9测试学习

    顺便推荐调试工具:vue-devtools,直接去chrome商城安装即可。在引入vue.js时,不能使用min版本不然无法使用。

    创建vue视图
    var vm=new Vue({
         name:'root', //给这里实例化对象取一个名字,组件想知道是哪个实力化对象调用的就使用this.$parent.$options.name
         el:'#app’,   //不能将容器设置在html和body标签上,如果el没声明也可以使用 vm.$mount('#app')来实现
         parent:baba, //该属性一般用在new Vue对象中,
         data:{  //存放数据
             str:'字符串数据',
             arr:[ //json数据
                 {name:'名字',age:123},
                 {name:'名字',age:123},
             ],
             obj:{age:22,name:'小么'}
         },
         methods:{  //存放事件
            click:function(e){
                console.log(this);
            }
         },
         components:{},
         render:...,
         directives:...,
         filters:...,
         computed:{
            myname:{
               get(){ return this.xx  },
               set(newValue){ this.$refs.xxx.src = newValue }   //在别的地方修改 this.myname = 'baidu.con',newValue就能获取到值
            } 
         },
         watch:{ //监听的数据有变为就触发回调
             //遇到复合型数据推荐结构是[{},{}]
            str:function(new_value,old_value){
            },
            arr:{
                handler: function (val, oldVal) { /* ... */ }, //不要使用箭头函数,否则this无法指向vue对象
                deep: true  //遇到对象或者复合结构要开启深度监听,简单数组不需要开启
            },
            'obj.age':function (val, oldVal) { /* ... */ },
             obj:[
                function handle1 (val, oldVal) { /* ... */ },
                function handle2 (val, oldVal) { /* ... */ }
             ]
         },
    
    
       
         //生命周期
         beforeCreate:function(){
              //vue实例化前执行,data数据和dom还没有数据
         },
         created:function(){
              //vue实例化后执行,已经有data数据,但还没加载dom
         },
         beforeMount:function(){
              //组件内容渲染到页面前执行,data数据有了,dom还没在页面中
         },  
         render:function(){
              //render执行顺序是在beforeMount和mounted之间,它的作用就是把DOM插入到页面上,所以到了mounted执行时我们才能看见数据
         },
         mounted:function(){
              //组件内容渲染到页面后执行,data和dom都在页面中了
         },
         beforeUpdate:function(){
              //只有当data数据发生变化后,但数据还没插入到dom的时候执行
         },
         updated:function(){
              //data数据变化完成并插入到dom之后执行
         },
         beforeDestroy:function(){
              //销毁之前回调,使用vm.$destroy()即是销毁了vm组件且先触发beforeDestroy之后是触发destroyed
             
         },
         destroyed:function(){
              //销毁后回调,这里的销毁后数据还是存在的,只是修改数据已经无法驱动修改视图变化了而已,
              //之前绑定在dom的事件例如click mouseenter等等还是有效的,仅仅是无法驱动视图变化而已,之前有的还是有
         },
    
         //activated和deactivated,只针对开启keep-alive的组件触发
         activated:function(){
            console.log("进页面")
         },
         deactivated:function(){
            console.log("离开页面")
         },
    
         //组件生命周期
         beforeRouteEnter(to, from, next) {
           //不能获取到this
           // do someting
           // 在渲染该组件的对应路由被 confirm 前调用
         },
         beforeRouteUpdate(to, from, next) {
           // do someting
           // 在当前路由改变,但是依然渲染该组件是调用
         },
         beforeRouteLeave(to, from ,next) {
           //能获取到this
           // do someting
           // 导航离开该组件的对应路由时被调用
           next()
         }
    });

    vue对象嵌套、加载顺序问题

    对于新手或者是要投入项目的最好先搞清楚,方便之后的架构设计

    1,情况:父对象id=xx,里面嵌套着子对象xx1,并且里面有相同元素{{a}}

    修改后

    2,情况2:父元素里面嵌套着子元素,但子元素里面的{{a1}},父元素没有

    修改后

    总结:

    1,子元素有的属性,父元素一定要有;父元素有的属性,子元素可以不声明。

    2,子元素要加载在父元素前面

    遮丑
    //放在公共样式的最最前面
    [v-cloak] {
       display: none !important;
    }
    
    <div id=“app” v-cloak>  </div>
    对外直接调用vue属性
    vm.str  //字符串数据

    vue数据的增、删、改
    vue不允许添加额外属性,只能在已有的基础上修改,我们可以自定义一个空对象,在其基础上添加属性也能达到这样的效果。

    var vm1= new Vue({
      el: '#repeat',
      data:{
        str:'',  //预留空的
        obj:{}   //预留空的
        obj1:{a:''}  //如果模板中要调用obj1.a,就要在vue实例中预先设置好,否则会报错。
     }
    })

    在修改数组、对象时也需要vue内置的方法去修改,如果还想有数据双向绑定效果就要用以下方法去修改。否则修改后的视图也不会改变。

    对象

    修改:
      Vue.set(vm1.obj,'age',123) //添加了age属性
      this.$set(this.someObject,'b',2)  //临时补加a属性且赋值,如果要删除使用this.$delete(this.someObject,'b')
       或
      vm1.str=xxxx //直接修改
    
    
    添加:
      this.obj = Object.assign({}, this.obj, { a: 1, b: 2 }); //在obj对象上添加了a属性和b属性
      调用:{{obj.age}}

    数组

    data:{
     arr:['我的名字','是谢尔顿']
    }
    
    修改:
    Vue.set(this.arr, 1, '陈陈')
    
    修改长度
    example1.items.splice(newLength)
    vue操作数组
    - push()      //末尾加
    - pop()       //末尾减
    - shift()      //首减
    - unshift()  //首加 ie8不支持
    - splice()    //推荐使用,可增、删、改
    - sort()       //升序
    - reverse()  //降序
    //以上方法会修改元数组
    
    
    filter()
    concat()
    slice()
    //以上方法,不会修改原数组,返回一个新数组
    var example2 = new Vue({
      el: '#example-2',
      data: {
          items: [
            { message: 'Foo' },
            { message: 'Bar' }
          ]
      }
    })
    example2.items.push({ message: 'Baz123' })  //在items数组里插入对象
    
    Vue.set(this.items,2,{name:’111’})   //找到数组this.items   在索引2的位置上添加数据  {name:’111’}
    或者
    this.arrys.splice(2,0,'吗132’)   //在数组中索引2的位置,插入一个数组内容为'吗132’
    数组替换
    filter()
    concat()
    slice()
    example1.items = example1.items.filter(function (item) {
      return item.message.match(/Foo/)
    })
    修改数组内容
    example2.items.$set(0, { childMsg: 'Changed!'})
    删除数组
    this.arrys.splice(0,1)  //从第0个索引开始包括第0个索引,选1个元素开始删除
    注意:$remove已经被弃用

    $用法
    vm.$data //获取到vm里面data设置的数据
    vm.$el //获取到此id的原生DOM
    vm.$options //vm.$options.render=(a)=>{ return a(‘div’,{},’文字’); } ,data属性里面的数字有更新就会触发该函数
    还有更多$的方法

    表达式

    {{str}} //输出变量
    表达式指出js语法
    {{ number + 1 }}
    {{ ok ? 'YES' : 'NO' }} //只能使用三元运算,不能使用if else
    {{ message.split('').reverse().join('') }}
    <div v-bind:id="'list-' + id"></div>

    不解析表达式

    <div v-pre>{{name}} </div> //直接输出 {{name}}

    计算属性
    计算属性主要是弥补解决{{}}表达式不能解决复杂的问题。
    vue初始化时,有些属性需要在vue初始化后进行计算后才显示
    什么时候需要计算属性?当一个值需要依赖另一个值变化而变化的时候就需要,尤其是对大数据的时候

    <div id="example">
     a={{ a }}, b={{ b }}
    </div>
    
    var vm = new Vue({
      el: '#example',
      data: {
        a: 1
      },
      computed: { //计算属性里面的属性名调用时,直接写变量,如:{{b}}, 不能{{b()}}
        b: function () { //在计算属性里面定义的属性名可以直接在表达式中显示,b值依赖a,需要初始化时计算出b值这时候就需要计算属性
        // `this` 指向 vm 实例
           return this.a + 1 //a值变化,b值也会自动更新
        }
    
        //另一种写法:
        myname:{
           get(){ return this.xx  },
           set(newValue){ this.$refs.xxx.src = newValue }   //在别的地方修改 this.myname = 'baidu.con',newValue就能获取到值
        } 
      }
    })
    
    结果:
    a=1,b=2  (只有变量b被调用的时候,计算属性里面的函数才会去运行)

    ***注意:当使用v-model监听某个值时,页面中正好有一个表达式是类似是<p>{{xx()}}</p>,如果xx()如果是做了很复杂耗时的计算,推荐把xx方法写入到computed,中不然页面性能会大大降低。案例:indexaaa

    https://cn.vuejs.org/v2/guide/computed.html#%E8%AE%A1%E7%AE%97%E5%B1%9E%E6%80%A7%E7%9A%84-setter

    还额外提供一个set属性

    computed:{
        fullName:{
            get: function (){
                return this.firstName + ' ' + this.lastName
            },
            set: function (newValue) {
                //一旦this.fullName = '1122'属性有改变就会触发set
                this.firstName = newValue
                this.lastName = '改了'
            }
        }
    },

    表单

    案例:test

    模板
    //需要控制大部分html显示、隐藏的 就把html都放入<template>里面
    //v-show 不能用在 <template>上 也不支持 v-else

    <template v-if="message">
      <h1>Title</h1>
      <p>Paragraph 1</p>
      <p>Paragraph 2</p>
    </template>
    <p v-else>No</p>
    
    
    取代v-else的方法:
    <p v-show="condition">YES</p>
    <p v-show="!condition">NO</p>

    (提示:频繁切换推荐使用v-show,因为v-if每次显示的时候都需要耗性能)

    过滤器表达式

    过滤器只能放在{{ }} 和 v-bind 中

    {{ message | capitalize }}    //message的值传入到capitalize函数里面进行过滤处理后在返回
    {{ message | filterA | filterB }}    //过滤条件可以叠加
    {{ message | filterA (‘arg1', arg2) }}   //过滤传参数,默认第一个参数是message,‘arg1', arg2分别是第二、第三个参数
    <li v-for="(value,index) in scroll_img" :class="value.xx | filterA">
       {{index}}
    </li>

    自定义过滤器

    <p>{{name | time_style | add_year}}</p>  //name是数据,name数据会经过time_style、add_year的过滤
    
    data:{
      name:new Date(),  //原始数据
    },
    filters:{
      time_style:function (value) {
        console.log(value); //这里的value就是new Date()
        return value.getHours()+':'+value.getMinutes()+':'+value.getSeconds()
      },
      add_year:function (value) {
        console.log(value); //这里的value是经过time_style处理过后返回来的值
        return "2017-"+value
      }
    }

    条件语句 (显隐)

    //v-if是直接删除DOM来控制显隐
    <p v-if="greeting">Hello!</p>
    <p v-else>No</p>
    
    条件可以这么写
    <h1 v-if="yes">Yes!</h1>
    <h1 v-if="no">No!</h1>
    <h1 v-if="age >= 25">Age: {{ age }}</h1>
    <h1 v-if="name.indexOf('jack') >= 0">Name: {{ name }}</h1>
    
    var vm = new Vue({
      el: '#app',
      data: {
        yes: true,
        no: false,
        age: 28,
        name: 'keepfool'
      }
    })
    
    
    //v-show根据display: none;来控制显隐
    <p v-show="message">YES</p>
    <p v-else>No</p>
    
    
    2.1.0 新增
    <div v-if="type === 'A'">
    A
    </div>
    <div v-else-if="type === 'B'">
    B
    </div>
    <div v-else-if="type === 'C'">
    C
    </div>
    <div v-else>
    Not A/B/C
    </div>

    元素属性attr

    data: {
     text:'text',
     value:'值',
     url:'http://baidu.com',
     a_title:'a连接'
    }
    
    <a v-bind:href="url" v-bind:title="a_title">aaa</a>
    //<a href="http://baidu.com" title="a连接">aaa</a>
    
    <input v-bind:type="text" v-bind:value="value">
    //<input type="text" value="值">
    
    <a v-bind:href="url"></a>
    缩写:
    <a :href="url"></a>
    动态属性

    data(){
     msg:'内容'
     name:'titlexx',
     event:'click'
    },
    template:`<div :[name]="msg" @[event]="handle"></div>`,
    methods:{
     handle(){
     }
    }
    
    效果:
    <div titlexx="内容"></div>

    class动态添加
    在vue中添加class推荐使用v-bind:class来添加

    对象方法:

    (1)
     <div class="static" v-bind:class="{ 'class-a': isA, 'class-b': isB }"></div>
    data: {
     isA: true,
     isB: false
    }
    结果:<div class="static class-a"></div>
     
    
    (2)
    <div v-bind:class="classObject"></div>
    data: {
      classObject: {
       'class-a': true,
       'class-b': false
      }
    }

    数组方法:

    <div v-bind:class="[classA, classB]">
    data: {
      classA: 'class-a',
      classB: 'class-b'
    }
    
    <div class="class-a class-b"></div>

    数组和对象

    <div v-bind:class="[{'active':a},iserror]"> fasdfasdf </div>
    
    data:{
      a:true,
      iserror:'name_class'
    },
    
    结果:<div class="active name_class"> fasdfasdf </div>
    
    
    另一种表达式
    <div v-bind:class="[classA, { classB: isB, classC: isC }]">

    三元表达式

    <div v-bind:class="[classA, isB ? classB : '']">

    如果遇到负责判断推荐使用计算属性,如:

    <input type="text" v-model="name" :class="class_array">
    
    var app=new Vue({
      el:"#app",
      data:{
        a:true,
        b:false
      },
      computed:{
        class_array:function () {
                       return {
                          class_1: this.a && !this.b
                       }
                     }
      }
    });

    css样式

    (推荐)对象方法:
    <div v-bind:style="styleObject"></div>
    data: {
      styleObject: {
        color: 'red',
        fontSize: '13px'
      }
    }
    
    数组方法:
    <div v-bind:style="[styleObjectA, styleObjectB]">fff</div>
    data: {
      styleObjectA:{color:'red'},
      styleObjectB:{fontSize:'13px'},
    }
    
    
    常规:
    <img alt="" :style="'background:url('+val.cover_picture+') no-repeat center;border:0'">
    
    结果都是:<div style="color: red; font-size: 13px;">fff</div>

    都类似要学会举一反三

    DOM事件

    v-on:input  缩写 @input
    
    <input type="text" @input="fn">  //fn写需要的逻辑判断
    
    类似于jquery写法
    $('.tx').bind('input propertychange', function() {    
        document.title=$(this).val();
    });

    图片监听事件

    <img :src="item.iconUrl" @error="errorImgfn" >
    
    methods: {
        errorImgfn(e){
          e.target.src=require('@/assets/imgs/dbsx.png')
        },
    }
    
    或者
    <img :src="item.iconUrl" :onerror="errorImg" >
    
     data () {
        return {
          errorImg: 'this.src="' + require('@/assets/imgs/dbsx.png') + '"'
        };
     },
    同样也有@onload=""

    案例:

    methods:{
      click:function(e){
        console.log(this);
      }
    }
    
    <button v-on:click="click($event)">点</button>
    缩写:<button @click="click($event)">点</button>

    解除事件绑定:

    vue不像jquery有unbind和off,但是可以利用一些小技巧去实现,例如:

    <div id="app">
     <button @click="status && fn($event)">xxx</button>
     <p><button @click="bian">change</button></p>
    </div>
    
    new Vue({
     el:'#app',
     data:{
        status:true
     },
     methods:{
        fn:function (e) {
            console.log(e)
        },
        bian:function () {
            this.status=false;
        }
     }
    });
    
    //通过改变status变量去实现

    常用:

    @focus  //input 获取焦点
    @blur   // 失去焦点

    touch事件

    长按,点击事件

    <div @touchstart="gotouchstart()" @touchmove="gotouchmove" @touchend="gotouchend()"></div>
    methods:{
           gotouchstart(img){
                touch_time=new Date()/1000; //记录手指放在屏幕上的时间
                temp_time=0;
                run_fn=null;
                clearTimeout(run_fn);
               run_fn= setTimeout(function () {
                   Tools.dialog.strHtml('<div><img style="display: block;width: 70%;" src="'+img+'"> </div>');
                },800);
            },
            //手释放,如果在800毫秒内就释放,则取消长按事件,此时可以执行onclick应该执行的事件
            gotouchend(num){
                var self=this;
                if(  Math.ceil( ((new Date()/1000)-touch_time)*100  )/100>0.8  ){
                   // console.log('长按');
    
                }else{
                    clearTimeout(run_fn);
                    self.gokill(num);
                }
            },
            //如果手指有移动,则取消所有事件,此时说明用户只是要移动而不是长按
            gotouchmove(){
                clearTimeout(run_fn);
            },
    }

    指令修饰符

    <a v-bind:href.literal="url" v-bind:title="a_title">aaa</a>
    直接显示 <a href="url" title="a连接">aaa</a> //href直接显示属性名
    
    禁止默认行为
    <button v-on:submit.prevent="onSubmit"></button> //相当于加了event.preventDefault()
    
    <a @click.stop=“"> </a> //阻止事件冒泡
    <div @click.self></div> //只有该元素触发,不包括子元素

    1,事件修饰符

    .stop //阻止事件冒泡
    .prevent //阻止默认行为,例如点击a会自动跳页面,点击<input type=“submit”>会刷新提交数据
    .capture //一般事件都是在冒泡时候被执行的,addEventListener(‘click’,fn,true) ,添加此修饰符相当于改成了true,默认是false
    .self //例如当父元素绑定了click,父元素里面又有一个子元素,当点击了子元素时候,其实同时也点击了父元素因为父元素包裹着子元素嘛,click触发。当给父元素添加.self时,在点击子元素时候,就不会出发click了。也有阻止冒泡的效果,相当于e.currentTarget
    .once //2.1.4 新增,只触发一次事件
    .native // v-on:click.native,这样触发的就是js原生的click事件了而不是vue封装好的事件
    
    <a v-on:click.stop="doThis"></a> //阻止默认行为
    <a v-on:click.stop.prevent="doThat"></a> //同时阻止默认行为和事件冒泡
    <form v-on:submit.prevent></form> //只添加修饰符 ,不添加其他参数

    2,键盘修饰符

    <!-- 同上 -->
    <input v-on:keyup.enter=“fn”> //当input获取焦点时候,按回车就会触发fn事件,对外调用就是
    vm.fn()事件
    
    <!-- 缩写语法 -->
    <input @keyup.enter=“fn">
    或者
    <input @keyup.13="fn" type="text”>
    
    按键组合
    <input @keyup.ctrl.67="fn" type="text”> //获取input焦点后同时按住ctrl+c 就能触发fn函数
    
    
    键盘别名
    enter
    tab
    delete
    esc
    space
    up
    down
    left
    right
    ctrl
    alt
    shift
    meta (mac是command,win是windows)
    
    自定义别名
    Vue.config.keyCodes.huiche=13

    3,数据同步修饰符

    lazy //效果都是同步,但是只有在input失去焦点时候才同步数据
    number //将字符串的数字转化为数字类型,如果是NaN直接显示此数据,例如是abc123,说明是NaN,那就直接显示abc123
    trim //自动去掉 首尾空格
    
    
    举例:
    <input v-model.lazy="msg">
    <input v-model.number="msg">
    <input v-model.trim="msg">

    属性监听$watch

    https://cn.vuejs.org/v2/api/#watch

    var vm = new Vue({
       el:'#app',
       data:{
           str:'你好',
           arr:[],
           obj:{
               a:''
           }
       },
       watch:{
          str:function(new_value,old_value){
          },
          'obj.a':{
             handler: function (new_value,old_value) { /* ... */ }
          }
          //或者
          'obj':{
             handler: function (new_value,old_value) { new_value.a },
             deep: true, //深度监听
             immediate: true //true时,默认执行一次handler函数
          }
       }
    });
    
    或者
    
    

    https://cn.vuejs.org/v2/api/#vm-watch

    vm.$watch('str', function (new_value,old_value) { //属性值发生改变就会触发
     
    },{
      deep: true
    });
    
    //注意如果直接监听整个对象arr或者obj,old_value返回来的值跟new_value是一样的
    
    

    input监听

    两种方法

    1,v-on:input

    <input type="text" v-on:input ="inputFunc($event)">
    
    methods:{
       inputFunc:function (e) {
          document.title=e.target.value;
       },
    }

    2,watch

    <input type="number" :value="buy_num" v-model="buy_num">
    
    data:{
       buy_num:0
    },
    watch:{
       buy_num:function(){
             console.log(this.buy_num);
       }
    }

    循环、遍历

    数据:

    data:{
       array:['陈陈',20,'男'],
       obj:{
         xx1:'数字1',
         xx2:'数字2',
         xx3:'数字3'
       },
    }

    数组:

    <ul>
     <li v-for="(value,index) in array">
        索引:{{index}}----值:{{value}}
     </li>
    </ul>

    对象:

    <ul>
     <li v-for="(value,key,index) in obj">
       属性名:{{key}}--- 
       值是:{{value}}---
       索引是{{index}} 
     </li>
    </ul>

    复合数据:

    data:{
        scroll_img:[
         {img_name:1},
         {img_name:2},
         {img_name:3},
         {img_name:4}
        ]
    },
    methods:{
        remove_li:function (index) {
           this.scroll_img.splice(index,1)
        }
    }

    对象和数组:

    <ul>
     <li :class="'xx-'+index" :title="value.img_name" v-for="(value,index) in scroll_img">
       值是:{{value.img_name}}---
       索引是{{index}} ----
       <button @click="remove_li(index)">删除该项</button>
     </li>
    </ul>

    v-for互嵌

    data:{
      scroll_img:[
        {img_name1:1},
        {img_name2:2},
        {img_name3:3},
        {img_name4:4},
      ]
    }
    
    
    <ul>
     <li v-for="(value,index) in scroll_img">
       索引:{{index}}---
       <span v-for=" (val,key,index) in value"> 属性:{{key}} </span>---
       <span v-for=" (val,key,index) in value"> 值:{{val}} </span>
     </li>
    </ul>

    v-for 筛选、过滤

    在遍历的同时不希望有些数据显示出来

    1,//v-bind:class方法,给不需要显示的数据添加指定class名隐藏或者添加test自定义过滤方法
    <li v-for="(value,index) in scroll_img" :class="!!value.xx?'gg':'mm' | test">
       索引:{{index}}---
    </li>
    2,//v-show方法,跟v-bind:class效果类似仅仅是隐藏,dom还是存在的
    3,//v-if,直接把不希望显示的数据删除
    <li v-for="(value,index) in scroll_img" v-if="!value=='xx'">  //遍历出来的value值如果等于xx字符串就不显示
      索引:{{index}}---
    </li>
    4,通过计算属性在过滤后才把值带入到v-for中遍历

    v-for排序:升序、降序

    如果希望遍历的值根据某个字段降序或者升序,要先通过计算属性排列好才带入到v-for循环中

    :key重新渲染

    案例:

    默认情况使用v-for渲染列表时,在每个input输入内容,如下

    在点击“打乱顺序”,reverse(),视图上并没有发生任何变化,其实dom结构已经发生了变化,如图:

    所以需要强制在更新一次排序视图才能同步更新,给遍历input的dom结构添加一个:key=”index”属性,index必须是唯一不能重复,添加之后在点击“打乱顺序”,

    如果在使用v-for遍历数据时,如果数据发生了变化但是视图没变可以尝试使用:key来解决。

    https://cythilya.github.io/2017/04/27/vue-list-rendering/

    生命周期

    vue的一系列执行过程,其实都通过以下的钩子(回调函数)捕获到,同时也可以通过钩子在我们需要的某时刻添加我们需要的功能。

    (1)第一次刷新页面加载时都会触发到以下钩子:

    beforeCreate   //常用,添加类似loding效果
    create   //常用,在数据显示到视图时,在额外添加数据到vm.$data中
    beforeMount
    mounted   //常用,有时需要获取dom,或者把接口的数据插入到dom中

    (2)数据发生改变时:

    beforeUpdate
    updated   //常用,数据发生改变后回调

    (3) 销毁(就是停止数据的双向绑定效果)vm.$destroy()

    beforeDestroy
    destroyed  //常用,销毁后回调

    虽然生命周期经历过这几个步骤,但是常用的也就那么几个。

    组件封装(重点)

    自己一个经典案例:《vue树节点创建以及增删改

    作用就是可以重复性的利用代码,例如选项卡组件可以在同一个页面下 多次使用。

    组件分:全局 和 局部

    1,全局

    var myComponent = Vue.extend({
      template: '<div>This is my first component!</div>’ //这个是子组件,组件必须要有一个容器div包裹着才行
    })
    
    
    
    // 2.注册组件,并指定组件的标签,组件的HTML标签为<my-component>
    Vue.component('my-component', myComponent)  <---全局组件声明方法
    
    或者
    
    Vue.component('my-component',{
       template: '<div>This is my first component!</div>’ //这个是子组件,组件必须要有一个容器div包裹着才行
    })
    
    //全局组件声明一定要写在new Vue实例对象的前面不然就出错
    
    new Vue({
     el: '#app'
    });
    
    
    调用:
    <div id="app">
      <!-- 3. #app是Vue实例挂载的元素,应该在挂载元素范围内使用组件-->
      <my-component></my-component> //调用组件,放在哪个vm容器下就在哪个vm显示,这个是父组件
    </div>

    2,局部

    new Vue({
       el: '#app',
       components: {
          'my-component' : {
              template:'<div> <button @click="fn">按钮1</button> <p>{{value}}</p> </div>'
          }
       }
    });
    
    
    或者
    
    var myComponent = Vue.extend({
      template: '<div>This is my first component!</div>'
    })
    
    new Vue({
    el: '#app', components: { // 2. 将myComponent组件注册到容器#app实例下,也就只有此vm容器内部可以使用其他的容器不行 'my-component' : myComponent } });
    调用:
    <div id="app">
       <!-- 3. my-component只能在#app下使用-->
       <my-component></my-component>
    </div>

    以上发现一个问题如果在组件复杂的时候template需要很多html就很麻烦且不好写,
    可以利用<script type=”text/x-template” id=”page”>

    案例:
    <script type="text/x-template" id="page"> 
     <ul>
       <li></li>
     </ul>
    </script>
    
    Vue.component("page",{ template:"#page"})
    
    或者
    
    template:'<div>\
               <h2>我是子组件的标题</h2>\
               <slot>\
                 只有在没有要分发的内容时才会显示。\
               </slot>\
              </div>'

    特殊dom结构  使用is
    例如table的结构都是固定的,要基于这样固定结构模板来写组件要这么做

    <table>
      <tbody is="my-component"></tbody>  //这里的tbody会被模版替代
    </table>
    
    Vue.component('my-component',{
     template:'<tbody><tr><td>123</td></tr></tbody>'
    });

    效果:

    <table><tbody><tr><td>123</td></tr></tbody></table>

    类似的还有ul ol select

    *注意:不推荐使用table表格里面嵌套vue代码会报错,尤其是ie10以上浏览器。推荐使用div+css去模拟table表格

    .vam { display: table; border-collapse:separate;border-spacing: 5px; } //table
    .vam>div { display: table-row; }  //tr
    .vam>div>div { display: table-cell; vertical-align: middle; }  //td
    
    <div class="vam">
        <div>
            <div> </div>
        </div>
    </div>

    组件继承

    //组件继承使用场景,可以把多组件使用比较多的方法独立封装成一个公共组件,其他组件在去调用,避免写重复代码。

    <div id="root">
    
    </div>
    
    var a={
       template:`<div>123---{{xxx}}</div>`
    }
    
    var x=Vue.extend(a);
    
    new x({
      el:'#root',
      data:{
         xxx:'aaa'
      }
    });
    //父组件
    var a={
      template:`<div>123</div>`,
      mounted(){
         console.log('a父亲');
      }
    }
    
    
    //子组件
    var b={
      extends:a, //子继承父
      template:`<div>456</div>`, //子模板覆盖父模板
      mounted(){
        console.log('b子');
        this.$parent.$options.name //打印出实例化对象的name属性值
      }
    }
    
      实例化方法1:
      var c=Vue.extend(b);  //组件b插入到Vue对象中
      new c({
        el:'#root'
      });
    
      实例化方法2: //推荐使用这种写法
      new Vue({
          name:'root',
          el:'#root',
          components:{
              diycomponent:b
          },
          template:'<diycomponent></diycomponent>'
      });
    
    //结果
    a父亲
    b子

    parent案例:

    var a={
      template:`
       <div>
         <div>{{haha}}---{{baba}}</div>
       123</div>
      `,
      props:['baba']
    }
    
    
    var b={
      extends:a, //b组件继承a组件
      data:function () {
        return {
           haha:'给父组件传参'
        }
      }
    }
    
    var xx=new Vue({
      name:'xx',
      data:{
        a1:'11',
        b2:'22'
      }
    });
    
    
    new Vue({
      parent:xx, //继承xx的new Vue对象
      el:'#root',
    
      components:{
        com:b //引入组件b
      },
      template:'<com :baba="this.$parent.a1"></com>', //将组件渲染出来
      mounted:function () {
          console.log( this.$parent.a1 ); //获取到指定父元素的值,可以获取不推荐去修改
      }
    });
    
    

    组件传参 (重点)

    要向组件中的template模板传值,只能靠组件中的data和props
    prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。

    1,组件传入参数
    //以下是子组件
    Vue.component('todo-item', {    //组件要放在最前面不能放在new Vue后面
        template: ‘<li v-show=“num">This is a todo{{num}}------{{value1}}-----{{value2}}</li>’,   //子组件
        data:function () {  //传递参数,这里要使用function
           return {num:0}  //返回的也必须是对象
        },
        props:['value1','value2’]  //父组件要传值给子组件就必须在props里面声明变量
    })
    //以上是子组件
    
    var vm = new Vue({
      el: '#app’,
      data:{
        parentMsg:’字符串'
      }
    });
    
    <div id="app">
      <ol>
        //如果要获取到vue实例对象里面的数据就要使用v-bind,以下parentMsg就是vue实例对象中data的数据
        <todo-item value1="参数1" v-bind:value2="parentMsg"></todo-item>  //<--这个是父组件
      </ol>
    </div>
     2,动态参数
    其实就是v-model和参数结合
    <input type="text" v-model="parentMsg">
    <my-dir v-bind:value1="parentMsg"></my-dir>  //value1是子组件里面的props里的属性,parentMsg是vue实例化对象中data里的数据

    3,传递数据类型
    用v-bind 和 不用的区别

    <my-dir value1="1"></my-dir> //这时候传递的是字符串类型
    <my-dir v-bind:value1="1"></my-dir> //这时候传递的是数字类型
    
    <my-dir value1="[1,2]"></my-dir> //传递给模板的数据类型仅仅是字符串
    <my-dir :value1="[1,2]"></my-dir> //传给模板的数据类型是数组

    4,参数验证
    限制父组件参数传入的类型,或者自定义传入参数的验证方法 。这些主要组件给别人用时做的限制。

    例如:
    props:{
     value1: {
       type: Number,
       default: 100
     },
     value2:Number,
     value3:[String,Number],
     value4:{
       type:Boolean,
       required:true
     },
     value5:{
       type:Array,
       default:function(){
         return [];
       }
     },
     value6:{
       validator:function(value){ //自定义验证,value6=“11” 传入的值必须大于10
          return value>10
       }
     }
    }

    除了以上类型还有 Object 、Function

    案例:

    <my-dir value1=“1″></my-dir> //这样限制了value1传入的类型,必须是数字类型,如果组件没设置value1属性,那么默认出入值为100
    还有更多请参考api

    5,子组件传参数给父组件
    父组件可以通过props传参数给子组件,子组件可以通过以下方法做到,就必须使用自定义事件
    $on(eventName) 监听事件 //适用在不同组件之间传参使用
    $emit(eventName) 触发事件  //适用子组件传参给父组件。例如$emit(‘click’,data)该方法都写子组件中 ,这里的click是父组件中,data是子组件要传给父组件的数据

    $once只有触发一次

    直接看例子:

    <my-component @on_jia="get_num" v-on:on_jian="get_num"></my-component>
    <p>这里的str是vue实例化对象里面的数据:{{str}}</p>
    
    
    Vue.component('my-component',{
     template:'<div><button @click="jia(num)">+</button>-----<button @click="jian(num)">-</button></div>',
     data:function () {
         return {num:0}
     },
     methods:{
       jia:function (value) {
         value=value+1;
         this.num=value;
    
         this.$emit('on_jia',this.num);
       },
       jian:function (value) {
         value=value-1;
         this.num=value;
         this.$emit('on_jian',this.num);
       }
     }
    });
    
    
    
    var vm=new Vue({
     el:'#app',
     data:{
       str:0
     },
     methods:{
       get_num:function (value) {
          this.str=value;
       }
     }
    });

    最终效果:把组件里面的参数值传给了实例化对象

    过程:
    1,子组件里面通过 this.$emit(自定义方法,参数) 自定义一个方法,并把参数带进去。
    2,父组件通过v-on监听,子组件自定义的方法,并触发一个回调事件get_num,get_num负责把子组件参数获取过来。(中介作用)
    3,在vue实例化对象中,在methods里面同样声明一个get_num并获取到,父组件传过来的数据。

    $on使用

    <div id="xx">
         <div @click="haha()">s</div>
    </div>
    
    
    <script>
        // click事件->haha->$emit->$on->diyclick->geth
        new Vue({
            el:'#xx',
            data(){
                return{
                    a1:'初始数据'
                }
            },
            created(){
                //$on可以为一个自定义事件定义多个方法,遇到复杂的逻辑可以这样处理不需要都写在一起。
                //一个事件多个方法按上到下顺序执行
                this.$on('diyclick',this.geth);
                this.$on('diyclick',this.geth_1);
    
                //也可以在同一个函数上自定义多个自定义事件,打印看看this._events
                //this.$on(['diyclick_1','diyclick_2'],this.geth);
            },
            methods:{
                geth(e){
                    console.log(this.a1,e); //this.a1 是$on自己的数据,e是顺带了$emit的数据
                },
                geth_1(e){
                    console.log('这里是geth_1数据',e);
                },
                haha(){
                    this.$emit('diyclick','$emit自己的数据');
                }
            }
    
        })
    </script>

    6,不同组件之间的传参(非父子关系) 跨组件传参
    描述:两个组件,分别在不同的vue实例中,实现相互之间的传递参数,借助一个第三个空的vue实例和$emit、$on

    //创建/src/eventbus.js
    import Vue from 'vue'
    export default new Vue()
    
    
    //子组件1
    <button @click="fn">1</button>
    import Eventbus from '@/eventbus'
    export default {
      name: "test1",
      methods:{
        fn(){
          Eventbus.$emit('send',{a:1})  //发送参数
        }
      }
    }
    
    
    //子组件2
    import Eventbus from '@/eventbus'
    export default {
      name: "test2",
      mounted() {
        Eventbus.$on('send',(e)=>{
          console.log(e)  //接收到{a:1}
        })
      }
    }

     

    
    

    7,组件数据共享
    其实只要在全局环境中 声明一个对象,在组件的data里面引用即可

    var obj={num:0}
    data:function(){
     return obj
    }

    8,父组件传值给子组件里的计算属性

    <my-component :value="1"></my-component> //父组件 传一个 数字类型 值为1 给子组件
    
    Vue.component('my-component',{
     template:'<div>{{xx}}</div>’, //计算属性的结果给 模板
     props:['value'],
     computed:{ 
       xx:function () {
         return this.value+2; //获取父组件的参数 并 参数计算后在把结果传给模板
       }
     }
    });

    9,子组件直接获取,组件所在的vue实例对象里面的data数据

    <div id="app"> <xx></xx> </div>
    
    Vue.component('xx',{
      template:'<a> </a>',
      methods:{
          fn:function(){
               this.$parent.num   //num是实例对象里面的数据
          }
      }
    });
    
    
    new Vue({
       el:'#app',
       data:{
          num:0
       }
    });

    父组件直接获取子组件数据是用this.$children ,会遍历出所有的子组件

    10, new Vue实例对象直接获取子组件的data数据,可以在父组件上用ref=””,如下案例:

    <div id="app"> <xx ref="comA"></xx>  <a @click="fn"></a> </div>  //给组件取名字,方便快速定位
    
    Vue.component('xx',{
     template:'<a> </a>',
     data:function(){
        return {num:0}
     }
    });
    
    
    new Vue({
     el:'#app',
     methods:{
         fn:function(){
              this.$refs.comA.num  //num是子组件的数据
         } 
     }
    });

    *注意如果在父组件里的子节点使用ref是获取到dom元素,如:

    <xx ref="comA"> <span ref="comB">111</span>  </xx>
    
    this.$refs.comA.num  //num是子组件的数据,打印0
    this.$refs.comB //打印 dom元素 <span ref="comB">111</span>

    11,孙子获取爷爷数据,provide / inject

    //孙子组件
    var onecomponent={
      template:`<div> 345 </div>`,
      inject:[
         'yeye',
         //'data'
      ],
      mounted(){
         console.log( this.yeye.baba );
        //console.log( data.baba );
      }
    }
    
    
    //儿子组件
    var component_temp={
      template:`
        <div> <slot baba="baba22"></slot> <haha></haha> </div>
      `,
      data(){
        return{
          xx:'11'
        }
      },
      components:{
        haha:onecomponent //引入孙子组件
      },
      props:['value1']
    }
    
    
    new Vue({
      el:'#root',
      provide:function(){
    
        //这里代码,防止低版本的vue,孙子在获取爷爷数据时候,没有双向数据绑定效果而写的
            // var data={}
            // var _this=this;
            // Object.defineProperty(data,'baba',{
            //     get:function () {
            //         return _this.baba
            //     },
            //     enumerable:true
            // })
        return{
         yeye:this,
         // data:data
        }
      },
      components:{
         com:component_temp
      },
      template:'<com ref="x"> <p slot-scope="diy">{{diy.baba}}</p> </com>', //爷爷组件
      data:{
        baba:'baba11' //孙子要获取爷爷的数据
      }
    });

    父子组件方法调用

    vue 父调用子方法

    子:

    mounted(){
      this.$on('bridge',(val)=>{
        this.childAction(val);
      });
      ///此时通过$on进行监听中间桥接函数bridge对目的方法childAction进行触发
    },
    methods:{
      childAction(val='hello world'){
        console.log(val) //得到爸爸传来的数据
      }
    }

    父:

    <Category ref="category"></Category>
    
    <el-button @click="addcate()">修改分类</el-button>
    addcate(){
      this.$refs.category.$emit('bridge','这里是要给儿子的数据');
    }

    子调用父亲

    (1)通过this.$parent.event来调用父组件的方法

    父组件

    methods: {
     fatherMethod() {
       console.log('测试');
     }
    }

    子组件

    mounted() {
      this.$parent.fatherMethod();
    }

    (2)子组件里用$emit

    父组件

    <child @fatherMethod="fatherMethod"></child>
    
    methods: {
       fatherMethod() {
         console.log('测试');
       }
    }

    子组件

    this.$emit('fatherMethod'); //调用

    (3)父组件把方法传入子组件中,在子组件里直接调用这个方法

    父组件

    <child :fatherMethod="fatherMethod"></child>
    methods: {
          fatherMethod() {
            console.log('测试');
          }
    }

    子组件

    props: {
     fatherMethod: {
       type: Function,
       default: null
     }
    },
    mounted(){
      if (this.fatherMethod) {
          this.fatherMethod();
      }
    }

    动态组件 (类似选项卡)

    需要特殊<component v-bind:is=”str”></component>

    其实也就是多个组件项目切换 显示

    <div id="app">
       <a @click="fn('comA')"></a>
       <a @click="fn('comB')"></a>
       <component v-bind:is="str"></component>  //str显示哪个组件名就显示那个组件
    </div>
    
    
    
    var vm=new Vue({
      el:'#app',
      data:{
         str:'comA'
      },
      methods:{
          fn:function(value){
              this.str=value;
          }
      },
      components:{
         'comA':{
              template:'<a>1</a>'
         },
         'comB':{
              template:'<a>2</a>'
         }
      }
    });
    缓存
    避免组件切换回来又重新渲染,可以使用keep-alive在外包一层,更多功能http://cn.vuejs.org/v2/api/#keep-alive
    <keep-alive>
       <component :is="currentView">
          <!-- 非活动组件将被缓存! -->
       </component>
    </keep-alive>

    异步组件

    有些组件可能要从别的地方获取数据后才显示出来,这时候肯定考虑异步

    <div id="app">
        <com ref="haha"></com>
        <button @click="fn">点我</button>
        <p>{{str}}<p>
    </div>
    var vm=new Vue({
     el:'#app',
     data:{
       str:''
     },
     methods:{
       fn:function(value){
         this.str=this.$refs.haha.num;
       }
     },
     components:{
       'com':function (a,b) {
    
            $.ajax({
               url:'http://localhost/test_duble_data.html',
               success:function () {
                 a({
                    template:'<div>xx</div>',
                    data:function(){
                       return {num:'子组件传来的数据'}
                    }
                 });
               }
            });
    
        }
     }
    });

    强制更新,实现数据双向绑定效果

    html:

    <div id="root">
      <div>{{text}}--{{obj.a}}</div> //正常来说如果要在模板中使用obj.a,那么在vue实例中就要预先声明obj中的a变量即使是空值也好。
    </div>
    var app=new Vue({
      el:'#root',
      // template:'<div>{{text}}--{{obj.a}}</div>',
      data:{
        text:0,
        obj:{} //但是在obj中并没有预先声明a变量,就算在后面临时赋值obj.a=xxx,在模板中调用也不会有值显示。
      }
     });
    
     var i=0;
     setInterval(()=>{
       i++;
       app.obj.a=i; //临时给a赋值
       app.$forceUpdate(); //如果要为临时设置的也实现双向绑定就要强制更新组件。(不太推荐)
       //如果没有临时预设属性,又不想使用强制更新,可以使用app.$set(app.obj,'a',i),作用是临时补上a属性到data中
     },1000)

    DOM回调函数

    按理来说我们使用vue是不需要操作dom的,但是偏偏可能我们在做一些动画效果时,就是要需要等dom加载完成后才去执行

    <div id="app">
       <div id="haha" v-if="num">数据</div>
       <button @click="fn">点我</button>
    </div>
    
    var vm=new Vue({
      el:'#app',
      data:{
         num:false
      },
      methods:{
         fn:function(){
              this.num=true;
              this.$nextTick(function(){ //等待#app容器下的dom加载完成后才执行以下代码
                  
                  $('#haha').text();
              });
         }
      }
    });
    
    
    

    slot内容分发  (插槽)

    把这个理解为父组件往子组件传值的另一种方法就行。

    或者理解为,在父组件里面写的html想要在子组件渲染出来就需要到slot

    //在父组件的<my-component></my-component>标签里面加内容
    <div id="app">
      <my-component> //这个是父组件,以下内包裹的就是要传给子组件的内容
        <p slot="header">头部1</p>
        <p slot="header">头部2</p>
        <p>主体内容1</p>
        <p>主体内容2</p>
        <p slot="foot">底部1</p>
      </my-component>
    </div>
    
      
    
    <script>
    //要显示出父组件加的内容就需要到slot标签
    Vue.component('my-component',{
      template:'<div> ' +
                '<slot name="header"></slot> ' +
                '<slot></slot> ' +
                '<slot name="foot"></slot> ' +
                '<slot name="foot2">父组件没传值就默认显示我</slot> ' +
               '</div>'
      });
    
    
    
     new Vue({
      el:'#app'
     });
    
    </script>
    
    
    
    //渲染效果
    <div id="app">
      <div>
        <p>头部1</p>
        <p>头部2</p> 
        <p>主体内容1</p> 
        <p>主体内容2</p> 
        <p>底部1</p> 
        父组件没传值就默认显示我
      </div>
    </div>
    
    
    

    1,父组件my-component包裹着内容就是要传给子组件的
    2,子组件要接收父组件传来的值就要使用<slot></slot>
    3, 子组件的<slot name=”xx”>使用name就只能指定接收父组件的<dom slot=”xx”></dom>
    父组件可以使用多次<dom slot=”xx”></dom>,子组件也可以接收多个,只要一一对应
    4,如果子组件有<slot name=”xx”>设置默认值</slot>,而父组件没有传值来,子组件可以显示默认值
    5,只要子组件没有为slot设置name的,父组件的其他内容就默认替换

    slot传参 (作用域插槽)

    slot结合template使用,子组件传参给父组件,在子组件的slot标签上自定义参数,父组件接收参数时使用scope=””

    <my-component>
      <template slot="xx" scope="xxx">
         <p>123</p>
         <p>{{xxx.msg0}}</p>
         <p>{{xxx.msg1}}</p>
      </template>
    </my-component>
    
    
    
    <script>
    
    Vue.component('my-component',{
      template:'<div> <slot name="xx" :msg1="str" msg0="内容123"></slot> </div>',
      data:function () {
        return {str:'子组件内容'}
      }
    });
    
    
    new Vue({
     el:'#app'
    });
    
    </script>
    //渲染效果
    <div id="app">
      <div>
         <p>123</p> 
         <p>内容123</p> 
         <p>子组件内容</p>
      </div>
    </div>

    如果slot没有结合使用<template>时,子组件传参给父组件时,父组件接收参数要使用slot-scope=””

    //子组件
    template:`
    <div> <slot baba="baba22"></slot> </div>
    `
    
    //父组件
    template:'<com> <p slot-scope="diy">{{diy.baba}}</p>  </com>',  //父组件接收参数要用slot-scope

    $slots

    可以利用$slots来获取到父组件传来的slot具名,例如可以获取到父组件传来的dom元素

    <my-component>
      <p id="nimei" slot="xx">xxx</p>
    </my-component>
    
    Vue.component('my-component',{
      template:'<div> <slot name="xx" :msg1="str" msg0="内容123"></slot> </div>',
      data:function () {
         return {str:'子组件内容'}
      },
      mounted:function () {
        document.title=(this.$slots.xx)[0].elm.id  //获取到父传来的slot="xx"的dom元素,也就是id="nimei"的p元素
      }
    });

    内联模板

    之前介绍slot,在父组件包裹里面写数据就默认相当于参数要传给子组件,
    我们也可以不在子组件里的template里面写div,可以直接把父组件里面的
    数据当做模板。

    <div id="app">
     <my-component inline-template> //inline-template告诉父组件,里面内容是当成模板使用,而不是当成slot内容分发给子组件
       <div> //跟子组件的template一样写模版最外层同样也要包裹着一个div容器不然没效果
         <p>父组件里面的内容就相当于模板了</p>
         <p>{{msg}}</p>
         <p>{{message}}</p>
         <p>{{aa}}</p> //这里优先使用子组件的数据
       </div>
     </my-component>
    </div>
    
    
    <script>
    
    Vue.component('my-component',{
     data:function () {
       return {msg:'子组件',aa:'子组件的aa'}
     }
    });
    
    new Vue({
      el:'#app',
      data:{
        message:'父组件',
        aa:'父组件的aa'
      }
    });
    
    </script>

    动态生成vue实例
    vue实例都是我们最开始使用new Vue()来实现了,但有时候我们也需要动态是生成。

    <div id="app">
      <button @click="fn()">动态挂载vue对象</button>
    
      <div id="app2">
    
      </div>
    </div>
    
    
    
    <script>
    
    var myvue=Vue.extend({
      template:'<div><input type="text" v-model="haha"><p>{{haha}}</p></div>',
      data:function () {
          return {haha:''}
      }
    })
    
    
    new Vue({
     el:'#app',
     data:{
     message:'父组件',
        aa:'父组件的aa'
     },
     methods:{
       fn:function () {
         new myvue().$mount('#app2');
       }
     }
    });
    </script>

    自定义指令

    <div id="app">
     <input type="text" v-focus="{haha:'笑哈哈'}">
    </div>
    
    <script>
        //以下是全局
        Vue.directive('focus',{
            bind:{},
        });
    
    
        //以下是局部 自定义指令
        new Vue({
            el:'#app',
            directives:{
                focus:{
                    bind:function (el,binding) {  //仅仅执行一次,作用就是为绑定的元素,添加初始化值。
                        el.value=1
                        el.className='nihao';
                        el.addEventListener('click',function () {
                            console.log('绑定');
                        });
                        console.log(el);  //笑哈哈
                        el.xx=123;  //要想其他钩子函数都能调用到,就把要公用的属性和方法都写在el中
                    },
                    inserted:function (el,binding) {  //dom加载完成后,就调用
                        el.focus();
                        console.log(el.xx);  //123
                    },
                    update:function (el,binding,vnode,oldVnode) {
    
                    },
                    componentUpdated:function (el,binding,vnode,oldVnode) {
    
                    },
                    unbind:function (el,binding) {
    
                    }
                }
            }
        });
    
    </script>

    render函数   虚拟dom   vue创建html

    template:'<div ref="x"></div>' //template里面的html,最终还是靠render函数显示到页面上的
    等价
    render(createElement){
            return createElement('div',{
                ref:'x'
            });
    },

    具体更多用法参考:https://cn.vuejs.org/v2/guide/render-function.html

    **注意:能用template创建html就尽量用,否则使用render创建html会增加难度。

    使用场景是:当模板出现重复性比较高时可以考虑使用,例如:

    <script type="text/x-template" id="xx"> 
      <div>      
        <h1 v-if="show">       
          <a></a>      
        </h1>
    
        <h2 v-if="show">       
          <a></a>      
        </h2>
    
         <h3 v-if="show">       
          <a></a>      
         </h3>
    
         <h4 v-if="show">       
          <a></a>      
         </h4> 
      </div>
    </script>

    如果出现类似以上的重复性出现的dom就考虑使用虚拟dom进行遍历了。

    对比学习效率会比较高

    template:'\
             <div id="ele"> \
               :class="show:show" \
               @click="fn">内容</div>'
    
    比较
    
    render:function(createElement){
       return createElement(
                 'div',
                 {
                   class:{'show':this.show}
                   attrs:{id:'ele'},
                   on:{click:this.fn}
                 },
                 '内容'
              )
       }

    可读性明显template比render好,所以要看情况使用虚拟dom不然会带来不便。

    上面的案例都知道传进来的createElement参数才是最关键的,而这个参数是一个函数,
    函数里面又有3个参数

    createElement(
      {string|object|function}, //必选 (根据逻辑判断生成不同的dom元素标签)
      {object}, //可选 (数据填充,第二个参数玩法很多)
      {string|array} //可选 (子节点)
    )

  • 常用正则

     

    数字 2位小数
    <input type="text" name="amount" id="amount">
    
    $('#amount').keyup(function () { 
    
       if (parseFloat($(this).val()) > parseFloat($('#in_moneys').text())) {  //限制输入大小
          $(this).val(parseFloat($('#in_moneys').text()));
          return;
       }
    
       if ($(this).val().indexOf(".") != -1) {
          var str_ = $(this).val().substr($(this).val().indexOf(".") + 1);
    
          if($(this).val().split('.')[1].length>2){ //只能保留2位小数,输入数字类型
             $(this).val( (Math.floor( parseFloat($(this).val())*100 )/100).toString().replace(/[^\d\.]/g, '') )
          }
    
          //限制只能输入一个小数点
          if (str_.indexOf(".") != -1) {
            $(this).val($(this).val().substr(0, $(this).val().indexOf(".") + str_.indexOf(".") + 1));
          }
       } else {
          //只能输入数字类型
          $(this).val( $(this).val().replace(/[^\d\.]/g, '') )
       }
    });

     

     

    一、校验数字的表达式

    数字:^[0-9]*$
    
    n位的数字:^\d{n}$
    
    至少n位的数字:^\d{n,}$
    
    m-n位的数字:^\d{m,n}$
    
    零和非零开头的数字:^(0|[1-9][0-9]*)$
    
    非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
    
    匹配小数点大于2位的字符串 /^\d+(\.\d{3,})$/ig
    
    小数点是1位或者2位,或者没有 /^\d+(\.\d{1,2})*$/ig
    
    带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$
    
    正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$
    
    有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
    
    有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
    
    非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
    
    非零的负整数:^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$
    
    非负整数:^\d+$ 或 ^[1-9]\d*|0$
    
    非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
    
    非负浮点数:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
    
    非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
    
    正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
    
    负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
    
    浮点数:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$

     

     

    二、校验字符的表达式

    汉字:^[\u4e00-\u9fa5]{0,}$
    
    英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
    
    长度为3-20的所有字符:^.{3,20}$
    
    由26个英文字母组成的字符串:^[A-Za-z]+$
    
    由26个大写英文字母组成的字符串:^[A-Z]+$
    
    由26个小写英文字母组成的字符串:^[a-z]+$
    
    由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
    
    由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$
    
    中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
    
    中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
    
    可以输入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+ 12 禁止输入含有~的字符:[^~\x22]+

     

     

    三、特殊需求表达式

    Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
    
    域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
    
    InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
    
    手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
    
    电话号码(“XXX-XXXXXXX”、”XXXX-XXXXXXXX”、”XXX-XXXXXXX”、”XXX-XXXXXXXX”、”XXXXXXX”和”XXXXXXXX):^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$
    
    国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
    
    身份证号(15位、18位数字):^\d{15}|\d{18}$
    
    短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
    
    帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
    
    密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
    
    强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
    
    日期格式:^\d{4}-\d{1,2}-\d{1,2}
    
    一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
    
    一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$
    
    钱的输入格式:
    
    1.有四种钱的表示形式我们可以接受:”10000.00” 和 “10,000.00”, 和没有 “分” 的 “10000” 和 “10,000”:^[1-9][0-9]*$
    
    2.这表示任意一个不以0开头的数字,但是,这也意味着一个字符”0”不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$
    
    3.一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$
    
    4.这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧.下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$
    
    5.必须说明的是,小数点后面至少应该有1位数,所以”10.”是不通过的,但是 “10” 和 “10.2” 是通过的:^[0-9]+(.[0-9]{2})?$
    
    6.这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$
    
    7.这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$
    
    23 8.1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$
    
    备注:这就是最终结果了,别忘了”+”可以用”*”替代如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里
    
    xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
    
    中文字符的正则表达式:[\u4e00-\u9fa5]
    
    双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))
    
    空白行的正则表达式:\n\s*\r (可以用来删除空白行)
    
    HTML标记的正则表达式:<(\S*?)[^>]*>.*?</\1>|<.*? /> (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力)
    
    首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
    
    腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)
    
    中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)
    
    IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址时有用)
    
    IP地址:((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))

     

     

    四,关于过滤html

    js html标签转化过滤

     

    http://www.cnblogs.com/zxin/archive/2013/01/26/2877765.html

    https://mp.weixin.qq.com/s/rwQZz5Dti5MRsnrCVxyH4w

     

     

    ——————————————————
    //////////////////////更多//////////////////
    ——————————————————
    匹配中文字符的正则表达式: [u4e00-u9fa5]

    评注:匹配中文还真是个头疼的事,有了这个表达式就好办了

    匹配双字节字符(包括汉字在内):[^x00-xff]

    评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)

    匹配空白行的正则表达式:ns*r

    评注:可以用来删除空白行

    匹配HTML标记的正则表达式:< (S*?)[^>]*>.*?|< .*? />

    评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力

    匹配首尾空白字符的正则表达式:^s*|s*$

    评注:可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式

    匹配Email地址的正则表达式:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*

    评注:表单验证时很实用

    匹配网址URL的正则表达式:[a-zA-z]+://[^s]*

    评注:网上流传的版本功能很有限,上面这个基本可以满足需求

    匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$

    评注:表单验证时很实用

    匹配国内电话号码:d{3}-d{8}|d{4}-d{7}

    评注:匹配形式如 0511-4405222 或 021-87888822

    匹配腾讯QQ号:[1-9][0-9]{4,}

    评注:腾讯QQ号从10000开始

    匹配中国邮政编码:[1-9]d{5}(?!d)

    评注:中国邮政编码为6位数字

    匹配身份证:d{15}|d{18}

    评注:中国的身份证为15位或18位

    匹配ip地址:d+.d+.d+.d+

    评注:提取ip地址时有用

    匹配特定数字:

    ^[1-9]d*$ //匹配正整数

    ^-[1-9]d*$ //匹配负整数

    ^-?[1-9]d*$ //匹配整数

    ^[1-9]d*|0$ //匹配非负整数(正整数 + 0)

    ^-[1-9]d*|0$ //匹配非正整数(负整数 + 0)

    ^[1-9]d*.d*|0.d*[1-9]d*$ //匹配正浮点数

    ^-([1-9]d*.d*|0.d*[1-9]d*)$ //匹配负浮点数

    ^-?([1-9]d*.d*|0.d*[1-9]d*|0?.0+|0)$ //匹配浮点数

    ^[1-9]d*.d*|0.d*[1-9]d*|0?.0+|0$ //匹配非负浮点数(正浮点数 + 0)

    ^(-([1-9]d*.d*|0.d*[1-9]d*))|0?.0+|0$ //匹配非正浮点数(负浮点数 + 0)

    评注:处理大量数据时有用,具体应用时注意修正

    匹配特定字符串:

    ^[A-Za-z]+$ //匹配由26个英文字母组成的字符串

    ^[A-Z]+$ //匹配由26个英文字母的大写组成的字符串

    ^[a-z]+$ //匹配由26个英文字母的小写组成的字符串

    ^[A-Za-z0-9]+$ //匹配由数字和26个英文字母组成的字符串

    ^w+$ //匹配由数字、26个英文字母或者下划线组成的字符串

    在使用RegularExpressionValidator验证控件时的验证功能及其验证表达式介绍如下:

    只能输入数字:“^[0-9]*$”

    只能输入n位的数字:“^d{n}$”

    只能输入至少n位数字:“^d{n,}$”

    只能输入m-n位的数字:“^d{m,n}$”

    只能输入零和非零开头的数字:“^(0|[1-9][0-9]*)$”

    只能输入有两位小数的正实数:“^[0-9]+(.[0-9]{2})?$”

    只能输入有1-3位小数的正实数:“^[0-9]+(.[0-9]{1,3})?$”

    只能输入非零的正整数:“^+?[1-9][0-9]*$”

    只能输入非零的负整数:“^-[1-9][0-9]*$”

    只能输入长度为3的字符:“^.{3}$”

    只能输入由26个英文字母组成的字符串:“^[A-Za-z]+$”

    只能输入由26个大写英文字母组成的字符串:“^[A-Z]+$”

    只能输入由26个小写英文字母组成的字符串:“^[a-z]+$”

    只能输入由数字和26个英文字母组成的字符串:“^[A-Za-z0-9]+$”

    只能输入由数字、26个英文字母或者下划线组成的字符串:“^w+$”

    验证用户密码:“^[a-zA-Z]w{5,17}$”正确格式为:以字母开头,长度在6-18之间,

    只能包含字符、数字和下划线。

    验证是否含有^%&’,;=?$”等字符:“[^%&’,;=?$x22]+”

    只能输入汉字:“^[u4e00-u9fa5],{0,}$”

    验证Email地址:“^w+[-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*$”

    验证InternetURL:“^http://([w-]+.)+[w-]+(/[w-./?%&=]*)?$”

    验证电话号码:“^((d{3,4})|d{3,4}-)?d{7,8}$”

    正确格式为:“XXXX-XXXXXXX”,“XXXX-XXXXXXXX”,“XXX-XXXXXXX”,

    “XXX-XXXXXXXX”,“XXXXXXX”,“XXXXXXXX”。

    验证身份证号(15位或18位数字):“^d{15}|d{}18$”

    验证一年的12个月:“^(0?[1-9]|1[0-2])$”正确格式为:“01”-“09”和“1”“12”

    验证一个月的31天:“^((0?[1-9])|((1|2)[0-9])|30|31)$”

    正确格式为:“01”“09”和“1”“31”。

    匹配中文字符的正则表达式: [u4e00-u9fa5]

    匹配双字节字符(包括汉字在内):[^x00-xff]

    匹配空行的正则表达式:n[s| ]*r

    匹配HTML标记的正则表达式:/< (.*)>.*|< (.*) />/

    匹配首尾空格的正则表达式:(^s*)|(s*$)

    匹配Email地址的正则表达式:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*

    匹配网址URL的正则表达式:http://([w-]+.)+[w-]+(/[w- ./?%&=]*)?

    1. 校验基本日期格式

    1. var reg1 = /^\d{4}(\-|\/|\.)\d{1,2}\1\d{1,2}$/;
    2. var reg2 = /^(^(\d{4}|\d{2})(\-|\/|\.)\d{1,2}\3\d{1,2}$)|(^\d{4}年\d{1,2}月\d{1,2}日$)$/;

    2. 校验密码强度

    密码的强度必须是包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间。

    1. var reg = /^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$/;

    3. 校验中文

    字符串仅能是中文。

    1. var reg = /^[\\u4e00-\\u9fa5]{0,}$/;

    4. 由数字、26个英文字母或下划线组成的字符串

    1. var reg = /^\\w+$/;

    5. 校验E-Mail 地址

    同密码一样,下面是E-mail地址合规性的正则检查语句。

    1. var reg = /[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?/;

    6. 校验身份证号码

    下面是身份证号码的正则校验。15 或 18位。

    15位:

    1. var reg = /^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$/;

    18位:

    1. var reg = /^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([0-9]|X)$/;

    7. 校验日期

    “yyyy-mm-dd” 格式的日期校验,已考虑平闰年。

    1. var reg = /^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$/;

    8. 校验金额

    金额校验,精确到2位小数。

    1. var reg = /^[0-9]+(.[0-9]{2})?$/;

    9. 校验手机号

    下面是国内 13、15、18开头的手机号正则表达式。(可根据目前国内收集号扩展前两位开头号码)

    1. var reg = /^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\\d{8}$/;

    10. 判断IE的版本

    IE目前还没被完全取代,很多页面还是需要做版本兼容,下面是IE版本检查的表达式。

    1. var reg = /^.*MSIE [5-8](?:\\.[0-9]+)?(?!.*Trident\\\/[5-9]\\.0).*$/;

    11. 校验IP-v4地址

    1. var reg = /\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b/;

    12. 校验IP-v6地址

    1. var reg = /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/;

    13. 检查URL的前缀

    应用开发中很多时候需要区分请求是HTTPS还是HTTP,通过下面的表达式可以取出一个url的前缀然后再逻辑判断。

    1. if (!s.match(/^[a-zA-Z]+:\/\//)) {
    2.    s = 'http://' + s;
    3. }

    14. 提取URL链接

    下面的这个表达式可以筛选出一段文本中的URL。

    1. var reg = /^(f|ht){1}(tp|tps):\/\/([\w-]+\.)+[\w-]+(\/[\w- ./?%&=]*)?/;

    15. 文件路径及扩展名校验

    验证 windows下文件路径和扩展名(下面的例子中为.txt文件)

    1. var reg = /^([a-zA-Z]\\:|\\\\)\\\\([^\\]+\\)*[^\\/:*?"<>|]+\\.txt(l)?$/;

    16. 提取Color Hex Codes

    有时需要抽取网页中的颜色代码,可以使用下面的表达式。

    1. var reg = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;

    17. 提取网页图片

    假若你想提取网页中所有图片信息,可以利用下面的表达式。

    1. var reg = /\\< *[img][^\\>]*[src] *= *[\\"\']{0,1}([^\\"\'\ >]*)/;

    18. 提取页面超链接

    提取html中的超链接。

    1. var reg = /(<a\\s*(?!.*\\brel=)[^>]*)(href="https?:\/\/)((?!(?:(?:www\\.)?'.implode('|(?:www\\.)?', $follow_list).'))[^"]+)"((?!.*\\brel=)[^>]*)(?:[^>]*)>/;

    19. 查找CSS属性

    通过下面的表达式,可以搜索到相匹配的CSS属性。

    1. var reg = /^\\s*[a-zA-Z\\-]+\\s*[:]{1}\\s[a-zA-Z0-9\\s.#]+[;]{1}/;

    20. 抽取注释

    如果你需要移除HMTL中的注释,可以使用如下的表达式。

    1. var reg = /<!--(.*?)-->/;

     

    https://segmentfault.com/a/1190000012806098

    https://mp.weixin.qq.com/s/TsiTKSZCzo4O8rBznvpkcA

  • windows安装nvm

    推荐直接装:nvm-setup

     

    安装完之后设置:

    nvm node_mirror https://npm.taobao.org/mirrors/node/
    nvm npm_mirror  https://npm.taobao.org/mirrors/npm/
    
    nvm list available //列出所有可安装的版本,推荐安装LTS稳定版
    nvm install 12.16.3 //例如安装此版本
    nvm list //查看已经安装的版本
    nvm use 12.16.3 //使用该版本
    node -v //最后看看是否安装成功

     

    更多详细信息:

    nvm arch 查看当前系统的位数和当前nodejs的位数
    nvm install <version> [arch] 安装制定版本的node 并且可以指定平台 version 版本号 arch 平台
    nvm list [available] 
    - nvm list 查看已经安装的版本
    - nvm list installed 查看已经安装的版本
    - nvm list available 查看网络可以安装的版本
    nvm on 打开nodejs版本控制
    nvm off 关闭nodejs版本控制
    nvm proxy [url] 查看和设置代理
    nvm node_mirror [url] 设置或者查看setting.txt中的node_mirror,如果不设置的默认是 https://nodejs.org/dist/
    nvm npm_mirror [url] 设置或者查看setting.txt中的npm_mirror,如果不设置的话默认的是:https://github.com/npm/npm/archive/.
    nvm uninstall <version> 卸载制定的版本
    nvm use [version] [arch] 切换制定的node版本和位数
    nvm root [path] 设置和查看root路径
    nvm version 查看当前的版本

     

     

    —————————————分割线—————————————————-

    1,下载nvm包

    下载 nvm 包 地址:https://github.com/coreybutler/nvm-windows/releases,我们选择第一个:nvm-noinstall.zip

    nvm-noinstall

    解压后把里面所有文件放入到C:\dev\nvm目录中后双击install.cmd

     

    2,

    双击 install.cmd 然后会让你输入”压缩文件解压或拷贝到的一个绝对路径” 先不用管它,直接回车。

    将C盘生成的settings.txt放入到C:\dev\nvm目录中,然后我们把它的内容修改成这样:

    root: C:\dev\nvm 
    path: C:\dev\nodejs 
    arch: 64 
    proxy: none 
    node_mirror: http://npm.taobao.org/mirrors/node/ 
    npm_mirror: https://npm.taobao.org/mirrors/npm/

     

     

    3,配置环境变量

    在“系统环境变量中”会生成两个环境变量:NVM_HOME 和 NVM_SYMLINK,它们的值分别改为:

    NVM_HOME的变量值为:C:\dev\nvm; 
    NVM_SYMLINK的变量值为:C:\dev\nodejs
    (如果在Path中也会自动添加上C:\dev\nvm;或者是C:\dev\nodejs,把他们删掉)

    接着在Path的最前面输入:

    ;%NVM_HOME%;%NVM_SYMLINK%;

     

     

    4,测试是否安装nvm成功

    输入:

    nvm v   //有版本号说明成功

     

     

    5,nvm安装node.js

    nvm install latest   //安装最新版本
    nvm install 8.9.0    //安装指定版本

    安装成功后使用

    nvm use 8.9.0   //切换使用
    node -v  //有版本号输出 说明安装成功

     

  • git笔记

    git

    以下是本人常用的git命令,git有一个不明文的规定要为第一次使用git的人介绍一下,

    master:分支是正式上线的分支,git默认自动创建。一般我们改代码是不会在此地方改的。

    develop/dev:这个分支需要手动创建,一般项目都会取这个名字,这个是即将和master合并上线的分支,也就是把其他人在各自的分支下完成不同的功能统一合并到develop/dev时。我们也不会在此分支上直接修改代码。

    自定义分支:这个具体看团队的要求,例如有些团队要求是这样:zhaosan/images_upload,一眼就看出是张三的人正在开发一个图片上传的功能。

    //查看当前项目状态看看有没有修改或者冲突的
    git status
    
    1,nothing to commit, working tree clean
    代码没有修改和冲突
    
    
    2,
    modified //代码有过修改
    both //代码有冲突
    deleted by them: www-v2/common.css  //服务器上没有这个文件,你本地却有
    
    
    有冲突代码一般都会有这样符号
    <<<<<<< HEAD
    我的代码
    ======= 
    合并过来别人的代码
    >>>>>>> feature1
    
    
    解决完冲突后,再次检查是否有遗漏的
    git diff --check
    
    //以下提交代码流程
    git add .
    git commit -m "注释" 
    git pull
    git status
    git push
    git push -f  //强制更新。例如回归到2018.1.1的分支,强制更新后。在1.1之后的修改服务器上全没了。谨用!
    
    
    //查看增、删了哪些代码
    git diff resources/views/www-v2/home/index.blade.php
    
    
    //查看本地分支
    git branch
    
    //查看本地和远程
    git branch -a (之前需要git pull 更新)
    
    //强制更新不管对错
    git add . && git commit --no-verify -m "代码规范强制提交测试"
    
    //创建一个分支
    git branch xx (在此之前最好git branch一下看看分支命名有没有什么规则,按规则来)
    git checkout -b xx  //git branch xx  且  git checkout xx ,新建并切换xx分支
    
    //提交新分支
    1,先切换到刚刚创建的分支git checkout feature/ceshi
    2,git push (一般会有提示)
    3,git push --set-upstream origin feature/ceshi
    之后新分支就提交到了服务器上了
    
    合并,希望基于develop与当前分支合并。
    1,先git checkout develop切换到develop分支
    2,git pull更新一下develop分支
    3,git checkout feature/ceshi切回当前分支
    4,git merge develop ,当前分支和develop分支合并
    5,git status 看看有没有异常
    
    
    版本退回
    git reflog //先查看已经commit的版本获取到commit id
    git reset --hard 3628164

    让git忽略文件

    在根目录下新建.gitignore,以下内容均被git忽略不提交。

    .svn/
    .settings/
    *.project
    target
    rebel.xml
    hsf.lock
    
    HELP.md
    target/
    !.mvn/wrapper/maven-wrapper.jar
    !**/src/main/**/target/
    !**/src/test/**/target/
    
    /vendor
    /node_modules
    .env
    
    ### STS ###
    .apt_generated
    .classpath
    .factorypath
    .project
    .settings
    .springBeans
    .sts4-cache
    
    ### IntelliJ IDEA ###
    .idea
    *.iws
    *.iml
    *.ipr
    
    ### NetBeans ###
    /nbproject/private/
    /nbbuild/
    /dist/
    /nbdist/
    /.nb-gradle/
    build/
    !**/src/main/**/build/
    !**/src/test/**/build/
    
    ### VS Code ###
    .vscode/

     

    本地修改文件忽略其修改内容让git status跟踪不到

    方法一:

    git update-index --assume-unchanged "/root/dev.yml" //git关闭跟踪文件修改提交
    git update-index --no-assume-unchanged "/root/dev.yml"//git打开跟踪文件修改提交
    
    git ls-files -v | grep "^h" //查看哪些文件被忽略

     

    方法二:

    编辑.git/info/exclude文件

    # 忽略特定的文件
    my_password.txt
    config/local_config.json
    
    # 忽略整个文件夹(记得加斜杠)
    temp_logs/
    bin/
    
    # 忽略所有 .mp4 结尾的文件
    *.mp4
    
    # 但不忽略特定的某个 .mp4 文件
    !important_guide.mp4

     

     

    方法三:

    刚刚下载的项目git一般都还不会跟踪新加的文件,直接去.gitignore里面追加忽略的文件即可。

    查看文件是否被跟踪使用git ls-files,如果你想忽略的文件有在里面,还在.gitignore追加是没效果的,

    在跟踪列表中删除文件如:

    git rm --cached .nvmdrc  //在项目跟目录删除跟踪的.nvmdrc文件
    git rm --cached subdir/.nvmdrc  //如果是在目录subdir里面删除跟踪的.nvmdrc文件
    然后在把.nvmdrc文件追加到.gitignore
    测试下修改.nvmdrc文件git status能否还被跟踪

     

    如果文件曾经被 Git 跟踪,但已经被删除,Git 仍然会保留其记录。你可以通过以下命令清理 Git 的缓存:

    git rm --cached -r .
    git add .

     

     

    基本案例

    //初始化一个空白仓库
    git init 
    
    git config user.name "作者昵称"
    git config user.email "chenge@chinaesport.com"
    //给本地仓库设置一个远程上传、下载地址值是git@xxx.git,赋值到一个变量名为origin,(默认都是origin不推荐乱取名)
    git remote add origin git@gitee.com:chen77134056/vuelic3.git  
    
    //将本地代码提交上远程服务并关联分支,本地和远程分支都是master名字
    git push --set-upstream origin master
    
    
    //通过设置好的远程仓库,下载远程仓库的内容,但是这个命令不会帮我们合并代码
    git fetch
    
    //将本地分支master与远程仓库分支关联到一起,这样才能git push(推荐本地分支取名和远程分支取名一样)
    git branch master origin/master
    
    //现在切换master分支
    git checkout master
    
    //下载远程仓库的内容,会把我们自己代码和远程代码合并在一起
    git pull

    分布式版本控制系统

    好处:
    1,记录每次改动时间
    2,多人协作同一个项目
    3,可以恢复指定某一个时间点的文件
    4,自己电脑永远是最新,修改时直接改,不需要从类似中央服务器先更新在改
    5,强大分支管理(远远把svn抛在后面)

    历史:
    git是linux的创始人写的

    比较:
    svn和git比较
    svn需要类似中央服务器,要在自己电脑修改时,先从中央服务器更新才能修改,
    所以前提是需要联网后才能继续工作。

    git不需要联网就能工作,不需要中央服务器,自己本机上的文件最新的,断网可以继续工作。
    多个用户修改同一个文件,只需要把自己修改的部分推送给对方即可,这样每个人电脑又都是最新的了。

    安全性:
    git没有中央服务器就不怕黑客攻击,就算某个用户被黑了,代码可以在从其他人电脑获取最新的。

    弥补不足:
    之前说了要保证大家的文件保持最新的就要大家同时在线推送自己修改的部分给其他人,在实际中不现实
    为了方便大家推送自己修改的部分给其他人,还是需要一个“中央服务器”,这里的“中央服务器”
    仅仅是方便大家交换自己修改的部分而已,没它我们可以照样工作。

    开始教程:
    (声明图片、视频、Microsoft的Word格式, git只能知道变化大小,不知道具体改变了什么)
    注意:不要使用Windows自带的记事本编辑任何文本文件。

    创建版本库又名仓库:
    git init

    增:
    git add file1.txt //提交单个
    git add file2.txt file3.txt //提交多个
    git status //最后查看有什么修改又漏了add提交的
    git commit -m “写点有意义的注释” //一次性提交之前add的文件到仓库,如果修改文件后没add,就算commit也不会提交成功的

    git branch xx //创建一个xx分支

    git merge xx //将xx分支和当前分支合并 (将当前分支的代码和xx分支的代码合并)
    git merge –no-ff -m “注释” xx //合并,禁用Fast forward模式,可以看出合并历史

    git stash //存储正在工作还没完成的项目(目的是另一个bug更急着去修改)
    //如果当前工作的分支是dev
    //使用git stash把未完成的dev分支工作进度保存,去修改其他分支bug
    //如果其他分支bug修改完成,切回dev分支git checkout dev
    //使用git stash pop切回dev之前的工作进度并删除之前的git stash历史记录

    git push origin master //将本地master推送到远程master。推送其他分支git push origin xx

    git push origin v1.0 //推送指定标签名到远程
    git push origin –tags //推送所有已经设置标签名到远程

    git add -f App.class //强制添加文件到暂存区,针对.gitignore设置

    git fetch <远程主机名> <分支名>   //取回远程仓库的资源,类似下载,如果想取回取回origin主机的master分支
    //就例如:git fetch origin master

    删:
    git rm test.txt //删除(其实还没有真正删除,撤回之前的删除git checkout — test.txt)
    git commit -m “remove test.txt” //真正的从仓库中删除

    git branch -d xx //删除本地xx分支
    git branch -D xx //强行删除没有合并的分支

    git tag -d v0.1 //删除某个写错的标签名

    如果上传错误的标签名删除顺序是:
    git tag -d v0.9 //先删除本地标签名
    git push origin :refs/tags/v0.9 //先删除远程标签名

    git remote rm <主机名>  //删除远程主机

    git push origin –delete xx   //删除远程xx分支

    改:

    git reset --hard HEAD^    //退回一个版本,如果发现出现有more错误可以这么改   git reset --hard "HEAD^"
    git reset --hard HEAD^^ //退回上上一个版本
    git reset --hard HEAD~100 //退回到上第100个版本
    git reset --hard 3628164 //切换到底指定版本

    git checkout — readme1.txt readme2.txt //未git add,恢复修改前,
    情况1,如果没add,就退回到最近的一次版本(最近的一次git commit)
    情况2,如果有add,就退回到最近的那次add到暂存区的版本(最近的一次git add)

    撤回遇到情况1还好,如果遇到情况2,要怎么撤回add呢?
    git reset HEAD readme.txt
    接着
    git checkout — readme.txt
    之前提交到修改的并且提交到暂存区的全部退回到最近一次版本,退回到最近的一次git commit

    git checkout master //切换指定分支

    git merge xx //将xx分支和当前分支合并 (如果当前切换到master分支使用此命令,就是把xx分支和master分支合并)

    git stash apply stash@{0} //我们可以多次使用git stash,要恢复指定历史记录使用git stash list

    git tag v1.0 //为某commit id设置标签名,就要先切换到到某标签git checkout

    git tag v0.9 6224937 //为某具体commit id设置标签名
    git tag -a v0.1 -m “注释” 3628164 //为某commit id设置标签名同时设置注释

    git remote rename <原主机名> <新主机名>   //修改远程主机名

    git pull origin next:master   //远程的分支next与本地的分支master合并

    git reset HEAD // 撤销所有git add .提交的文件

    git reset HEAD XXX/XXX/XXX.java  //撤销某一个 git add 的文件

    git config --global user.name "你的名字"  //push提交代码显示这里的名称
    git config --global user.email "你的邮箱"

     

     

     

    查:

    冲突分析:

    git status //查看当前仓库的文件是否修改、或未提交的

    git diff HEAD 文件名.txt //查看当前文件具体修改了什么内容

    git log //查看每次提交所修改的什么详细内容,方便回到从前
    git log –pretty=oneline //简要的显示每次修改内容,方便回到从前

    git reflog //查看所有提交commit id,方便回到未来

    git branch //查看所有分支

    git stash list //查看stash列表

    git remote -v //查看远程仓库克隆,也就是我们要pull和push的远程主机默认名称都是origin

    git remote show <主机名>  //查看远程主机详细信息

    git log –pretty=oneline –abbrev-commit //查看全部commit id和注释

    git tag //查看所有为commit id设置的标签名

    git show v0.9 //查看具体标签信息

    git check-ignore -v xx.class //查看.gitignore文件里是否含有xx.class

    git branch -a  //查看本地和远程的所有分支

    Git版本库
    就是仓库里面的隐藏目录.git

    工作区
    就是我们创建的仓库,除了隐藏目录.git

    暂存区
    暂存区就在仓库里面隐藏的.git目录中,还有Git为我们自动创建的第一个分支master
    git add 实际上就是把文件修改添加到暂存区

    分支
    我们创建仓库时同时创建了Git版本库,Git在版本库里面自动为我们创建了唯一一个master分支
    git commit 实际上就是把暂存区的所有内容提交到master当前分支。

    添加远程库
    git remote add <主机名> <网址>

    //案例,第一次添加远程仓库
    git remote add origin git@github.com:chen77134056/vue-web.git  //第一次创建仓库需要把本地的origin和远程git@github.com:xx/vue-web.git关联
    git push -u origin master  //第一次把本地的master分支提交到远程仓管

    (如果远程库有更新,执行以上命令会出错,必须先把远程库下载并合并到本地后才能继续push以上命令,
    合并代码:git pull –rebase <远程主机名> <远程分支名>:<本地分支名>)
    git push origin master //此后,每次本地提交后,只要有必要,就可以使用命令
    git push origin dev //推送dev分支

    下载远程库
    git clone git@github.com:michaelliao/gitskills.git
    多人合作只需要下载本地库

    分支管理
    它的存在是什么?
    当你完成一个50%的项目上传远程库后,别人在下载基于你的50%项目不能正常运行给别人造成麻烦,
    但又怕不上传万一丢失数据。
    可以创建一个分支保存工作的个个进度状况,别人看不到你的分支,最后再一次性合并分支。

    快捷键设置
    git config –global alias.st status

    git status
    等同
    git st

    多人合作:
    首先,可以试图用git push origin branch-name推送自己的修改;

    如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;

    如果合并有冲突,则解决冲突,并在本地提交;

    没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功!

    如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch –set-upstream branch-name origin/branch-name。

    这就是多人协作的工作模式,一旦熟悉了,就非常简单。

    建议:
    1,主分支master一般都是稳定项目,即能正常工作的。所以一般我们开发在develop开发
    2,每次为项目添加一个新功能,就创建一个新分支,完成后合并,最后,删除该分支。
    3,master分支是主分支,因此要时刻与远程同步;
    dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
    bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
    feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
    (总之,就是在Git中,分支完全可以在本地自己藏着玩,是否推送,视你的心情而定!)

    push免输入帐号密码(只适用http协议,ssh貌似不行)

    Linux或者Mac下方法:

    1,在cd ~目录新建.git-credentials名字的文件,内容为:

    https://{username}:{password}@github.com

    2,终端输入:

    git config --global credential.helper store

    3,打开~/.gitconfig文件,会发现多了一项:

    [credential]
    helper = store

    Windows方法:

    在%HOME%目录中,如果不知道就使用git bash去找cd ~目录即可,在~目录下然后用touch创建文件 .git-credentials