Vue框架,从基础入门到项目实战。看这一篇知识点全覆盖了

2021年9月20日 8点热度 0条评论 来源: new 前端

##放在最前面,
github 重构vancl网站
https://github.com/pengboooo/VANCL 这是地址,有喜欢的希望给个免费的start,谢谢了

安装Vue

介绍

Vue 只关注视图层, 采用自底向上增量开发的设计。
在了解Vue之前你需要了解

  • HTML
  • CSS
  • JavaScript

安装Vue

  1. 通过CDN方式使用
    示例 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.min.js"></script>
  • Staticfile CDN(国内) : https://cdn.staticfile.org/vue/2.2.2/vue.min.js

  • unpkg:https://unpkg.com/vue/dist/vue.js, 会保持和 npm 发布的最新的版本一致。

  • cdnjs : https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.min.js

  1. 通过npm安装
    1. 初始化环境
npm init -y
  1. 安装vue
cnpm i -D vue//-d的含义是开发模式添加到依赖
  1. 写第一个vue
    说实话怎么写着感觉有点像 art-template,但是比模板引擎的功能更强大。
<div id="box">
        <p>{ { msg}}</p>
    </div>
    <script>
        var vm = new Vue({ 
            el: '#box',
            data: { 
                msg: 'hello world'
            }
        })
    </script>

初识指令

  1. 数据双向绑定(v-model)
 <div id="box">
      <p v-text = 'msg'></p>  
        <input type="text" v-model ="msg"  > <!--双向绑定,只需要填写v-model -->
    </div>
    <script>
        
    var vm = new Vue({ 
        el:'#box',
        data:{ 
            msg:'王五'
        },
        
    })
    
    </script>
  1. 标签属性的设置(v-bind || :)
 <div id="box">
        <!-- 思考,如果我想渲染多个属性呢 -->
        <div v-bind:class='msg'></div>//可以简写为<div :class='msg'></div>
    </div>
    <script>
        var cls = ["div1","div2","div3"]
        cls.toString = function(){ 
            return this.join(' ');//这里填什么都没有影响,只处理数组
        }
        
        console.log(cls);
        
    var vm = new Vue({ 
        el:'#box',
        data:{ 
            msg:cls
        }
    })
    </script>
  1. 标签内容的设置(v-text );
  <div id="box">
        <p v-text='msg'></p>
  </div>
  <script>
  new Vue({ 
      el:'#box',
      data:{ 
          msg:'这是一个文本'
      }
  })
  </script>  
  1. 标签内容的设置(v-html )
  <div id="box">
        <p v-html='msg'></p>
  </div>
  <script>
  new Vue({ 
      el:'#box',
      data:{ 
          msg:'<p>这是一个文本</p>'
      }
  })
  </script>  
  1. 监听DOM事件(v-on || @)
   <div id="div">
   <button v-on:click='setCon'>{ { msg}}</button>//可以这样简写<button @click='setCon'>{ {msg}}</button>
    </div>
    <script>
    new Vue({ 
        el:'#div',
        data:{ 
            msg:'5'
        },
        methods:{ 
            setCon:function(e){ 
                this.msg++
                
            }
        }
    })
    </script>
  1. 循环(v-for)
  <div id="box">
        <ul>
             <li v-for='(item,index) in msg'>{ { item+' '+index}}</li><!--循环数组支持多参数 -->
             <li v-for='(item,key,index) in obj'>{ { item+' '+ key +' '+ index}}</li><!--循环对象支持多参数 -->
        </ul>
    </div>
    <script>
    new Vue({ 
        el:'#box',
        data:{ 
            msg:[1,2,3,1,4,5,4],
            obj:{ 
                name:"张三",
                age:'18',

            }
        }
    })
    </script>

7.computed(依赖缓存数据)与methods(不依赖缓存,每次都计算)
当data数据发生变化时就会变化

 <div id="box">
           
        { { yesNum()}}
        { { yesNum()}}
        { { yesNum1}}
        { { yesNum1}}
        { { yesNum1}}
    </div>
    <script>
        var conts =1;
    var vm = new Vue({ 
        el:'#box',
        data:{ 
            msg:'vue'
        },
        methods:{ //这个每个都要重新计算一遍
            yesNum:function(){ 
                conts++;
                console.log(this.msg.split('').reverse().join(''));
                
                 return conts+' '+ this.msg.split('').reverse().join('')//返回字符串反转内容
            }
        },
        computed:{ //这个会有缓存,之前有了不再计算直接输出
            yesNum1:function(){ 
                conts++;
                console.log(this.msg.split('').reverse().join(''),'se');
                
                 return conts+' '+ this.msg.split('').reverse().join('')
            }
        }
    })
    </script>
  1. 属性监听(属性改变数据跟着变化)
    案例购物车
 <div id="app">
        <table>
            <tr>
                <th>序号</th>
                <th>商品名称</th>
                <th>商品价格</th>
                <th>购买数量</th>
                <th>操作</th>
            </tr>
            <tr v-for="iphone in Ip_Json">
                <td>{ {  iphone.id }}</td>
                <td>{ {  iphone.name }}</td>
                <td>{ {  iphone.price }}</td>
                <td>
                        <!-- disabled="iphone.count === 0" 里面是个表达式,当为true时禁用按钮,就不能0以下了 -->
                    <button v-bind:disabled="iphone.count === 0" v-on:click="iphone.count-=1">-</button>
                    { {  iphone.count }}
                    <button v-on:click="iphone.count+=1">+</button>
                </td>
                <td>
                    <button v-on:click="iphone.count=0">移除</button>
                </td>
            </tr>
        </table>
        总价:${ { totalPrice()}}
    </div>
    <script>
        var app = new Vue({ 
            el: '#app',
            data: { 
                Ip_Json: [{ 
                        id: 1,
                        name: 'iphone 8',
                        price: 5099,
                        count: 1
                    },
                    { 
                        id: 2,
                        name: 'iphone xs',
                        price: 8699,
                        count: 1
                    },
                    { 
                        id: 3,
                        name: 'iphone xr',
                        price: 6499,
                        count: 1
                    }
                ]

            },
            methods: { 
                totalPrice: function () { 
                    var totalP = 0;
                    for (var i = 0, len = this.Ip_Json.length; i < len; i++) { 
                        totalP += this.Ip_Json[i].price * this.Ip_Json[i].count;
                    }
                    return totalP;
                }


            }
        })
    </script>
  1. 插值表达式闪烁问题(v-clock)
 <style>
    [v-clock]{ 
        display: none !important;
    }
    </style>
     <div id="box" >
        <div v-clock >{ { msg}}</div>
    </div>
    <div id="box" >
        <div v-text='msg' ></div>//这样写没有闪烁问题
    </div>
  1. 事件修饰符
    .stop (阻止冒泡或者捕获,后面的不触发) .prevent(阻止默认行为).capture (事件捕获).self(阻止自身) .once(只触发一次)
<div id="boxs">
     <div id="box" @click.capture='box1'><!--设置捕获 -->
           <div id="box2" @click.self='box2'> <!-- 阻止自身的捕获 -->
                 <div id="box3" @click.stop='box3'><!--阻止冒泡 -->
                </div>
            </div>
    </div>
    <button @click.once='one'>once</button> <!--只触发一次 -->
    <a href="www.baidu.com" @click.prevent='alert("弹出跳转")'>跳转</a> <!--阻止默认行为 -->
</div>
    <script>
        
    new Vue({ 
        el:'#boxs',
        methods:{ 
            box3(){ 
                console.log('触发了3');
            },
            box2(){ 
                console.log('触发了2'); 
            },
            box1(){ 
                console.log('触发了1');
            },
            one(){ 
                console.log('执行了');
                
            }
            
        }

    })
    
    
    </script>
  1. 事件的冒泡和捕获
    1. 原生js事件的冒泡和捕获
<div class="grandfather">
    <div class="father">
      <div class="son">

      </div>
    </div>
 </div>
 <script>
    var grandfather = document.querySelector(".grandfather")
    var father = document.querySelector(".father")
    var son = document.querySelector(".son")
    grandfather.addEventListener("click", function() { 
      console.log("grandfather冒泡阶段")
    }, false)

   

    father.addEventListener("click", function() { 
      console.log("father冒泡阶段")
    }, false)

    // 如果某一个元素是目标阶段,谁先注册谁先执行!!!
    son.addEventListener("click", function() { 
      console.log("son冒泡阶段")
    }, false)


    grandfather.addEventListener("click", function() { 
      console.log("grandfather捕获阶段")
    }, true)
    father.addEventListener("click", function() { 
      console.log("father捕获阶段")
    }, true)
    son.addEventListener("click", function() { 
      console.log("son捕获阶段")
    }, true)
</script>
  1. 事件代理

应用为,你不知道你又多少个子元素需要加事件,或者有很多的子元素,
如果你一个一个加,不就很浪费资源。所以出现事件代理去解决

 <ul id="ul">
      <li>1</li>
      <li>2</li>
      <li>3</li>
     ............我就省略重复的了
      <li>98</li>
      <li>99</li>
      <li>100</li> 
    </ul> 
    <script>
     // removeEventListener('click', 函数) 
     // 事件委托? 通过冒泡事件,给父元素绑定事件。s
     var ul = document.getElementById('ul');
     ul.onclick = function(event) { 
         console.log(event);
       console.log(event.target.innerHTML)
     }
  </script>
  1. 按键修饰符
    .enter => // enter键
    .tab => // tab键
    .delete (捕获“删除”和“退格”按键) => // 删除键
    .esc => // 取消键
    .space => // 空格键
    .up => // 上
    .down => // 下
    .left => // 左
    .right => // 右
   <div id="box">
        <input type="text" @keyup='enters'>//或者@keyup.某个修饰符
    </div>
    <script>
    new Vue({ 
        el:'#box',
        methods:{ 
            enters(e){ 
                console.log(e.keyCode);
                
            }
        }
    })
    
    </script>
也可以固定某一个按键,这样写
 <div id="box">
        <input type="text" @keyup.enter='enters'>//或者@keyup.某个修饰符
    </div>
    <script>
    new Vue({ 
        el:'#box',
        methods:{ 
            enters(e){ 
                console.log(e.keyCode);
                
            }
        }
    })
    
    </script>
  1. 数据的过滤器 (filters)
 <div id="box">{ { msg | num | num2}}</div>
    <script>
    new Vue({ 
        el:'#box',
        data:{ 
            msg:15,
        },
        filters:{ 
            num:function(val){ 
                console.log(val);
                return val+1
                
            },
            num2:function(val){ 
                console.log(val);
                return val+1
            }
        }
        
    })
    </script>
  1. watch(支持异步代码)handlar
	 watch: { //某数据改变时触发
		 	check:{ //要监听值的名称
		 		handler(newName, oldName) { 
     					 this.fullName = newName + ' ' + this.lastName;
   					 },
   		 // 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法
   						 immediate: true
   					  监听数值是不是要深度监听
						deep: true,
		 		},
  1. v-if和v-show
 <p v-if="msg">{ { msg}}</p>直接删除标签
        <p v-show="msg">{ { msg}}</p>不会删除标签。在标签上添加display属性
  1. template模板标签,只支持v-if 和v-else
    有三种写法
    //第1种模板 写在构造器里
    //template:<h1 style="color:red">我是选项模板2</h1>

    //第2种模板 写在<template>标签里
    //template:'#demo3'
    
    //第3种模板 写在<script type="x-template">标签里
    
<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address" key="email-input">
</template>

如果你想继续使用里面的内容,可以用slot

<body>
    <div id="box">

        <Hello-world>
            <p slot="p1">1</p>
            <p>2</p>
            <p>3</p>
            <p>4</p>
            <p>5</p>
            <p>6</p>
            <p>7</p>
            <p>8</p>
            <p>9</p>
            <p>10</p>

        </Hello-world>


    </div>
    <template id="temp">
        <div>
            <p>把这里的内容全部替换掉</p>
            <slot></slot>
            <slot name='p1'></slot>
        </div>
    </template>
    <script>
        // 自定义组件
        let HelloWorld = { 
            template: "#temp",

        }
        new Vue({ 
            el: '#box',
            data: { 
                msg: true
            },
            components: { 
                HelloWorld //添加组件
            },

            /* 这是第一种写法 template: '<p>#box中的全部替换掉</p>', //这里是模板名称,要替换#box里所有的内容, */
            /** * 这是第二种写法,需要在页面中添加 * template:'#temp' * <template id="temp"> <div > <p>把这里的内容全部替换掉</p> </div> </template> * * */


        })
    </script>
  1. ref
    设置在标签上,就可以获取dom对象
 <div id="box">
        <p ref="element"></p>
    </div>
    <script>
     let vm = new Vue({ 
            el:"#box",
            data:{ 
                msg:"张山"
            }
        })    
        
   console.log( vm.$refs.element);
   
    </script>
  1. vue的生命周期
    主要是四个钩子函数
    1,beforeCreate、created、 (创建=>)
    beforeMount、mounted、 (挂载=>)在挂载时会实时监听更新的状态
    beforeUpdate、updated、(更新=>)
    beforeDestroy、destroyed ,销毁,
  2. nextTick 原理mutationObserver(监视dom渲染完毕后执行nextTick)
    原理就是使同步的api,变为异步执行,添加到队列中。
    nextTick行为利用了microtask队列, 先使用 Promise.resolve().then(nextTickHandler)来将异步回调
    放入到microtask中,Promise 和 MutationObserver都可以使用,但是 MutationObserver 在IOS9.3以上的
    WebView中有bug,因此如果满足第一项的话就可以执行,如果没有原生Promise就用 MutationObserver。
    .我把JavaScript在浏览器中运行主要分为以下几种类型的任务:
  • 同步任务(MainTask) :同步任务是指JavaScript按照正常顺序执行的代码,比如:函数调用,数值运算等等,只要是执行后立即能够得到结果的就是同步任务。
  • 宏任务 (MacroTask):setTimeout、setInterval、I/O、UI渲染
  • 微任务 (MicroTask) :Promise、Object.obsever、MutationObsever
  • 用户交互事件(User Interaction Event):点击事件onclick、键盘事件onkeywodn、鼠标事件onmouseover等等

**

执行顺序

**

24. 全局组件定义

 <div id="box">
            <hello></hello>
    </div>
    <script>
        //定义全局组件
        Vue.component('hello',{ //注册全局,其实就是挂载到vue的构造函数中
            template:'<div>这是一个模板<div>',
            created() { 
                console.log('这是创建之后钩子函数')
            },
        })
    new Vue({ 
        el:'#box',
        data() { 
            return { 
                
            }
        },
    })
    </script>
  1. 局部组件定义
 <div id="box">
                <hello></hello>
            </div>
            <script>
                let hello = { 
                    template : "<div>这里定义的是一个局部组件</div>",
                    created() { 
                        console.log('这个是创建之后的钩子函数')
                    },
                }
                new Vue({ 
                    el: '#box',
                    data:{ 
                    },
                    components: { 
                        hello,
                    }
                })
            </script>
  1. 组件嵌套
 <div id="box">
        <grandfather></grandfather>

    </div>
    <script>
        /** 分析,组件的嵌套,最终是将所有组件放到一个父组件中,所以页面写的是一个组件的名字 写在最后一层的需要最先定义,因为只有定义的才能使用 */
            let son ={ 
                template: '<div>这是儿子的组件</div>'
            }
            let father ={ 
                template:'<div>这是父亲的组件<son></son></div>',
                components:{ 
                    son
                }

            }
            let grandfather = { 
                template:'<div>这是爷爷的组件<father></father></div>',//注册完需要写在爷爷的模板中渲染
                components:{ 
                    father,
                }
            }
    new Vue({ 
        el:'#box',
        components:{ 
            grandfather,
        }
    })
    
    </script>
  1. 父组件向子组件传参
<div id="box">
        <father></father>
    </div>
    <script>
        //父向子传递,需要子元素绑定一个属性,然后子元素接收
        //
        //新建子组件
        let son = { 
            template: '<div>父亲传递过来的值{ {manoe}}<input type="text" v-model:value="manoe"> </div>',
            props: ['manoe']
        }
        //新建父组件
        let father = { 
            // data:{ 
            // m:20
            // },
            data() { //组件嵌套时就需要写成对象返回值方式
                return { 
                    m: 20,
                }
            },
            template: '<div class="father">这是父亲的块{ {m}}<son class="son" :manoe="m"></son></div>',
            components: { 
                son,
            }
        }
        new Vue({ 
            el: '#box',

            components: { 
                father
            }
        })
    </script>
  1. 订阅发布模式
    先用原生js写一遍订阅发布模式
 <script>
    // 女生失恋 吃火锅 买包包 看电影
    function Girl() { 
      this._events = { }
    }

    Girl.prototype.on = function(eventName, handler) { 
      // _events.shilian
      if(this._events[eventName]) { 
        this._events[eventName].push(handler)
      }else { 
        // 如果说events.shilian没有的话,则将handler加入空数组中
        // this._events.shilian = [handler]
        this._events[eventName] = [handler]
      }
    }

    Girl.prototype.emit = function(eventName) { 
      if(this._events[eventName]) { 
        this._events[eventName].forEach((item)=> { 
          item()
        })
      }
    }

    var g1 = new Girl();
    // 订阅事件
    g1.on('shilian', function() { 
      console.log("吃火锅")
    })

    g1.on('shilian', function() { 
      console.log("买包包")
    })

    g1.on('shilian', function() { 
      console.log("看电影")
    })
    //[fn1, fn2, fn3]

    // 发布事件!!!
    g1.emit('shilian')

  </script>

再用vue中bus模式写同级相互传参

 <div id="box">
        <son1></son1>
        <son2></son2>
    </div>
    <script>
        let bus = new Vue();//使用bus方法创建一个空的总线。让组件去通信

        //新建兄弟组件
        let son1 = { 
            template: '<div class="son">父亲传递过来的值{ {msg}} </div>',
            data() { 
                return { 
                    msg: ''
                }
            },

            created() { 
                bus.$on("a", (msg) => { 
                    this.msg = msg;
                })
            }

        }
        //新建兄弟2组件
        let son2 = { 

            data() { 
                return { 
                    m: 10
                }
            },
            template: '<div class="father">这是父亲的块 <button @click="sendMsg">向另外一个兄弟组件传值</button></div>',
            methods: { 
                sendMsg() { 
                    bus.$emit('a', this.m)

                }
            },

        }
        new Vue({ 
            el: '#box',

            components: { 
                son2,
                son1
            }
        })
    </script>
  1. 子组件向父组件传参
    <div id="box">
        
        <father></father>
    </div>
    <script>
        //突然感觉这种方式在小项目中很好用啊,可以跨级组件传递。
        var bus = new Vue();
        //子组件
        let son ={ 
            data() { 
                return { 
                    msg:10
                }
            },
            template:'<div>这是子组件<button @click="faya">发送</button></div>',
            methods: { 
                faya(){ 
                    bus.$emit('name',this.msg)
                }
            },
        }
        //父组件
        let father = { 
            data() { 
                return { 
                    num:''
                }
            },
            template:'<div class="father">这是一个父组件的值{ {num}}<son class="son"></son></div>',
            components:{ 
                son
            },
            created() { 
                bus.$on('name',(msg)=>{ 
                    console.log("触发了");
                    
                    this.num = msg
                })
            },
        }
    new Vue({ 
        el:'#box',
        components:{ 
            father
        }

    })    
        
        
        
    </script>
  1. 弹窗
<div id="box">
        <button @click="brother">显示弹窗</button>
        <brothers ref ="boxs"></brothers>
        
    </div>


    <template id="boxs">
            <div class="whet" v-if="init">
                <div class="net">
                    <button @click='hide'>
                        关闭
                    </button>
                </div>
            </div>
        </template>
    <script>
        let brothers ={ 
            template:'#boxs',
            data() { 
            return { 
                init:false
            }
        },
            methods: { 
               hide(){ 
                this.init =!this.init
               }
            },
        }
    new Vue({ 
        el:'#box',
       
        methods: { 
            brother(){ 
                this.$refs.boxs.init =!this.$refs.boxs.init
            }
        },
        components:{ 
            brothers
        }
    })    
        
        
    </script>
  1. 写个中和案例,我就直接放在github上了。
    计划列表(数据持久化)点击前面的字就可以跳转

基础的vue学的差不多了。该学习路由,

follow me

Go! **

Vue-router

**
…正在一点点更正,欢迎大牛指点,小白学习。

    原文作者:new 前端
    原文地址: https://blog.csdn.net/qq_36131502/article/details/99303398
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。