Vue基础技能【二、计算属性、监听器、样式处理、本地存储、$set方法】

1、事件简写和template标签

1.1、事件简写

<button @click="nums+=100">100</button>
data:{ // 数据
  nums:2000
}
// 适用于简单的运算

1.2、template标签

  • 作用: 当我们的循环或者if判断的时候,内部的内容不是一个容器标签包裹。

     <template v-for="item in arr">
       <div class="li">{{item}}</div>
       <p>对的{{item}}</p>
     </template>
    // 不会产生真的标签,只帮助我们进行渲染
    

2、计算属性

  • 作用:不是直接展示data中的数据,而是对data中的数据进行一些处理后在进行展示。 计算属性帮助我们对data中的数据进行一些处理

  • 本质:属性,和data中的变量是一样的。 也是直接挂在Vue实例上面的属性。

  • 写法:

    computed:{ // 计算属性
      add:function(){
        return 3333
      },
        revstr(){
          return this.str.split("").reverse().join("")
        }
    },
      // 渲染
    {{ add }}
    <hr>
    {{revstr}}
    
  • 注意: 值是一个函数,而且这个函数一定要有返回值,不然这个计算属性就为空

  • 计算属性和方法的区别: 计算属性是依赖于缓存的,数据不变,不会更新。方法就必须每次调用。

3、监听器

  • 作用:对data中的数据或者computed里面的计算属性进行监听,只要是this上面的属性都可以监听。

  • 写法:

    data:{
      nums:200
    },
    watch:{
      nums:function(newVal,oldVal){  // 第一个形参是新值,第二个形参是旧值  【浅监听】
        console.log("nums变化了");
      }
    }
    // 修改
    <button @click="nums+=100">改变</button>
    
  • 注意: 监听的数据是基本数据类型还是引用数据类型。如果是基本数据类型,那么可以像上面这么书写,如果是引用数据类型(对象和数组)就要注意,我们需要使用深监听。

    data:{ // 数据
      nums:200,       // 基本数据类型
      obj:{           // 引用数据类型
          name:"张飞",
          age:20
      }
    },
    watch:{  // 监听器  (监听data中的数据或者计算属性的变化)
      nums:function(newVal,oldVal){  // 第一个形参是新值,第二个形参是旧值
        console.log("nums变化了");
      },
      obj:{
          deep:true,  // 深监听
          handler:function(newVal){
             console.log(newVal.age);
          }
      }
    },
    

4、样式处理

4.1、操作class

  • 对象语法

    <h3 :class="{active:isActive,title:hasTitle,'text-box':hasBox}">222</h3>
    data:{
      isActive:true,
      hasTitle:true,
      hasBox:true,
    },
    // active 和 text-box  和 title 是class名称。
    // isActive,hasTitle,hasBox 是data中的变量,决定要不要用,这个class
      
    // 简写:  
    <h3 :class="classObj">222</h3>
     data:{        
       classObj:{
         header:true,
        'tit-nav':true,  // class名带有-或者_ 那么我们需要用引号
         error:false
       }
     },
    
  • 数组语法

    <h4 :class="[aaa,bbb]">3333333</h4>   // aaa,bbb是变量,对应的值是class名
    data:{
      aaa:"box",
      bbb:"title"
    }
    

4.2、操作syle

  • 对象语法

    <h1 :style="{color:mycolor,fontSize:nums}">标题</h1>
    data:{  // 对象的属性名是css样式属性名,对象的属性值是 css的样式属性值
      mycolor:"red",
      nums:"20px"
    }
    
    // 简写
    
    <h1 :style="styleObj">标题</h1>
    data:{
      styleObj:{
         color:"red",
        fontSize:"20px"  // 注意驼峰命名
      }
    }
    
  • 数组语法

    <p :style="[aa,bb]">2222</p>
    data:{
      aa:{
        width:"20px",
          height:"20px",
            backgroundColor:"#ddd"
      },
      bb:{
          fontSize:"50px"
      }
    }
    

4.3、三木操作class(推荐)

  • 本质:还是操作class,建议大家操作class,因为我们讲究行为结构表现三者分离

  • 使用:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <style>
            .box{
                border: 4px solid blue;
                text-align: center;
                line-height: 40px;
            }
            .active{
                background-color: red;
                color: #fff;
            }
    
        </style>
    </head>
    <body>
        <div id="app">
           <h3 :class="state?'active box':'box'" @click="state=!state">中原一点红</h3>
        </div>    
    </body>
    <script>
        new Vue({
            el:"#app",
            data:{
               state:false
            },
            computed:{},
            watch:{},
            methods:{}
        })
    // 行为(JS) 、结构(HTML)  、表现(CSS)
        // 三者分离
    
    </script>
    </html>
    

5、本地存储

  • 介绍:localStorage 持久存在,页面关闭了,再打开依旧存在,sessionStorage 会话存储,页面关闭了,打开就不存在。

  • 方法:

    // 存
    localStorage.setItem(key,value);
    // 取
    localStorage.getItem(key);
    // 删一个
    localStorage.removeItem(key);
    // 删所有
    localStorage.clear();
    
  • 使用:

    		// 存
        // setItem(key,val)
        // localStorage.setItem('hello',20)
    
        // 取
        // getItem(key)
        let res = localStorage.getItem('hello');
        console.log(res);
    
        // 删一个
        // removeItem(key)
        // localStorage.removeItem('lastname');
    
        // 删除所有
        // localStorage.clear();
    
  • 作用:

    • 用户登录信息的存储

    • 历史搜索记录

    • 重要作用:实现页面之间的传值

6、跨页面之间传值

  • 原因: 因为二级页面,或者三级页面,等下级页面肯定是需要从上一级页面传递一个关键字段数据过来,比如文章详情一定要接收文章的id,文章列表,一定要接收文章的分类。

  • 如何实现跨页面之间的传值

    • URL传参
    • localStorage传值

6.1、URL传参

AA页面
<!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="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <ul>
            <li v-for="(item,index) in arr" :key="index">
                <h3><a :href="'10、bb.html?id='+item.id">{{item.title}}</a></h3> 
            
                <p>{{item.description}}</p>
                <img  width="100px" :src="item.picimg[0].url" alt="">
            </li>
        </ul>
    </div>
</body>
<script>
    let vm = new Vue({
        el:"#app",
        data:{
            arr:[]
        },
        methods:{
           
        }
    })
    let ajax = new XMLHttpRequest();
    ajax.open("GET","http://122.51.249.55:3030/api/article?act=getlist");
    ajax.send();
    ajax.onload = function(){
        console.log(ajax);
        let data = JSON.parse(ajax.response);
        console.log(data);
        vm.arr = data.data
    }


    //  跨页面之间传值
        // url上面的search传值
        // localStorage 


</script>
</html>
BB 页面
<!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="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        
        <h3>{{article.title}}</h3>
        <img :src="article.picimg[0].url" alt="">
        <div v-html="article.content"></div>
    </div>
</body>
<script>
    // url上面获取传入的值
     let id = location.search.split("=")[1]
     console.log(id);
    
  
    
    let vm =new Vue({
        el:"#app",
        data:{
            article:""
        }
    })
    let ajax = new XMLHttpRequest();
    ajax.open("GET",`http://122.51.249.55:3030/api/article?act=find&id=${id}`);
    ajax.send();
    ajax.onload = function(){
        console.log(ajax);
        let data = JSON.parse(ajax.response);
        console.log(data);
        vm.article = data.data
    }
</script>
</html>

6.2、 本地存储传值

AA页面
<!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="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <ul>
            <li v-for="(item,index) in arr" :key="index">
               
                <h3 @click="go(item.id)">{{item.title}}</h3>
                <p>{{item.description}}</p>
                <img  width="100px" :src="item.picimg[0].url" alt="">
            </li>
        </ul>
    </div>
</body>
<script>
    let vm = new Vue({
        el:"#app",
        data:{
            arr:[]
        },
        methods:{
            go(id){
                console.log(id);
                window.localStorage.setItem("articleid",id)
                location.href = "10、bb.html"
            }
        }
    })
    let ajax = new XMLHttpRequest();
    ajax.open("GET","http://122.51.249.55:3030/api/article?act=getlist");
    ajax.send();
    ajax.onload = function(){
        console.log(ajax);
        let data = JSON.parse(ajax.response);
        console.log(data);
        vm.arr = data.data
    }


    //  跨页面之间传值
        // url上面的search传值
        // localStorage 


</script>
</html>
BB页面
<!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="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        
        <h3>{{article.title}}</h3>
        <img :src="article.picimg[0].url" alt="">
        <div v-html="article.content"></div>
    </div>
</body>
<script>
    
    // 本次存储拿
    let id = localStorage.getItem("articleid")
    
    let vm =new Vue({
        el:"#app",
        data:{
            article:""
        }
    })
    let ajax = new XMLHttpRequest();
    ajax.open("GET",`http://122.51.249.55:3030/api/article?act=find&id=${id}`);
    ajax.send();
    ajax.onload = function(){
        console.log(ajax);
        let data = JSON.parse(ajax.response);
        console.log(data);
        vm.article = data.data
    }
</script>
</html>

7、填坑(修改对象和数组页面不更新)

  • 问题描述:

    • 当我们修改data中数组变量中的某一个值得时候(如: this.arr[1]=‘xx值’), 页面不会实现数据更新
    • 当我们给data中的对象变量添加一个新的属性的时候,页面不会响应更新
    • 当我们修改data中的对象变量中的某个属性的时候(属性值是引用数据类型),同样也不会响应
  • 解决问题:

    • 数组的问题: 使用数组常用的API方法,如push,pop,shift,unshift,splice
    • 对象的问题: vue中本身存在的一个方法 this.$set(数组/对象,下标/属性名,值)
  • 代码:

    <!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="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <ul>
                <li v-for="(item,index) in arr" :key="index">{{index}}===={{item}}</li>
            </ul>
            <button @click="change">将第二个改成'Vue'</button>
            <hr>
            {{person}}
            <button @click="addsex">添加一个sex属性</button>
    
    
        </div>
    </body>
    <script>
        let vm = new Vue({
            el:"#app",
            data:{
               arr:['轮播图','ajax','tab切换','node.js'],
               person:{
                   name:"李寻欢",
                   desc:"小李飞刀",
                   age:20,
                   friend:[]
               }
            },
            methods:{
                change(){
                    // this.arr[1] = 'vue'   // 不响应
                    // this.arr[this.arr.length] = '添加的'  // 不响应
                    // this.arr.splice(1,1,'Vue')
                    // this.arr.push('添加的');
                    // console.log(this.arr);
                    this.$set(this.arr,1,'vue')
                },
                addsex(){
                    // this.person.sex = "公的"  // 不响应
                    this.$set(this.person,'sex','公的')
                    console.log(this.person);
                    
                }
            }
        })
    
        console.log(vm);
       
    
    </script>
    </html>
    

8、原生购物车功能

  • 功能

    
    		// 功能需求:  
        //   数量加减变化
        //   数量加减变化  小计变化
        //   数量加减变化  该行选中
        //   数量加减变化  总数,总价变化
        //   选中变化  总数,总价变化,全选变化
        //   全选变化  选中,总价都变化
        //   删除变化
    
  • 代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>原生JS实现购物车功能</title>
    </head>
    <body>
        <table align="center" width="600" border="1">
            <thead>
                <tr>
                    <td>全选 <input type="checkbox" class="allcheck"></td>
                    <td>名称</td>
                    <td>价格</td>
                    <td>数量</td>
                    <td>小计</td>
                    <td>操作</td>
                </tr>
            </thead>
            <tbody>
    
            </tbody>
            <tfoot>
                <tr>
                    <td>
                        全选 <input type="checkbox" class="allcheck">
                    </td>
                    <td colspan="5" style="text-align: right;"><span>0 </span> 件商品,共计 <span>0.00</span><button>立即结算</button>
                    </td>
                </tr>
            </tfoot>
        </table>
    </body>
    <script>
        //数据
        let data = [
            {
                title:"苹果6",
                price:2000,
                nums:1
            },
            {
                title:"华为p30",
                price:4000,
                nums:1
            },
            {
                title:"vivo X9",
                price:3000,
                nums:1
            },
            {
                title:"oppro R9",
                price:3000,
                nums:1
            }
        ]
    
        // 渲染数据
        let htmlstr = ""
        for (let index = 0; index < data.length; index++) {
            htmlstr += `
                <tr>
                    <td><input class="check" type="checkbox"></td>
                    <td>${data[index].title}</td>
                    <td class="price">${data[index].price}</td>
                    <td>
                        <button class="jian">-</button>
                        <input type='text' class="nums" value='${data[index].nums}' style="width:40px;text-align:center;" />
                        <button class="add">+</button>
                    </td>
                    <td class="xj">${data[index].nums*data[index].price}</td>
                    <td>
                        <button class="del">删除</button>
                    </td>
                </tr>
            `
        }
        document.querySelector("tbody").innerHTML = htmlstr
    
    // 功能需求:  
        //   数量加减变化
        //   数量加减变化  小计变化
        //   数量加减变化  该行选中
        //   数量加减变化  总数,总价变化
        //   选中变化  总数,总价变化,全选变化
        //   全选变化  选中,总价都变化
        //   删除变化
    
    
    // 数量加减变化
        // 数量加变化
        var add = document.querySelectorAll(".add");
        for (var index = 0; index < add.length; index++) {
            add[index].onclick = function(){
                var nums = this.parentNode.children[1].value;
                nums++;
                this.parentNode.children[1].value = nums;
                rowChange(this.parentNode.parentNode);
            }
        }
    
        // 减少变化
        var jian = document.querySelectorAll(".jian");
        for (var index = 0; index < jian.length; index++) {
            jian[index].onclick = function(){
                var nums = this.parentNode.children[1].value;
                if(nums==1){
                    return;
                }
                nums--;
                this.parentNode.children[1].value = nums;
                rowChange(this.parentNode.parentNode);
            }
        }
        // 小计价格变化
        function rowChange(dom){
            var price = dom.querySelector(".price").innerHTML;
            var nums = dom.querySelector(".nums").value;
            dom.querySelector(".xj").innerHTML = price*nums;
            dom.querySelector(".check").checked = true;
            isAllCheck();
        }
    
        // 单选变化
        var check = document.querySelectorAll("tbody .check")
        for (let index = 0; index < check.length; index++) {
            check[index].onclick = function(){
                isAllCheck();
            }
        }
    
    
        // 全选变化
        var allcheck = document.querySelectorAll(".allcheck");
        for (let index = 0; index < allcheck.length; index++) {
            allcheck[index].idx = index;
            allcheck[index].onclick = function(){
                // 获取tbody里面的单选框
                var check = document.querySelectorAll("tbody .check");
                for (let k = 0; k <check.length; k++) {
                    check[k].checked = this.checked                
                }
                if(this.idx==0){
                    allcheck[1].checked = this.checked
                }else{
                    allcheck[0].checked = this.checked
                }
                allInfo();
            }
        }
    
        // 全选判断
        function isAllCheck(){
            // 判断是否所有的都被选中
            let state = true;
            var check = document.querySelectorAll("tbody .check")
            for (let k = 0; k < check.length; k++) {
                if(!check[k].checked){  // 如果是false的时候
                    state = false;
                    break;
                }
            }
            if(check.length==0){
                state = false;
            }
            var allcheck =   document.querySelectorAll(".allcheck");
            allcheck[0].checked = allcheck[1].checked = state;
            allInfo(); // 总计
        }
    
        // 总计 变化
        function allInfo(){
            var allnum = 0;
            var allprice =0;
            var check = document.querySelectorAll("tbody .check");
            for (let k = 0; k <check.length; k++) {
               if(check[k].checked){
                   allnum++;
                   var price =  check[k].parentNode.parentNode.querySelector(".xj").innerHTML;
                   allprice +=  (price*1)
               }           
            }
            document.querySelectorAll("tfoot span")[0].innerHTML = allnum
            document.querySelectorAll("tfoot span")[1].innerHTML = allprice
        }
    
        // 删除
        var del =  document.querySelectorAll(".del")
        for (let index = 0; index < del.length; index++) {
            del[index].onclick = function(){
                var tb = this.parentNode.parentNode.parentNode;
                var tr = this.parentNode.parentNode;
                tb.removeChild(tr);
                isAllCheck();
            }        
        }
    
    </script>
    </html>
    
    // dom查找麻烦
    // 逻辑关系比较麻烦
    
发布了10 篇原创文章 · 获赞 0 · 访问量 133

猜你喜欢

转载自blog.csdn.net/qq_32620027/article/details/104374593
今日推荐