Vue知识点补充学习

key属性,template占位符,v-for数组,v-for对象

当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。理想的 key 值是每项都有的且唯一的 id。
建议尽可能在使用 v-for 时提供 key,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

案发现场1:key

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>
<body>
<div id="root">
    <!-- 当页面加载时会首先显示邮箱名当我们输入邮箱时,在浏览器控制台上改变show的值为true时,为了减少DOM操作,
    vue会复用input元素,会导致input的内容未被清空,这时需要阻止复用使用key属性,key的值确保是唯一的且不重复 -->
    <div v-if="show">
        用户名:<input type="text" key="userName">
    </div>
    <div v-else>
        邮箱名:<input type="text" key="userEmail">
    </div>
</div>
<script>
    var vm=new Vue({
        el:"#root",
        data:{
            show:false
        }
    }); 
</script>
</body>
</html>
案发现场2:key/template/v-for数组/变异方法

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>
<body>
<div id="root">
    <!-- 一般为了提升循环的性能会在循环项上添加唯一的key值 -->
    <div v-for="(item,index) of list" :key="item.id"><!--在循环表达式中in和of都可以使用,'蛋'更推荐of-->
        {{item.text}}---{{index}}
    </div>
    <!-- 当循环体需要包裹其他标签时使用template占位符,template占位符 只会包裹不会显示到页面上 -->
    <template v-for="(text,idx) of list">
        <span>{{idx}}</span>
        <h1>{{text.text}}</h1>
    </template>
</div>
<script>
    var vm=new Vue({
        el:"#root",
        data:{
            /*
            对数组进行操作时,只能使用push pop shift unshift splice sort reverse变异方法否则页面和数据之间
            无法实现响应式
            其他响应式的操作数组的方法
                1还可以通过改变数组的引用来实现数据和页面之间的响应式
                    list=[
                        {
                            id:'010120201',
                            text:'Iphone'
                        },
                        {
                            id:'010120202',
                            text:'OPPO'
                        },
                        {
                            id:'010120203',
                            text:'VIVO'
                        },
                        {
                            id:"010120204",
                            text:'HUIWEI'
                        },
                        {
                            id:"010120205",
                            text:"NOKIA"
                        }
                    ]
                2.Vue.set(vm.list,下标,值)
                    Vue.set(vm.list,4,{id:"010120205",text:"NOKIA"});
                3.vm.$set(vm.list,下标,值)
                    vm.$set(vm.list,4,{id:"010120205",text:"NOKIA"});
            */
            list:[  
                {
                    id:'010120201',
                    text:'Iphone'
                },
                {
                    id:'010120202',
                    text:'OPPO'
                },
                {
                    id:'010120203',
                    text:'VIVO'
                },
                {
                    id:"010120204",
                    text:'HUIWEI'
                }
            ]
        }
    }); 
</script>
</body>
</html>
案发现场3:v-for对象

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>
<body>
<div id="root">
    <!-- 其实js中对象的底层就是一个关联数组,查看页面item key index 分别表示什么 -->
    <div v-for="(item,key,index) of userInfo">
        {{key}}:{{item}}---{{index}}
    </div>
</div>
<script>
    var vm=new Vue({
        /*
            响应式的操作对象中的数据
                1.修改引用
                    vm.userInfor={
                        name:'Tom',
                        age:18,
                        car:'BYD',
                        girlFriend:false
                    }
                2.Vue.set(vm.userInfor,"address","beijing")
                3.vm.$set(vm.userInfor,"address","beijing")
        */
        el:"#root",
        data:{
            userInfo:{
                name:'Dell',
                age:28,
                gender:'male',
                salary:'secret'
            }
        }
    }); 
</script>
</body>
</html>

is属性

用于动态组件且基于 DOM 内模板的限制来工作。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>
<body>
<div id="root">
    <table border="1">
        <tbody>
            <!-- 如果直接使用子组件语法会不符合html5语法规范,会出现bug 
            可在页面审查元素查看tbody里并无tr -->
            <!-- 
            <row></row>
            <row></row>
            -->
            <!-- 使用is属性使其标签指向组件,ul,ol.select标签同理 -->
            <tr is="row"></tr>
            <tr is="row"></tr>
            <tr is="row"></tr>
        </tbody>
    </table>
</div>
<script>
    Vue.component('row',{
        template:`
            <tr>
                <td>this is a row</td>
            </tr>
        `
    });
    var vm=new Vue({
        el:"#root"
    }); 
</script>
</body>
</html>

组件参数校验

我们可以为组件的 prop 指定验证要求,例如你知道的这些类型。如果有一个需求没有被满足,则 Vue 会在浏览器控制台中警告你。这在开发一个会被别人用到的组件时尤其有帮助。
为了定制 prop 的验证方式,你可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。例如:

案发现场:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> 
</head>
<body>
<div id="app">
    <!-- content通过:绑定传递数字类型,因为绑定:表示js表达式 -->
    <child :content="123"></child>
</div>
<script>
    Vue.component('child',{
        props:{
            //1.基础校验
            // 对父组件content传递过来的数据进行校验必须为String类型
            // content:String
            // content:Number
            // content:Object
            // content:[String,Number]
            // content:null  匹配任意类型
            //2.更为严格的校验
            content:{
                type:String,
                // 父组件必须传入该类型的值
                required:true,
                // 如果父组件没有传入该类型的值时,使用默认的值
                default:"default value",
                // 自定义校验器:对父组件传入的值进行校验,字符长度大于5
                validator:function (value) {
                    return (value.length>5)
                }
        }
    },
    template:`
        <div>{{content}}</div>
    `
    });
    var vm=new Vue({
        el:"#app"   
    });
</script>
</body>
</html>

组件绑定原生事件

案发现场:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> 
</head>
<body>
<div id="app">
    <!-- 通过事件修饰符.native给组件绑定原生事件 -->
    <!-- 不加.native 监听的是自定义事件 -->
    <child @click.native="handleClick"></child>
</div>
<script>
Vue.component('child',{
    template:`
        <div>Child</div>
    `
});
var vm=new Vue({
    el:"#app",
    methods:{
        handleClick:function () {
            alert("click");
        }
    }   
});

</script>
</body>
</html>

非父子组件传值

案发现场:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>非父子组件间传值(Bus/总线/发布订阅模式/观察者模式)</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>
<body>
<div id="root">
    <child content='Dell'></child>
    <child content='Lee'></child>
</div>
<script>
    // 向Vue的prototype中加入bus方法,其他组件就可以借助bus来传递数据
    Vue.prototype.bus=new Vue();
    Vue.component('child',{
        props:{
            content:String,
            required:true,
            default:'Default Value'
        },
        data:function(){
            //父组件传递过来的数据子组件无法直接修改,所以保存副本
            return {selfContent:this.content}
        },
        template:`
            <div @click="sendData">{{selfContent}}</div>
        `,
        methods:{
            sendData:function(){
                //触发事件并发送数据
                this.bus.$emit('change',this.selfContent);
            }
        },
        mounted:function(){
            // 监听事件并响应
            var this_=this;
            this.bus.$on('change',function(msg){
                this_.selfContent=msg;
            });
        }
    });
    var vm=new Vue({
        el:"#root"
    }); 
</script>
</body>
</html>

插槽

案发现场:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Vue中的插槽(slot)</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>
<body>
<div id="root">
    <child>
        <h1>Dell</h1>
    </child>


    <body-content>
        <!-- 具名插槽 -->
        <div class="header" slot="header">header</div>
        <div class="footer" slot="footer">footer</div>
    </body-content>
</div>
<script>
    Vue.component('child',{
        template:`
            <div>
                <p>Hello Slot</p>
                <slot>当父组件没有传递插槽内容,使用此处默认内容</slot>
            </div>
        `
    });
    Vue.component('body-content',{
        template:`
            <div>
                <slot name="header">default header</slot>
                <div class="content">content</div>
                <slot name="footer">default footer</slot>
            </div>
        `
    });
    var vm=new Vue({
        el:"#root"
    }); 
</script>
</body>
</html>

作用域插槽

案发现场:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Vue中的作用域插槽(slot)</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
</head>
<body>
<div id="root">
    <child>
        <!-- template必须写固定语法 -->
        <template slot-scope="content">
            <!-- <li>{{content.item}}</li> -->
            <h1>{{content.item}}</h1>
        </template>
    </child>
</div>
<script>
    Vue.component('child',{
        data:function(){
            return {list:[1,2,3,4,5]}
        },
        template:`
            <div>
                <ul>
                    <slot v-for="item of list" :item=item></slot>
                </ul>
            </div>
        `
    });
    var vm=new Vue({
        el:"#root"
    }); 
</script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值