美文网首页
Vue基础补充

Vue基础补充

作者: 强某某 | 来源:发表于2018-05-06 20:20 被阅读9次

    第一章

    注意点

    let app=new Vue({
            el:"#app",
            data:{
                msg:'Vue!'
            }
        });
        setTimeout(() => {
            // app.msg="Heelo";
            app.$data.msg="Heelo";
        }, 1000);
    
    简化的todolist
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <script src="./js/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <input type="text" v-model='msg'>
            <button @click='addList'>添加</button>
            <ul>
                <li v-for='item in arrs'>{{item}}</li>
            </ul>
        </div>
    </body>
    </html>
    <script>
        let app=new Vue({
            el:"#app",
            data:{
                msg:'',
                arrs:[]
            },
            methods:{
                addList(){
                    this.arrs.push(this.msg);
                    this.msg='';
                }
            }
        });
    </script>
    
    

    全局组件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <script src="./js/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <input type="text" v-model='msg'>
            <button @click='addList'>添加</button>
            <ul>
                <todo-item v-bind:content='item' v-for='item in arrs'></todo-item>
            </ul>
        </div>
    </body>
    </html>
    <script>
        Vue.component('TodoItem',{
            props:['content'],
            template:`<li>{{content}}</li>`,
        })
    
        let app=new Vue({
            el:"#app",
            data:{
                msg:'',
                arrs:[]
            },
            methods:{
                addList(){
                    this.arrs.push(this.msg);
                    this.msg='';
                }
            }
        });
    </script>
    

    局部组件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <script src="./js/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <input type="text" v-model='msg'>
            <button @click='addList'>添加</button>
            <ul>
                <todo-item v-bind:content='item' v-for='item in arrs'></todo-item>
            </ul>
        </div>
    </body>
    </html>
    <script>
        let TodoItem={
            props:['content'],
            template:`<li>{{content}}</li>`,
        }
        let app=new Vue({
            el:"#app",
            data:{
                msg:'',
                arrs:[]
            },
            components:{
                TodoItem
            },
            methods:{
                addList(){
                    this.arrs.push(this.msg);
                    this.msg='';
                }
            }
        });
    </script>
    

    组件传值(子组件修改父组件数据)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <script src="./js/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <input type="text" v-model='msg'>
            <button @click='addList'>添加</button>
            <ul>
                <todo-item 
                v-bind:content='item'
                :index='index' 
                v-for='(item,index) in arrs'
                @delete='deleteIndex'
                ></todo-item>
            </ul>
        </div>
    </body>
    </html>
    <script>
        let TodoItem={
            props:['content','index'],
            template:`<li @click='hehe'>{{content}}</li>`,
            methods:{
                hehe(){
                    this.$emit('delete',this.index);
                }
            }
        }
        let app=new Vue({
            el:"#app",
            data:{
                msg:'',
                arrs:[]
            },
            components:{
                TodoItem
            },
            methods:{
                addList(){
                    this.arrs.push(this.msg);
                    this.msg='';
                },
                deleteIndex(index){
                    this.arrs.splice(index,1);
                }
            }
        });
    </script>
    

    第二章

    条件渲染

    <body>
        <div id="app">
            <div v-if='show'>
                用户名:<input key="username">
            </div>
            <div v-else>
                密码:<input key="password">
            </div>
        </div>
    </body>
    </html>
    <script>
        let app=new Vue({
            el:"#app",
            data:{
               show:false
            }
        });
    </script>
    说明: <input key="username">中key的用处,比如在默认显示用户名输入框时候,
    如果此时不加key则修改show值使之显示密码输入框,此时之前输入框输入内容还在
    virtualdom的diff算法,会尽量少的修改dom,复用了input,vi是加上key代表input
    是独一无二的,则可以达到之前输入内容清除的效果。
    

    列表渲染

    <body>
        <div id="app">
            <template v-for='item in arrs'>
                <div :key='item.id'>
                    {{item.info}}
                </div>
                <span>
                    {{item.info}}
                </span>
            </template>
    
            <div v-for='(item,key,index) of objs'>
                {{item}}--{{key}}--{{index}}
            </div>
        </div>
    </body>
    </html>
    <script>
        let app=new Vue({
            el:"#app",
            data:{
               arrs:[
                   {id:"0001",info:"1"},
                   {id:"0002",info:"2"},
                   {id:"0003",info:"3"},
                   {id:"0004",info:"4"}
               ],
               objs:{
                   name:"qiang",
                   age:12
               }
            }
        });
    </script>
    说明:
    一、列表渲染的时候,上面div和span被template包裹,tempalte作用就是:
    在span和div(类似多个标签)内部数据来源一样,为了避免写两次循环,必须最外部
    再用div包裹,但是这样在html源码里面多出来一个无意义的div,此时tempalte就是
    起一个占位符的作用,即满足包裹还在生成的html里面不存在一个无意义的div。
    二、:key='item.id'其实就是针对的绑定key属性(上面条件渲染说明了key一些的作用),
    一般不要使用index直接当key,而是使用后台返回数据,保证唯一性和高效性。
    三、在针对数组的时候,直接去修改数组内容dom视图不变化。
    但是直接修改此时app.arrs[0].info的值,即具体值会更新视图
    方案:① 使用js提供的数组操作方法(push,sort等)
          ② 直接改数组的引用(即重新赋值) ③ set方法
    四、针对对象遍历使用of,<div v-for='(item,key,index) of objs'>,其中item是属性值,key是属性名,index是索引 
    
    

    第三章(组件)

    组件使用的细节

    <body>
        <div id="app">
            <ul>
                <li ref='one' is='itemli' @change='addTotal'></li>
                <li ref='two' is='itemli' @change='addTotal'></li>
                <li>{{total}}</li>
            </ul>
        </div>
    </body>
    </html>
    <script>
        Vue.component('itemli',{
            template:`<li @click='add'>{{msg}}</li>`,
            data(){
                return{
                    msg:1
                }
            },
            methods:{
                add(){
                    this.msg++;
                    this.$emit('change');
                }
            }
        });
        let app=new Vue({
            el:"#app",
            data:{
               total:0
            },
            methods:{
                addTotal(){
                    this.total=this.$refs.one.msg+this.$refs.two.msg;
                }
            }
        });
    </script>
    说明:
    一、组件中,data必须是函数形式,是因为,每个组件应该数据是独立的,互不影响,从当前案例可以看出,同样都是itemli组件,两者的点击事件加msg值互不影响。
    二、例如在ul中放入组件,有些浏览器会存在兼容性问题,必须放入li,形成ul>li结构,
    此时可以使用is='组件名称'达到效果。
    三、注意this.$emit('change');括号内部参数是 change对应的是<li ref='one' is='itemli' @change='addTotal'></li>中的v-on的属性,这个属性值change是随意的,也可以是click等.然后触发是父级的在vue构造器内部的方法addTotal
    四、ref属性作用:在组件中ref代表的是组件的引用(可以打印看到各种内部属性),在dom中代表该dom节点。this.$refs代表所有的ref,根据相关引用,可以得到各种所需的dom中的值或者其他属性。、
    补充:<counter :count='1'></counter>
    上面是父组件给子组件传递参数方式的一种,此时反是:修饰的属性内部的''中都是表达式
    所以此时传递是数字,如果不加:直接count也可以传递参数,但是传递的是字符串。
    补充:同理在子组件中,也可以不通过传递参数直接使用父组件的数据,方法等
    this.$parent.数据名称
    

    单项数据流

    单向数据流:父组件可以传递参数给子组件,但是子组件不能修改该参数,因为传递过来的参数可能是一个对象的引用,可能不光是该子组件在使用,可能会影响其他子组件。

    解决方案:
    <body>
        <div id="app">
            <ul>
                <li  is='itemli' :count='1' @change='addTotal'></li>
                <li  is='itemli' :count='2' @change='addTotal'></li>
                <li>{{total}}</li>
            </ul>
        </div>
    </body>
    </html>
    <script>
        Vue.component('itemli',{
            props:['count'],
            template:`<li @click='add'>{{num}}</li>`,
            data(){
                return{
                    num:this.count
                }
            },
            methods:{
                add(){
                    this.num++;
                    this.$emit('change',2);
                }
            }
        });
        let app=new Vue({
            el:"#app",
            data:{
               total:0
            },
            methods:{
                addTotal(step){
                    this.total+=step;
                }
            }
        });
    </script>
    说明::count='1'是父组件传递的number类型的参数,如果在子组件中直接修改count会报错,此时解决方案是num:this.count,相当于复制有一份在当前子组件中,即可。
    
    

    组件参数校验


    一、
    <itemli :count='1+3'></itemli>:在界面上显示的是4
    <itemli count='1+3'></itemli>:在界面上显示的是1+3

    二、
    Vue.component('itemli',{
    props:{
    count:Number
    },
    template:<li>{{count}}</li>,
    });
    说明:props一般是数组形式,但是如果需要对父组件传递的参数进行校验需要如上的写法
    意思是必须是Number类型,也可以这么写[String,Number],就是字符串或者数字类型都可以。

    三、针对二的更完整复杂写法

        <body>
        <div id="app">
            <itemli count='afasad'></itemli>
        </div>
    </body>
    </html>
    <script>
        Vue.component('itemli',{
            props:{
                count:{
                   type: String,
                   required:false,
                   defalut:'hello',
                    validator:function(value){
                        return (value.length>5);
                    }
                }
            },
            template:`<li>{{count}}</li>`,
        });
        let app=new Vue({
            el:"#app",
            data:{
            },
            
        });
    </script>
    

    说明:required代表(是否,布尔值)必须传递count参数,defalut代表允许不传递时候的默认值,validator是一个判断函数,此时意思是传递的参数长度必须大于5.注意这种详细判断和上面的一二的写法不同count后面跟的也是对象


    非付子组件之间传值(总线,发布订阅,观察者模式)

    <body>
        <div id="app">
            <itemli count='1'></itemli>
            <itemli count='2'></itemli>
        </div>
    </body>
    </html>
    <script>
        Vue.prototype.bus=new Vue();
        Vue.component('itemli',{
            props:['count'],
            template:`<li @click='hehe'>{{info}}</li>`,
            data(){
                return{
                    info:this.count
                }
            },
            methods:{
                hehe(){
                    this.bus.$emit('change',this.info);
                }
            },
            mounted(){
                //如果此处不用箭头函数,内部的this指向不是vue
                this.bus.$on('change',(msg)=>{
                    this.info=msg;
                })
            }
        });
        let app=new Vue({
            el:"#app"
        });
    </script>
    说明:
    一、Vue.prototype.bus=new Vue();是在vue原型上增加bus属性,并且赋值为一个Vue对象。
    二、this.bus.$emit('change',this.count);触发bus上面的change
    三、this.bus.$on('change',(msg)=>{this.info=msg;})监听bus上面的change事件
    四、data(){return{info:this.count}},解决子组件逆向修改父组件值的报错问题
    

    Vue的插槽(slot)

    使用场景:当父组件向子组件传递大量信息时候,例如:dom,使用上面的props不方便维护代码,此时slot(插槽)作用就显现出来了。

    <body>
        <div id="app">
            <itemli>
                <div slot='A'>slot A </div>
                <div slot='B'>slot B </div>
            </itemli>
            <itemli><div>如果不写slot则itemli内部整体被当作插槽</div></itemli>
        </div>
    </body>
    </html>
    <script>
        Vue.prototype.bus=new Vue();
        Vue.component('itemli',{
            // template:`<li>
            // <slot name='A'></slot>
            // <h1>中间内容</h1>
            // <slot name='B'></slot>
            // <slot name='C'><h2>默认内容,在指定的插槽没有传递时候,显示出来</h2></slot>
            // </li>`,
            template:`<li>
            <slot></slot>
            </li>`,
        });
        let app=new Vue({
            el:"#app",
        });
    </script>
    说明:
    一、第二个itemli内部整体直接被当作slot,不区分名称,直接替换template:`<li><slot></slot></li>`,中的<slot></slot>。
    二、第一个slot中的name='A'对应上面的slot='A',这样可以避免整体替换,而且没有传递对应slot(不见的一定要name),则会显示默认,否则不显示默认内容。
    

    作用于插槽

    使用场景:显示细节是由父组件确定情况下,例如此时li内部可以是h2或者p

    <body>
        <div id="app">
            <itemli>
                <template slot-scope='props'>
                    <h2>{{props.item}}</h2>
                </template>
            </itemli>
            <itemli>
                    <template slot-scope='props'>
                        <p>{{props.item}}</p>
                    </template>
            </itemli>
        </div>
    </body>
    </html>
    <script>
        Vue.component('itemli',{
            template:`<li>
            <slot v-for='item in arrs' :item=item></slot>
            </li>`,
            data(){
                return{
                    arrs:[1,2,3,4]
                }
            }
        });
        let app=new Vue({
            el:"#app",
        });
    </script>
    说明:作用于插槽在父组件中,必须是template包裹,slot-scope='props'代表数据来源也是固定写法,所有子组件传递给父组件的数组都在props中。
    在子组件的模板中<slot v-for='item in arrs' :item=item></slot>的:item=item是固定写法,代表数据
    

    动态组件的切换性能问题

    <body>
        <div id="app">
           <one v-if='show==1'></one>
           <two v-if='show==2'></two>
           <button @click='change'>切换</button>
        </div>
    </body>
    </html>
    <script>
        Vue.component('one',{
            template:`<li v-once>one</li>`,
           
        });
        Vue.component('two',{
            template:`<li v-once>two</li>`,
           
        });
        let app=new Vue({
            el:'#app',
            data:{
                show:1
            },
            methods:{
                change(){
                    this.show=(this.show==1?2:1);
                }
            }
        })
    </script>
    说明:在组件的template中添加v-once属性,可以提高性能,因为动态切换组件的时候,是加载之后销毁在加载别的组件,但是加上v-once属性后,除了第一次是加载,其他切换时候都是加载内存中保存的实例,可以极大的提高性能。
    

    相关文章

      网友评论

          本文标题:Vue基础补充

          本文链接:https://www.haomeiwen.com/subject/mptprftx.html