Vue基础补充

第一章

注意点

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属性后,除了第一次是加载,其他切换时候都是加载内存中保存的实例,可以极大的提高性能。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容

  • 下载安装搭建环境 可以选npm安装,或者简单下载一个开发版的vue.js文件 浏览器打开加载有vue的文档时,控制...
    冥冥2017阅读 6,037评论 0 42
  • vue概述 在官方文档中,有一句话对Vue的定位说的很明确:Vue.js 的核心是一个允许采用简洁的模板语法来声明...
    li4065阅读 7,206评论 0 25
  • 这篇笔记主要包含 Vue 2 不同于 Vue 1 或者特有的内容,还有我对于 Vue 1.0 印象不深的内容。关于...
    云之外阅读 5,048评论 0 29
  • 有多久没有写东西了,很久很久了。 不是不想写,很多次,打开电脑,想写点什么,却不知道改写些什么了。 就连16年的年...
    雨影阅读 399评论 0 1
  • 我喜欢他的时候。 他阳光 谦卑 快乐,唯独不喜欢我。 我不喜欢他的时候,他喜欢我。 神迷,优雅,其实不大清楚。 当...
    贺瑾野子阅读 162评论 1 4