Vue初探——Vue是什么

代码部分请下载本文代码阅读,代码均能正常运行并有详细的注释。

本文代码下载地址

概述

前端开发近况
  • 需求依然旺盛,从JavaScript已经在编程语言排行榜上排到了第七位和前端聘岗位数就可以看出。
  • 加入前端开发的新手越来越多,其中女孩子比例不少,自学能力稍有匮乏
  • 前端框架层出不穷,部分前端开发精力跟不上
  • 作为一名码农最急需的是精通一门语言一个框架,然后再横向去尽量多学一些技术,有助于融会贯通,专业精通才有高收入。
写这个博客的目的
  • 希望能通过写博客分享的方式更好的学习Vue和其它前端技术
  • 希望能帮助到更多的同学更快速的学习Vue和其它前端技术
  • 希望能赚点零花钱,如果你觉得我的文章帮助到了你,请在文章最下面点打赏按钮打赏我。打赏过的同学加我qq:791831347,我拉你进我建的Vue交流群算是小小的回报吧,你在群里问的问题都会尽量得到解答,但不做任何承诺。
  • 未来也可能计划出一套视频教程
  • 让我们一起走在Vue进阶的路上吧.(这个博客我会尽量说人话少说专业术语)

Vue简述

长期以来,前端都是Jquery为王这样一个状态,虽然从业时间比较长的前沿的前端开发者可能都已经接触至少十多个框架了,但是大多数年轻的开发者可能都还只是对Jquery这样的万金油更熟悉一些,下面我会用几个小例子来说明Jquery开发和Vue这样的Mvvm框架开发模式上的不同。

用一个简单的例子来说明编写Jquery和Vue上的不同
demo1 简单修改文字
  • 点击按钮后:
    把hello,美女!欢迎学习Angular.
    改为
    hello,帅哥!欢迎学习Vue.
屏幕快照 2017-02-27 22.48.32.png
  • jquery代码(用以下代码直接替换掉html文件中的body,看不懂没关系后面会详细说道Vue的方方面面)
<div>
    <p>Hello, <span id="name">美女</span>!</p>
    <p>欢迎学习 <span id="libName">Angular</span>.</p>
    <button id = "modifyBtn">修改</button>
</div>

<script src="https://unpkg.com/jquery"></script>
<script type="text/javascript">
    $("#modifyBtn").click(function(){
        $("#name").text("帅哥");
        $("#libName").text("Vue");
    });
</script>
  • Vue代码
<div id="mycontent">
    <p>Hello, <span >{{name}}</span>!</p>
    <p>欢迎学习 <span >{{libName}}</span>.</p>
    <button v-on:click="modifyInfo" >修改</button>
</div>

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
    var vm = new Vue({
        el: "#mycontent",
        data:{
            name:"美女",
            libName:"Angular"
        },
        methods:{
            modifyInfo:function(){
                this.name = "帅哥";
                this.libName = "Vue";
            }
        }
    })
</script>
  • tips 1 Jquery首先要获取到dom对象,然后对dom对象进行进行值的修改等操作;
  • tips 2. Vue是首先把值和js对象进行绑定,然后修改js对象的值,Vue框架就会自动把dom的值就行更新。
  • tips 3. 可以简单的理解为Vue帮我们做了dom操作,我们以后用Vue就需要修改对象的值和做好元素和对象的绑定,Vue这个框架就会自动帮我们做好dom的相关操作。
  • tips 4.这种dom元素跟随JS对象值的变化而变化叫做单向数据绑定,如果JS对象的值也跟随着dom元素的值的变化而变化就叫做双向数据绑定,顾名思义单向和双向😊,后面会详细介绍。
用一个更复杂的例子来说明Vue的优势
demo2-模拟一个简易购物车
QQ20170303-144554@2x.png

下面只是展示下两种框架写出来的代码,感兴趣的同学可以把代码下下来。
-Vue代码

<div id="cart_item">
    <!-- v-for 可以根据Vue中myListArr数组的长度来生成div,其中item和index分别是每一项的值和索引 -->
     <div class="item_i" v-for="(item,index) in myListArr">
        <div class="checkbox"  >
            <!-- v-on:click绑定了check点击方法,传入了index这个参数,它是数组当前的索引,在外层div的v-for中定义过 -->
            <input type="checkbox" class="checkOne check" v-model="item.isChecked"  v-on:click="check(index)"/></div>
        <div class="good">
            <!-- 绑定了图片的地址和商品的名称,:src 是v-bind:src的简写,只要是html元素的属性值都可以用v-bind指令 -->
            <img :src ="item.pic"  />
            <span>{{item.name}}</span></div>
        <div class="price">{{item.price}}</div>
        <div class="count">
            <!-- @click 是v-on:click的简写,这里特意展示一下 -->
            <span class="reduce" @click="reduce(index)">-</span>
            <input type="text" class="count_input" v-model="item.num" />
            <span class="add" v-on:click="add(index)">+</span></div>
        <!-- 这里每一行商品总价是价格*数量,四舍五入保留两位小数 -->
        <div class="subTotal">{{(item.price* item.num).toFixed(2)}}</div>
        <div class="act">
            <span class="delete" @click= "remove(index)">删除</span></div>
    </div>
</div>

var vm = new Vue({
    el: "#cart",
    data:{
         myListArr : [
                            {
                                name:"【三只松鼠_小贱拉面丸子85gx3】休闲零食膨化小吃干脆面串烧味",
                                pic:"https://gw.alicdn.com/bao/uploaded/i1/TB16tk_KpXXXXX7XVXXXXXXXXXX_!!0-item_pic.jpg_200x200q50s150.jpg_.webp",
                                price:22.8,
                                num:2,
                                isChecked:true,

                            },
                            {
                                name:"【三只松鼠_炭烧腰果185gx2袋】坚果零食特产炒货干果腰果仁",
                                pic:"https://gw.alicdn.com/bao/uploaded/i2/TB1372RKXXXXXXnXVXXXXXXXXXX_!!0-item_pic.jpg_200x200q50s150.jpg_.webp",
                                price:42,
                                num:1,
                                isChecked:true,
                            },
                            {
                                name:"【三只松鼠_皇族牌牛奶夹心饼240g】台湾进口休闲零食夹心饼干",
                                pic:"https://gw.alicdn.com/bao/uploaded/i3/TB1UK3uOVXXXXaiaXXXXXXXXXXX_!!0-item_pic.jpg_200x200q50s150.jpg_.webp",
                                price:15.5,
                                num:3,
                                isChecked:true,

                            },
                            {
                                name:"【三只松鼠_碧根果210gx2袋】零食坚果山核桃长寿果干果奶油味",
                                pic:"https://gw.alicdn.com/bao/uploaded/i2/TB1eTzgJVXXXXcIXFXXXXXXXXXX_!!0-item_pic.jpg_200x200q50s150.jpg_.webp",
                                price:18.9,
                                num:1,
                                isChecked:true,

                            }],
         //这三个属性分别绑定的是所有商品数量、总价格、时候全选
         totalCount:0,
         totalPrice:0,
         allCheck:true,
    },
    mounted: function () {
        //这里是vue初始化完成后执行的函数,注意vue1.x版本是ready方法,如无特别说明本人使用的都是Vue2.x
        this.calTotal();
    },
    methods:{
        //每一行增加商品的方法,根据索引值修改这一项对应的数据源的值就可以了,Vue会帮你自动更新dom中相关的值
        add:function(index){
            var item = this.myListArr[index];
            item.num +=1;
            //计算总价和总件数
            this.calTotal();
        },
        //减商品
        reduce:function(index){
            var item = this.myListArr[index];
            //如果商品只有1件就不允许再减了,只能删除
            if (item.num == 1) {
                return;
            }
            item.num -= 1;
            this.calTotal();
        },
        //删除本行商品
        remove:function(index) {
            //splice 是array的批量删除方法
            this.myListArr.splice(index,1);
            this.calTotal();
        },
        //单行的checkbox选中
        check:function(index){
            var listItem = this.myListArr[index];
            this.calTotal();
            if (!listItem.isChecked) {
                //如果没有选中状态肯定是没有全选
                this.allCheck = false;
            }else {
                //如果是选中状态先把全选选中,然后再每一项遍历,如果有一项没有选中就改为非全选状态
                this.allCheck = true;

                for (var i = 0; i < this.myListArr.length; i++) {
                    var listItem1 = this.myListArr[i];
                    if (!listItem1.isChecked) {
                        this.allCheck = false;
                    }
                }
            }
        },
        //全选checkbox事件
        allCheckMethod:function(){
            //全选只需要所有的列表都跟全选状态是同一个状态就可以
            for (var i = 0; i < this.myListArr.length; i++) {
                var listItem = this.myListArr[i];
                listItem.isChecked = this.allCheck;
            }
            this.calTotal();
        },
        //计算总数
        calTotal:function(){
            //计算总件数
            this.calTotalCount();
            //计算总价格
            this.calTotalPrice();
        },
        //计算总件数
        calTotalCount: function () {
            var count = 0;
            for (var i = 0; i < this.myListArr.length; i++) {
                var listItem = this.myListArr[i];
                if (listItem.isChecked) {
                    count += listItem.num;
                }
            }
            this.totalCount = count;
        },
        //计算总价格
        calTotalPrice: function () {
            var price = 0.0;
            for (var i = 0; i < this.myListArr.length; i++) {
                var listItem = this.myListArr[i];
                if (listItem.isChecked) {
                     price = price + listItem.num * listItem.price;
                }
            }
            this.totalPrice = price;
        }
    },
});
  • Jquery代码
$(function(){
        //这里模拟数据,实际中是ajax请求网络数据,并没有太大差异
        var myListArr = [{
                            name:"【三只松鼠_小贱拉面丸子85gx3】休闲零食膨化小吃干脆面串烧味",
                            pic:"https://gw.alicdn.com/bao/uploaded/i1/TB16tk_KpXXXXX7XVXXXXXXXXXX_!!0-item_pic.jpg_200x200q50s150.jpg_.webp",
                            price:22.8,
                            num:2,},
                        {
                            name:"【三只松鼠_炭烧腰果185gx2袋】坚果零食特产炒货干果腰果仁",
                            pic:"https://gw.alicdn.com/bao/uploaded/i2/TB1372RKXXXXXXnXVXXXXXXXXXX_!!0-item_pic.jpg_200x200q50s150.jpg_.webp",
                            price:42,
                            num:1,},
                        {
                            name:"【三只松鼠_皇族牌牛奶夹心饼240g】台湾进口休闲零食夹心饼干",
                            pic:"https://gw.alicdn.com/bao/uploaded/i3/TB1UK3uOVXXXXaiaXXXXXXXXXXX_!!0-item_pic.jpg_200x200q50s150.jpg_.webp",
                            price:15.5,
                            num:3,},
                        {
                            name:"【三只松鼠_碧根果210gx2袋】零食坚果山核桃长寿果干果奶油味",
                            pic:"https://gw.alicdn.com/bao/uploaded/i2/TB1eTzgJVXXXXcIXFXXXXXXXXXX_!!0-item_pic.jpg_200x200q50s150.jpg_.webp",
                            price:18.9,
                            num:1,}];
        //每个列表项对应的html代码,实际情况中只要先把html写好然后拷贝去空格就好
        var listItemCodeStr = '<div class="item_i"><div class="checkbox"><input type="checkbox" class="checkOne check" checked="checked"></div><div class="good">![]( 1.jpg)<span>xxxxxxx</span></div><div class="price">0</div><div class="count"><span class="reduce">-</span><input type="text" class="count_input" value="1"><span class="add">+</span></div><div class="subTotal">0</div><div class="act"><span class="delete">删除</span></div></div>';

        //根据数据来添加每一项列表到dom上
        for (var i = 0; i < myListArr.length; i++) {
            //生成的列表项dom元素
            var jqueryListItem = $(listItemCodeStr);
            //对应列表项数据
            var listItemData = myListArr[i];

            //用数据填充dom列表项
            fillListWithData(jqueryListItem,listItemData)

            //把列表项添加到dom上
            $("#cart_item").append(jqueryListItem);
        }

        //跟两个全选check-box加事件
        $('.checkAll').click(function(event) {
            var checkList = $(".checkOne");
            var checkAllList = $(".checkAll");

            //让另一个按钮也全选或者也不全选保持同步
            for (var i = 0; i < checkAllList.length; i++) {
                checkAllList.get(i).checked = this.checked;
            }

            for (var i = 0; i < checkList.length; i++) {
                //如果当前项和全选项不一样则执行选中单行操作
                if (checkList.get(i).checked != this.checked) {
                    checkList.get(i).click();
                }
            }
        });

    });
//返回每一行的数据
    function getTotalCountAndPrice (item) {
        var count_input = parseInt(item.find(".count_input").eq(0).val());
        var price = parseFloat(parseFloat(item.find(".price").eq(0).text()).toFixed(2));
        var totalPrice = parseFloat((count_input*price).toFixed(2));

        var jsonData = {"count":count_input,"price":price,"totalPrice":totalPrice};
        return jsonData;
    }
//每一个商品的总价
    function getSubTotal(item){
        var listData = getTotalCountAndPrice(item);     
        item.find('.subTotal').eq(0).html(listData.totalPrice);
    }
//根据每一行的数据传入修改所有商品总价格和总件数
    function updateTotal(item,count){
        var listData = getTotalCountAndPrice(item);     
        var listPrice = listData.price;

        var totalPrice = parseFloat($("#totalPrice").eq(0).text());
        var totalCount = parseInt($("#totalCount").eq(0).text());

        $("#totalPrice").text((totalPrice + count * listPrice ).toFixed(2));
        $("#totalCount").text((totalCount + count ));
    }
//根据列表项数据填充列表项和总价总数量
    function fillListWithData(jqueryListItem,listItemData){
        //首次跟一行列表赋值(一个商品)
        jqueryListItem.find('img').eq(0).attr('src', listItemData.pic);
        jqueryListItem.find('span').eq(0).html(listItemData.name);
        jqueryListItem.find('.price').eq(0).html(listItemData.price);
        jqueryListItem.find('.count_input').eq(0).val(listItemData.num);
        //计算一行的总价格
        getSubTotal(jqueryListItem);
        //减商品个数的事件
        jqueryListItem.find('.reduce').click(function(event) {
            //个数输入框,因为会取值赋值用到几次,所以提出来作变量
            var count_inputOBJ =  $(this).parent().find('.count_input').eq(0);
            var count_input = parseInt(count_inputOBJ.val());
            //输入框的值为1就不允许再减个数了,输入框最小值为1
            if (count_input == 1) {
                return;
            }
            count_input -= 1;
            count_inputOBJ.val(count_input);
            //更新每一行的总价格
            getSubTotal($(this).parent().parent());
            var itemCheck = $(this).parent().parent().find(".checkOne").get(0);
            if (itemCheck.checked) {
                //如果这个商品勾选了应该更新整个总价格和总数量
                updateTotal($(this).parent().parent(),-1);
            }
        });
        //增加商品个数的事件,代码同减商品个数不注释
        jqueryListItem.find('.add').click(function(event) {
            var count_inputOBJ =  $(this).parent().parent().find('.count_input').eq(0);
            var count_input = parseInt(count_inputOBJ.val());
            count_input += 1;
            count_inputOBJ.val(count_input);
            getSubTotal($(this).parent().parent());
            var itemCheck = $(this).parent().parent().find(".checkOne").get(0);
            if (itemCheck.checked) {
                updateTotal($(this).parent().parent(),1);
            }
        });
        //删除某个商品的事件,代码同加减商品个数不注释
        jqueryListItem.find('.delete').click(function(event) {

            var itemCheck = $(this).parent().parent().find(".checkOne").get(0);
            if (itemCheck.checked) {
                var count_inputOBJ =  $(this).parent().parent().find('.count_input').eq(0);
                updateTotal($(this).parent().parent(),- parseInt(count_inputOBJ.val()));
            }
            $(this).parent().parent().remove();
        });
        //跟列表项的check-box加事件
        jqueryListItem.find('.checkOne').click(function(event) {
            var listData = getTotalCountAndPrice($(this).parent().parent());
            if (this.checked) {
                //加上勾选项数量和价格
                updateTotal($(this).parent().parent(),listData.count);
                //遍历看是否是全选
                var checkList = $(".checkOne");
                var checkAllList = $(".checkAll");

                var allCheckTag = true ;
                for (var i = 0; i < checkList.length; i++) {
                    var checkItem = checkList.get(i);
                    if (!checkItem.checked) {
                        allCheckTag = false;
                        break;
                    }
                }
                if (allCheckTag) {
                    for (var j = 0; j < checkAllList.length; j++) {
                        checkAllList.get(j).checked = true;
                    }
                }
            }else {
                //减去勾选项
                updateTotal($(this).parent().parent(),-listData.count);
                //去掉全选
                var checkAllList = $(".checkAll");
                for (var j = 0; j < checkAllList.length; j++) {
                    checkAllList.get(j).checked = false;
                }

            }
        });
        //初始化总价,每循环一个列表项就应该把总数总价格更新下
         updateTotal(jqueryListItem,listItemData.num);
    }
总结

如果你有认真写一下以下代码,可能你会在再做类似的项目的时候再也不想使用Jquery,下面做一下对比:
1.由于Vue帮我们省略了dom操作,代码变得比较简洁,逻辑更加清晰。
2.还是由于Vue帮我们省略了dom操作,加上双向数据绑定,Vue的代码量减少很多,大概2/3(还是要看具体项目)。
3.Jquery 专注于dom操作,步骤一般为:获取dom元素--> 跟dom元素赋值+加事件-->插入dom元素。 其中dom元素赋值和加事件又需要获取dom元素和更dom元素赋值,也就是这个原因代码量才会增加。Vue专注于数据:用户只需要关注dom元素值对应绑定的数据,每次dom需要修改只需要去修改数据就可以了。
4.由于多个dom事件可能会同时修改一个元素的值,Vue只需要关注元素对应绑定的数据就可以了,这使得Vue在逻辑上会更加清晰

读完这篇文章我希望您已经学会了:

1.知道Vue是以数据为中心的,你只需要关注数据,比类Jquery的优势在于去dom操作和双线数据绑定。
2.知道Vue.js的基本写法,例如怎么引入vue.js,怎么声明Vue实例,实例中能挂载的参数有el、methods,data等,el、methods、data又分别表示什么,methods内部的方法this可以引用Vue实例等等
3.了解到基本的Vue指令,比如v-model、v-on:click、@click、v-for、v-bind:src、:src,还有{{}}和@click方法里面可以传参等等
4.最后希望你能把这个demo好好敲一敲,不管你理不理解代码,熟练是学好一个框架的第一步,看再多听再多,不如好好写一下,有问题留言。

如果您觉得这篇文章对您有帮助,请打赏一下或去github上给个❤️,thanks。

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

推荐阅读更多精彩内容

  • 下载安装搭建环境 可以选npm安装,或者简单下载一个开发版的vue.js文件 浏览器打开加载有vue的文档时,控制...
    冥冥2017阅读 6,021评论 0 42
  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,716评论 0 33
  • 单例模式 适用场景:可能会在场景中使用到对象,但只有一个实例,加载时并不主动创建,需要时才创建 最常见的单例模式,...
    Obeing阅读 2,046评论 1 10
  • 2014年6月,没有蝉声却依旧燥热,一场离别,迷醉在一次次的杯起杯落中,那一次的挥别,竟成为了心里来不及拥抱的那一...
    那抹笑靥如花却凉了一季阅读 605评论 0 0
  • 凌晨两点的清醒, 不一定是对人类灵魂的最后坚守 或许是有些东西想不透 释迦牟尼说:不可说清,不可说破 其实天机不一...
    八月锋芒尽阅读 144评论 0 0