• 学习vue就是那么简单,一个简单的案例


        vue是前端兴起一个javascript库,相信大家都使用过jQuery,虽然vue和jQuery没有可比性,但从熟悉的角度去理解新的东西或许会容易接受一些,有时候由于思想和模式的转变会带来阵痛,但领悟到了却会有一种如何至宝的感觉。

        简单来说jQuery是操作页面的dom对象,而vue是操作页面的data数据,也就是将原来的操作dom的思想转变到操作数据上来。

        vue是一个精简的MVVM,是一套构建用户界面的渐进式框架,专注于 MVVM 模型的 ViewModel 层。它通过双向数据绑定把 View 层和 Model 层连接了起来,通过对数据的操作就可以完成对页面视图的渲染。

     vue和jQuery两者的侧重点是不一样的,所以在很多场合,我们需要结合起来使用,比如操作dom对象以及一些动画效果时,我们可以使用jQuery,在对复杂的数据操作,比如计算双向绑定,以及表单页面等,我们就可以使用vue来做更容易一些。

        作为一个会后端的前端工程师,从seo的角度来说,我更喜欢使用后端mvc模式来操作和绑定数据,而像vue,Angular,React等js库提倡的View与数据分离,其本质上依旧是在前端进行js操作,对seo都不是那么友好,在一些不需要考虑seo系统或平台上(比如移动端),我们可以怎么方便怎么来。

    学习vue,我们可以从一个应用最多的实例开始,分页数据绑定,如图:(或预览效果http://www.yealuo.com/Resource/Journal/FileUrl/38FC57B2-345B-4923-9D13-C9B201CE23BA/Index.html

    QQ截图20190506131922.png

    要用vue实现上面的效果图,如何实现呢!

    首先我们需要重构静态HTML

    <div id="app">
        <ul>
            <li><h6><a target="_blank" href="http:\www.yealuo.com/Cntv/Detail?ArticleType=WenZhang&amp;KeyValue=CD9291BC-1BA9-4FE2-B5BF-341A24998722">相忘于江湖/简媜</a></h6></li>
            <li><h6><a target="_blank" href="http:\www.yealuo.com/Cntv/Detail?ArticleType=TuHua&amp;KeyValue=70A807BD-A859-4172-9A6A-FEB21A75008F">2019419绝代尤物</a></h6></li>
            <li><h6><a target="_blank" href="http:\www.yealuo.com/Cntv/Detail?ArticleType=TuHua&amp;KeyValue=6A985247-CC73-4AA1-90D7-8D2F49896279">年少无知</a></h6></li>
            <li><h6><a target="_blank" href="http:\www.yealuo.com/Cntv/Detail?ArticleType=TuHua&amp;KeyValue=52BF13C9-1FCC-4C69-8968-4F0B96278B25">十年</a></h6></li>
            <li><h6><a target="_blank" href="http:\www.yealuo.com/Cntv/Detail?ArticleType=QingBao&amp;KeyValue=5D81C7A6-5861-4055-85BC-4356B4DD522B">关于哥哥张国荣(3)</a></h6></li>
        </ul> 
        <ul class="page-bar">
            <!----> 
            <li><a class="banclick">上一页</a></li>
            <li class="active"><a>1</a></li>
             <li class=""><a>2</a></li>
             <li><a class="">下一页</a></li>
             <!----> 
             <li><a><i>2</i></a></li>
         </ul>
     </div>
    <style type="text/css">
            
            html, body {
                width: 100%;
                font-family: "PingFang SC-Medium,sans-serif", "Noto Sans CJK SC,sans-serif", Arial, "Microsoft YaHei";
                background-color: #f5f5f5;
            }
    
           
    
            ul, ol, li {
                padding:0;margin:0;
                list-style: none;
            }
    
            [v-cloak] {
                display: none;
            }
    
            .cont-item {
                padding: 0.35rem 0.1rem;
                font-size: 0.14rem;
                color: #666;
            }
    
            .page-bar li:first-child > a {
                margin-left: 0px;
            }
    
            .page-bar a {
                border: 1px solid #ddd;
                text-decoration: none;
                position: relative;
                float: left;
                padding: 6px 12px;
                margin-left: -1px;
                line-height: 1.42857143;
                color: #337ab7;
                cursor: pointer;
            }
    
                .page-bar a:hover {
                    background-color: #eee;
                }
    
                .page-bar a.banclick {
                    cursor: not-allowed;
                }
    
            .page-bar .active a {
                color: #fff;
                cursor: default;
                background-color: #337ab7;
                border-color: #337ab7;
            }
    
            .page-bar i {
                font-style: normal;
                color: #d44950;
                margin: 0px 4px;
                font-size: 12px;
            }
    </style>

    得到我们想要的静态页面,然后就是使用vue对数据进行绑定

    在没有获取后台数据前,我们可以先实现页码单击的模拟,只需要初始化两个数据,一个总页数,一个当前页码就可以了。

    (1)实例化vue构造器

    <div id="app">
            <ul class="page-bar">
                <li v-if="page>1"><a>上一页</a></li>
                <li v-if="page==1"><a class="banclick">上一页</a></li>
                <li v-for="index in indexs" v-bind:class="{ 'active': page == index}">
                    <a>{{ index }}</a>
                </li>
                <li v-if="page!=pageTotal"><a>下一页</a></li>
                <li v-if="page == pageTotal"><a class="banclick">下一页</a></li>
                <li><a><i>{{pageTotal}}</i></a></li>
            </ul>
        </div>
    <script type="text/javascript">
          var app = new Vue({
                el: '#app',
                data: {
                    page: 1,//当前页码
                    pageTotal: 14//总页数
                },
                  computed: {
                    indexs: function () {
                        var self = this;
                        var left = 1;
                        var right = self.pageTotal;
                        var ar = [];
                        if (self.pageTotal >= 5) {
                            if (self.page > 3 && self.page < self.pageTotal - 2) {
                                left = self.page - 2
                                right = self.page + 2
                            } else {
                                if (self.page <= 3) {
                                    left = 1
                                    right = 5
                                } else {
                                    right = self.pageTotal
                                    left = self.pageTotal - 4
                                }
                            }
                        }
                        while (left <= right) {
                            ar.push(left)
                            left++
                        }
                        return ar
                    }
    
                }
    })
     </script>

    效果图如下:

    QQ截图20190506134549.png

    知识点(1):
    在上面的构造器中,我们使用到了vue的内部指令,这里罗列一下vue的内部指令有以下几种:

        1、v-bind:响应并更新DOM特性;例如:v-bind:href  v-bind:class  v-bind:title  等等,注意当属性值中出现特殊字符比如-等的时候,需要使用引号。

        2、v-on:用于监听DOM事件; 例如:v-on:click  v-on:keyup

        3、v-model:数据双向绑定;用于表单输入等;例如:<input v-model="message">

        4、v-show:条件渲染指令,为DOM设置css的style属性

        5、v-if:条件渲染指令,动态在DOM内添加或删除DOM元素

        6、v-else:条件渲染指令,必须跟v-if成对使用

        7、v-else-if:判断多层条件,必须跟v-if成对使用;

        8、v-text:更新元素的textContent;例如:<span v-text="msg"></span> 等同于 <span>{{msg}}</span>;

        9、v-html:更新元素的innerHTML;会把标签名也带上。

        10、v-for:循环指令;例如: <li v-for="book in books">{ { book.name } }</li>

        11、v-cloak:不需要表达式,这个指令保持在元素上直到关联实例结束编译;v-cloak 是一个解决初始化慢导致页面闪动的最佳实践;

        12、v-once:也是一个不需要表达式的指令,作用是定义它的元素或组件只渲染一次,包括元素或组件的所有子节点。

        首次渲染后,不再随数据的变化重新渲染,将被视为静态内容;v-once 在业务中也很少使用,当你需要进一步优化性能时,可能会用到。

        13、v-pre:不需要表达式,跳过这个元素以及子元素的编译过程,以此来加快整个项目的编译速度;例如:<span v-pre>{{ this will not be compiled }}</span>;

    知识点(2):
    上面的示例中,我们还用到了vue的计算属性,关键词是computed,在一个计算属性里可以完成各种复杂的逻辑,包括运算、函数调用等,就像上面的示例只要最终返回一个结果就可以了

        计算属性还有两个常用的依赖,一是计算属性可以依赖其他计算属性;  二是计算属性不仅可以依赖当前Vue 实例的数据,还可以依赖其他实例的数据,每一个计算属性都包含一个getter 和一个setter ,我们上面的示例是计算属性的默认用法, 只是利用了getter 来读取。

        我们可以使用 methods 来替代 computed,效果上两个都是一样的,但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行。

        假设我们有一个性能开销比较大的的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A 。

    如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。

    知识点(3):
    我们还用到了class 属性绑定,我们大多使用表达式的形式来绑定,表达式的结果类型除了字符串之外,还可以是对象。
               

    1、将 isActive 设置为 true 显示了一个绿色的 div 块,如果设置为 false 则不显示:

    <divv-bind:class="{ active: isActive }"></div>

    2、还可以在对象中传入多个属性

    <divclass="static"v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>

    3、我们也可以直接绑定数据里的一个对象

    <divv-bind:class="classObject"></div>

    4、我们可以把一个数组传给 v-bind:class 

    <divv-bind:class="[activeClass, errorClass]"></div>

    5、我们还可以使用三元表达式来切换列表中的 class :

    <divv-bind:class="[errorClass ,isActive ? activeClass : '']"></div>

     

     

    上面的示例只是做到了分页数据的计算和绑定,并没有实现页码的单击事件,接下来将从绑定事件和调用methods来实现!

    (2)绑定事件,假如我们有两个方法,一个是页码单击时调用btnClick(),一个是点击上一页下一页调用pageClick(),HTML代码如下:

    <div id="app">
            <ul class="page-bar">
                <li v-if="page>1"><a v-on:click="page--,pageClick()">上一页</a></li>
                <li v-if="page==1"><a class="banclick">上一页</a></li>
                <li v-for="index in indexs" v-bind:class="{ 'active': page == index}">
                    <a v-on:click="btnClick(index)">{{ index }}</a>
                </li>
                <li v-if="page!=pageTotal"><a v-on:click="page++,pageClick()">下一页</a></li>
                <li v-if="page == pageTotal"><a class="banclick">下一页</a></li>
                <li><a><i>{{pageTotal}}</i></a></li>
            </ul>
        </div>

    (3)在methods方法(为了区分我们可以把methods叫执行方法)中定义事件单击的方法:

    <script type="text/javascript">
          var app = new Vue({
                el: '#app',
                data: {
                    page: 1,//当前页码
                    pageTotal: 14//总页数
                },
                  computed: {
                    indexs: function () {
                        var self = this;
                        var left = 1;
                        var right = self.pageTotal;
                        var ar = [];
                        if (self.pageTotal >= 5) {
                            if (self.page > 3 && self.page < self.pageTotal - 2) {
                                left = self.page - 2
                                right = self.page + 2
                            } else {
                                if (self.page <= 3) {
                                    left = 1
                                    right = 5
                                } else {
                                    right = self.pageTotal
                                    left = self.pageTotal - 4
                                }
                            }
                        }
                        while (left <= right) {
                            ar.push(left)
                            left++
                        }
                        return ar
                    }
    
                },
                //methods方法
         methods: {
                btnClick: function(data){//页码点击事件
                    if(data != this.page){
                         this.page = data
                    }
                   console.log('正在单击'+this.page+'页'); 
                },
                pageClick: function(){
                    console.log('现在在'+this.page+'页');
                }
        }
    })
     </script>

    知识点:
    从上面的示例中我们也窥探出computed和methods的区别还有一个就是,methods方法可以直接传递参数给内部所定义的方法,两者在示例中都得到了很好的应用。
               

    效果图:

    QQ截图20190506160933.png


    接下来就是获取后台数据,获取后台数据,这里我们需要引用vue-resource 库,当然我们也可以采用其他方式,比如zepto.js等,然后$.ajax()获取,这在实际应用综合考虑,假如已经引用了一种,其他的就没必要,以减少多文件的加载!

    在这里,我们首先引进<script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>,然后再在methods方法中继续定义一个getData获取数据的方法,并且在构造器app的data中定义装数据的容器list以及每页需要条数pageSize。

    (4)定义获取数据方法

    data: {
                    list:[],
                    page: 1,//当前页码
                    pageTotal: 0,//总页数
                    pageSize: 5//每页加载条数
                }
                    getData: function () {
                        var self = this;
                        if (self.page > self.pageTotal && self.pageTotal != 0) return;
    
                        self.showLoading = true;
    
    
                        //发送get请求
                        this.$http.get("http://www.yealuo.com/YeaTool/GetTable?page=" + self.page + "&rows=" + self.pageSize).then(function (res) {
                            var data = res.body;
                                    if (data && data.start == '0') {
    
                                        if (data.pageData.total) {
    
                                            self.pageTotal = data.pageData.total;
    
                                        }
    
                                        if (self.pageTotal == 0 || !data.pageData.total) {
    
                                            self.loadTxt = '暂无数据';
    
                                        } else {
                                            if (self.list.length > 0) {
                                                self.list = data.body;
                                                //self.list = self.list.concat(data.body);//concat是追加数组或叫合并数组的方法(可用于点击加载)
    
                                            } else {
    
                                                self.list = data.body;
    
                                            }
    
                                        }
    
    
                                    } else {
    
                                        alert(data.errorMsg || "系统异常");
    
                                    }
    
                        }, function () {
                            console.log('请求失败处理');
                        });
                    }
        },

    知识点:
    说到钩子函数,我们不得不提到另外一个钩子函数created,区别在于created是在实例创建完成后挂载阶段还没开始,也就是模板还没有进行html渲染就立即调用,而mounted调用时,模板已经进行渲染,如果再实例中并没有操作页面元素,则两者可以替换使用!
               

    相应的,页码单击方法也需要调用获取数据方法:

    btnClick: function (data) {//页码点击事件
                        if (data != this.page) {
                            this.page = data
                        }
                       this.getData();
                    },
     pageClick: function () {
                      this.getData();
                    },

    (5监听属性 watch,在上面我们在单击页码的时候重复调用获取数据的方法,在vue中我们还有更好的方式,就是可以通过 watch 来响应数据的变化来执行获取数据的方法

    mounted: function () {
                    this.getData();
                },

    单击事件中的调用就可以注释掉了。

    效果查看:http://www.yealuo.com/Resource/Journal/FileUrl/38FC57B2-345B-4923-9D13-C9B201CE23BA/Index.html

    完整dome代码如下:

    <!DOCTYPE html>
    <html>
    <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
    <meta charset="utf-8">
    <title></title>
    <meta name="keywords" content="http://www.yealuo.com/" />
    <meta name="description" content="http://www.yealuo.com/" />
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
    <style type="text/css">
            
            html, body {
                 100%;
                font-family: "PingFang SC-Medium,sans-serif", "Noto Sans CJK SC,sans-serif", Arial, "Microsoft YaHei";
                background-color: #f5f5f5;
            }
    
           
    
            ul, ol, li {
                padding:0;margin:0;
                list-style: none;
            }
    
            [v-cloak] {
                display: none;
            }
    
            .cont-item {
                padding: 0.35rem 0.1rem;
                font-size: 0.14rem;
                color: #666;
            }
    
            .page-bar li:first-child > a {
                margin-left: 0px;
            }
    
            .page-bar a {
                border: 1px solid #ddd;
                text-decoration: none;
                position: relative;
                float: left;
                padding: 6px 12px;
                margin-left: -1px;
                line-height: 1.42857143;
                color: #337ab7;
                cursor: pointer;
            }
    
                .page-bar a:hover {
                    background-color: #eee;
                }
    
                .page-bar a.banclick {
                    cursor: not-allowed;
                }
    
            .page-bar .active a {
                color: #fff;
                cursor: default;
                background-color: #337ab7;
                border-color: #337ab7;
            }
    
            .page-bar i {
                font-style: normal;
                color: #d44950;
                margin: 0px 4px;
                font-size: 12px;
            }
    </style>
    </head>
    <body>
     <div id="app">
            <ul>
    
                <li v-for="item in list"><h6 v-html="item.ArticleTitle"></h6></li>
    
            </ul>
    
            <ul class="page-bar">
                <li v-if="page>1"><a v-on:click="page--,pageClick()">上一页</a></li>
                <li v-if="page==1"><a class="banclick">上一页</a></li>
                <li v-for="index in indexs" v-bind:class="{ 'active': page == index}">
                    <a v-on:click="btnClick(index)">{{ index }}</a>
                </li>
                <li v-if="page!=pageTotal"><a v-on:click="page++,pageClick()">下一页</a></li>
                <li v-if="page == pageTotal"><a class="banclick">下一页</a></li>
                <li><a>共<i>{{pageTotal}}</i>页</a></li>
            </ul>
        </div>
     <script type="text/javascript">
          var app = new Vue({
                el: '#app',
                data: {
                    list:[],
                    page: 1,//当前页码
                    pageTotal: 0,//总页数
                    pageSize: 5//每页加载条数
                },
                  computed: {
                    indexs: function () {
                        var self = this;
                        var left = 1;
                        var right = self.pageTotal;
                        var ar = [];
                        if (self.pageTotal >= 5) {
                            if (self.page > 3 && self.page < self.pageTotal - 2) {
                                left = self.page - 2
                                right = self.page + 2
                            } else {
                                if (self.page <= 3) {
                                    left = 1
                                    right = 5
                                } else {
                                    right = self.pageTotal
                                    left = self.pageTotal - 4
                                }
                            }
                        }
                        while (left <= right) {
                            ar.push(left)
                            left++
                        }
                        return ar
                    }
    
                },
                //methods方法
         methods: {
                btnClick: function (data) {//页码点击事件
                        if (data != this.page) {
                            this.page = data
                        }
                       // this.getData();
                    },
                    pageClick: function () {
                      // this.getData();
                    },
    
                    getData: function () {
                        var self = this;
                        if (self.page > self.pageTotal && self.pageTotal != 0) return;
    
                        self.showLoading = true;
    
    
                        //发送get请求
                        this.$http.get("http://www.yealuo.com/YeaTool/GetTable?page=" + self.page + "&rows=" + self.pageSize).then(function (res) {
                            var data = res.body;
                                    if (data && data.start == '0') {
    
                                        if (data.pageData.total) {
    
                                            self.pageTotal = data.pageData.total;
    
                                        }
    
                                        if (self.pageTotal == 0 || !data.pageData.total) {
    
                                            self.loadTxt = '暂无数据';
    
                                        } else {
                                            if (self.list.length > 0) {
                                                self.list = data.body;
                                                //self.list = self.list.concat(data.body);//concat是追加数组或叫合并数组的方法(可用于点击加载)
    
                                            } else {
    
                                                self.list = data.body;
    
                                            }
    
                                        }
    
    
                                    } else {
    
                                        alert(data.errorMsg || "系统异常");
    
                                    }
    
                        }, function () {
                            console.log('请求失败处理');
                        });
                    }
        },
          watch: {
                    page: function (oldValue, newValue) {
                        this.getData();//监听事件
                    }
                },
          mounted: function () {
                    this.getData();
                },
    })
     </script>
    
    
    
    </body>
    </html>


  • 相关阅读:
    JQuery实现模糊查询关键字高亮输入框
    jq--实现自定义下拉框
    js 实现颜色值格式转换 rgb和十六进制的转换
    原生JavaScript设置、获取 单选框、复选框 的值
    win10 开启端口,auto.js端口
    AES的加密和解密(Java and javascript)
    去除移动端 alert / confirm 显示的 url
    移动端拖拽
    前台传入base64图片,java后台转为MultipartFile文件
    移动端调试vConsole
  • 原文地址:https://www.cnblogs.com/boyzi/p/10824963.html
Copyright © 2020-2023  润新知