vue快速入門的三個小例項

守候i發表於2017-11-27

1.前言

用vue做專案也有一段時間了。但是關於vue入門基礎的文章,我還沒有寫過,那麼今天就寫vue入門的三個小例項,這三個小例項是我剛接觸vue的時候的練手作品,難度從很簡單到簡單,都是入門級的。希望能幫到大家更好的學習和了解vue,也是讓自己能夠複習一下vue。如果發現文章寫得有什麼不好,寫錯了,或者有什麼建議!歡迎大家指點迷津!

1.本篇文章使用的vue版本是2.4.2,可能會和新版有不一樣的地方,大家要注意。
2.現在我也是假設您有基礎的html,css,javascript的知識,也已經看過了官網的基本介紹,對vue有了一個大概的認識了,瞭解了常用的vue指令(v-model,v-show,v-if,v-for,v-on,v-bind等)!如果剛接觸前端的話,你看著文章可能會蒙圈,建議先學習基礎,掌握了基礎知識再來看!
3.下面的例項,建議大家邊看文章邊動手做!這樣思路會非常清晰,不易混亂!也不會覺得文章長(文章長是為了讓大家看得更資訊,貼了很多重複的程式碼,這些程式碼。html,css等完全可以跳過看)。如果只看文章,你可能未必會看完,因為文章我講得比較細,比較長!
4.這幾個例項,摘自我自己的平常練習的專案,程式碼已經提到github上面了(vue-demos)。歡迎大家star。!

2.什麼是vue

vue是現在很火的一個前端MVVM框架,它以資料驅動和元件化的思想構建,與angular和react並稱前端三大框架。相比angular和react,vue更加輕巧、高效能、也很容易上手。大家也可以移步,看一下vue的介紹和核心功能官網介紹。簡單粗暴的理解就是:用vue開發的時候,就是運算元據,然後vue就會處理,以資料驅動去改變DOM(不知道有沒有理解錯,理解錯了指點下)。
下面就是一個最簡單的說明例子

程式碼如下

html

<div id="app">
  <p>{{ message }}</p>
  <input v-model="message">
</div>複製程式碼

js

new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})複製程式碼

vue快速入門的三個小例項

相信也不難理解,就是input繫結了message這個值,然後在input修改的時候,message就改了,由於雙向繫結,同時頁面的html({{ message }})進行了修改!
好,下面進入例子學習!

3.選項卡

執行效果

vue快速入門的三個小例項

原理分析和實現

這個很簡單,無非就是一個點選切換顯示而已。但是大家也要實現。如果這個看明白了,再看下面兩個!這個例項應該只是一個熱身和熟悉的作用!

這個的步驟只有一步,原理也沒什麼。我直接在程式碼打註釋,看了註釋,大家就明白了!

完整程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<style>
    body{
        font-family:"Microsoft YaHei";
    }
    #tab{
        width: 600px;
        margin: 0 auto;
    }
    .tab-tit{
        font-size: 0;
        width: 600px;
    }
    .tab-tit a{
        display: inline-block;
        height: 40px;
        line-height: 40px;
        font-size: 16px;
        width: 25%;
        text-align: center;
        background: #ccc;
        color: #333;
        text-decoration: none;
    }
    .tab-tit .cur{
        background: #09f;
        color: #fff;
    }
    .tab-con div{
        border: 1px solid #ccc;
        height: 400px;
        padding-top: 20px;
    }
</style>
<body>
<div id="tab">
    <div class="tab-tit">
        <!--點選設定curId的值  如果curId等於0,第一個a新增cur類名,如果curId等於1,第二個a新增cur類名,以此類推。新增了cur類名,a就會改變樣式 @click,:class ,v-show這三個是vue常用的指令或新增事件的方式-->
        <a href="javascript:;" @click="curId=0" :class="{'cur':curId===0}">html</a>
        <a href="javascript:;" @click="curId=1" :class="{'cur':curId===1}">css</a>
        <a href="javascript:;" @click="curId=2" :class="{'cur':curId===2}">javascript</a>
        <a href="javascript:;" @click="curId=3" :class="{'cur':curId===3}">vue</a>
    </div>
    <div class="tab-con">
        <!--根據curId的值顯示div,如果curId等於0,第一個div顯示,其它三個div不顯示。如果curId等於1,第二個div顯示,其它三個div不顯示。以此類推-->
        <div v-show="curId===0">
            html<br/>
        </div>
        <div v-show="curId===1">
            css
        </div>
        <div v-show="curId===2">
            javascript
        </div>
        <div v-show="curId===3">
            vue
        </div>
    </div>
</div>
</body>
<script src="vue.min.js"></script>
<script>
    new Vue({
        el: '#tab',
        data: {
            curId: 0
        },
        computed: {},
        methods: {},
        mounted: function () {
        }
    })
</script>
</html>複製程式碼

4.統計總價

執行效果

vue快速入門的三個小例項

原理分析和實現

首先,還是先把佈局寫好,和引入vue,準備vue例項,這個不多說,程式碼如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .fl{
            float: left;
        }
        .fr{
            float: right;
        }
       blockquote, body, dd, div, dl, dt, fieldset, form, h1, h2, h3, h4, h5, h6, img, input, li, ol, p, table, td, textarea, th, ul {
            margin: 0;
            padding: 0;
        }
       .clearfix{
          zoom: 1;
       }
        .clearfix:after {
            clear: both;
        }
        .clearfix:after {
            content: '.';
            display: block;
            overflow: hidden;
            visibility: hidden;
            font-size: 0;
            line-height: 0;
            width: 0;
            height: 0;
        }
        a{
            text-decoration: none;
            color: #333;
        }
        img{vertical-align: middle;}
        .page-shopping-cart {
            width: 1200px;
            margin: 50px auto;
            font-size: 14px;
            border: 1px solid #e3e3e3;
            border-top: 2px solid #317ee7; }
        .page-shopping-cart .cart-title {
            color: #317ee7;
            font-size: 16px;
            text-align: left;
            padding-left: 20px;
            line-height: 68px; }
        .page-shopping-cart .red-text {
            color: #e94826; }
        .page-shopping-cart .check-span {
            display: block;
            width: 24px;
            height: 20px;
            background: url("shopping_cart.png") no-repeat 0 0; }
        .page-shopping-cart .check-span.check-true {
            background: url("shopping_cart.png") no-repeat 0 -22px; }
        .page-shopping-cart .td-check {
            width: 70px; }
        .page-shopping-cart .td-product {
            width: 460px; }
        .page-shopping-cart .td-num, .page-shopping-cart .td-price, .page-shopping-cart .td-total {
            width: 160px; }
        .page-shopping-cart .td-do {
            width: 150px; }
        .page-shopping-cart .cart-product-title {
            text-align: center;
            height: 38px;
            line-height: 38px;
            padding: 0 20px;
            background: #f7f7f7;
            border-top: 1px solid #e3e3e3;
            border-bottom: 1px solid #e3e3e3; }
        .page-shopping-cart .cart-product-title .td-product {
            text-align: center;
            font-size: 14px; }
        .page-shopping-cart .cart-product-title .td-check {
            text-align: left; }
        .page-shopping-cart .cart-product-title .td-check .check-span {
            margin: 9px 6px 0 0; }
        .page-shopping-cart .cart-product {
            padding: 0 20px;
            text-align: center; }
        .page-shopping-cart .cart-product table {
            width: 100%;
            text-align: center;
            font-size: 14px; }
        .page-shopping-cart .cart-product table td {
            padding: 20px 0; }
        .page-shopping-cart .cart-product table tr {
            border-bottom: 1px dashed #e3e3e3; }
        .page-shopping-cart .cart-product table tr:last-child {
            border-bottom: none; }
        .page-shopping-cart .cart-product table .product-num {
            border: 1px solid #e3e3e3;
            display: inline-block;
            text-align: center; }
        .page-shopping-cart .cart-product table .product-num .num-do {
            width: 24px;
            height: 28px;
            display: block;
            background: #f7f7f7; }
        .page-shopping-cart .cart-product table .product-num .num-reduce span {
            background: url("shopping_cart.png") no-repeat -40px -22px;
            display: block;
            width: 6px;
            height: 2px;
            margin: 13px auto 0 auto; }
        .page-shopping-cart .cart-product table .product-num .num-add span {
            background: url("shopping_cart.png") no-repeat -60px -22px;
            display: block;
            width: 8px;
            height: 8px;
            margin: 10px auto 0 auto; }
        .page-shopping-cart .cart-product table .product-num .num-input {
            width: 42px;
            height: 28px;
            line-height: 28px;
            border: none;
            text-align: center; }
        .page-shopping-cart .cart-product table .td-product {
            text-align: left;
            font-size: 12px;
            line-height: 20px; }
        .page-shopping-cart .cart-product table .td-product img {
            border: 1px solid #e3e3e3;
            margin-right: 10px; }
        .page-shopping-cart .cart-product table .td-product .product-info {
            display: inline-block;
            vertical-align: middle; }
        .page-shopping-cart .cart-product table .td-do {
            font-size: 12px; }
        .page-shopping-cart .cart-product-info {
            height: 50px;
            line-height: 50px;
            background: #f7f7f7;
            padding-left: 20px; }
        .page-shopping-cart .cart-product-info .delect-product {
            color: #666; }
        .page-shopping-cart .cart-product-info .delect-product span {
            display: inline-block;
            vertical-align: top;
            margin: 18px 8px 0 0;
            width: 13px;
            height: 15px;
            background: url("shopping_cart.png") no-repeat -60px 0; }
        .page-shopping-cart .cart-product-info .product-total {
            font-size: 14px;
            color: #e94826; }
        .page-shopping-cart .cart-product-info .product-total span {
            font-size: 20px; }
        .page-shopping-cart .cart-product-info .check-num {
            color: #333; }
        .page-shopping-cart .cart-product-info .check-num span {
            color: #e94826; }
        .page-shopping-cart .cart-product-info .keep-shopping {
            color: #666;
            margin-left: 40px; }
        .page-shopping-cart .cart-product-info .keep-shopping span {
            display: inline-block;
            vertical-align: top;
            margin: 18px 8px 0 0;
            width: 15px;
            height: 15px;
            background: url("shopping_cart.png") no-repeat -40px 0; }
        .page-shopping-cart .cart-product-info .btn-buy {
            height: 50px;
            color: #fff;
            font-size: 20px;
            display: block;
            width: 110px;
            background: #ff7700;
            text-align: center;
            margin-left: 30px; }
        .page-shopping-cart .cart-worder {
            padding: 20px; }
        .page-shopping-cart .cart-worder .choose-worder {
            color: #fff;
            display: block;
            background: #39e;
            width: 140px;
            height: 40px;
            line-height: 40px;
            border-radius: 4px;
            text-align: center;
            margin-right: 20px; }
        .page-shopping-cart .cart-worder .choose-worder span {
            display: inline-block;
            vertical-align: top;
            margin: 9px 10px 0 0;
            width: 22px;
            height: 22px;
            background: url("shopping_cart.png") no-repeat -92px 0; }
        .page-shopping-cart .cart-worder .worker-info {
            color: #666; }
        .page-shopping-cart .cart-worder .worker-info img {
            border-radius: 100%;
            margin-right: 10px; }
        .page-shopping-cart .cart-worder .worker-info span {
            color: #000; }

        .choose-worker-box {
            width: 620px;
            background: #fff; }
        .choose-worker-box .box-title {
            height: 40px;
            line-height: 40px;
            background: #F7F7F7;
            text-align: center;
            position: relative;
            font-size: 14px; }
        .choose-worker-box .box-title a {
            display: block;
            position: absolute;
            top: 15px;
            right: 16px;
            width: 10px;
            height: 10px;
            background: url("shopping_cart.png") no-repeat -80px 0; }
        .choose-worker-box .box-title a:hover {
            background: url("shopping_cart.png") no-repeat -80px -22px; }
        .choose-worker-box .worker-list {
            padding-top: 30px;
            height: 134px;
            overflow-y: auto; }
        .choose-worker-box .worker-list li {
            float: left;
            width: 25%;
            text-align: center;
            margin-bottom: 30px; }
        .choose-worker-box .worker-list li p {
            margin-top: 8px; }
        .choose-worker-box .worker-list li.cur a {
            color: #f70; }
        .choose-worker-box .worker-list li.cur a img {
            border: 1px solid #f70; }
        .choose-worker-box .worker-list li a:hover {
            color: #f70; }
        .choose-worker-box .worker-list li a:hover img {
            border: 1px solid #f70; }
        .choose-worker-box .worker-list li img {
            border: 1px solid #fff;
            border-radius: 100%; }
    </style>
</head>
<body>
<div class="page-shopping-cart" id="shopping-cart">
    <h4 class="cart-title">購物清單</h4>
    <div class="cart-product-title clearfix">
        <div class="td-check fl"><span class="check-span fl check-all"></span>全選</div>
        <div class="td-product fl">商品</div>
        <div class="td-num fl">數量</div>
        <div class="td-price fl">單價(元)</div>
        <div class="td-total fl">金額(元)</div>
        <div class="td-do fl">操作</div>
    </div>
    <div class="cart-product clearfix">
        <table>
            <tbody><tr>
                <td class="td-check"><span class="check-span"></span></td>
                <td class="td-product"><img src="testimg.jpg" width="98" height="98">
                    <div class="product-info">
                        <h6>【斯文】甘油&nbsp;|&nbsp;丙三醇</h6>
                        <p>品牌:韓國skc&nbsp;&nbsp;產地:韓國</p>
                        <p>規格/純度:99.7%&nbsp;&nbsp;起定量:215千克</p>
                        <p>配送倉儲:上海倉海倉儲</p>
                    </div>
                    <div class="clearfix"></div>
                </td>
                <td class="td-num">
                    <div class="product-num">
                        <a href="javascript:;" class="num-reduce num-do fl"><span></span></a>
                        <input type="text" class="num-input" value="3">
                        <a href="javascript:;" class="num-add num-do fr"><span></span></a>
                    </div>
                </td>
                <td class="td-price">
                    <p class="red-text">¥<span class="price-text">800</span>.00</p>
                </td>
                <td class="td-total">
                    <p class="red-text">¥<span class="total-text">800</span>.00</p>
                </td>
                <td class="td-do"><a href="javascript:;" class="product-delect">刪除</a></td>
            </tr>
            <tr>
                <td class="td-check"><span class="check-span check-true"></span></td>
                <td class="td-product"><img src="testimg.jpg" width="98" height="98">
                    <div class="product-info">
                        <h6>【斯文】甘油&nbsp;|&nbsp;丙三醇</h6>
                        <p>品牌:韓國skc&nbsp;&nbsp;產地:韓國</p>
                        <p>規格/純度:99.7%&nbsp;&nbsp;起定量:215千克</p>
                        <p>配送倉儲:上海倉海倉儲</p>
                    </div>
                    <div class="clearfix"></div>
                </td>
                <td class="td-num">
                    <div class="product-num">
                        <a href="javascript:;" class="num-reduce num-do fl"><span></span></a>
                        <input type="text" class="num-input" value="1">
                        <a href="javascript:;" class="num-add num-do fr"><span></span></a>
                    </div>
                </td>
                <td class="td-price">
                    <p class="red-text">¥<span class="price-text">800</span>.00</p>
                </td>
                <td class="td-total">
                    <p class="red-text">¥<span class="total-text">800</span>.00</p>
                </td>
                <td class="td-do"><a href="javascript:;" class="product-delect">刪除</a></td>
            </tr>
            </tbody></table>
    </div>
    <div class="cart-product-info">
        <a class="delect-product" href="javascript:;"><span></span>刪除所選商品</a>
        <a class="keep-shopping" href="#"><span></span>繼續購物</a>
        <a class="btn-buy fr" href="javascript:;">去結算</a>
        <p class="fr product-total">¥<span>1600</span></p>
        <p class="fr check-num"><span>2</span>件商品總計(不含運費):</p>
    </div>
    <div class="cart-worder clearfix">
        <a href="javascript:;" class="choose-worder fl"><span></span>繫結跟單員</a>
        <div class="worker-info fl">
        </div>
    </div>
</div>
</body>
<script src="vue.min.js"></script>
<script>
    new Vue({
        el:'#shopping-cart',
        data:{

        },
        computed: {},
        methods:{
            
        }
    })
</script>
</html>複製程式碼

然後準備下列表資料,根據下面表格的箭頭

vue快速入門的三個小例項

所以大家就知道嗎,下面的資料大概是漲這樣

productList:[
    {
        'pro_name': '【斯文】甘油 | 丙三醇',//產品名稱
        'pro_brand': 'skc',//品牌名稱
        'pro_place': '韓國',//產地
        'pro_purity': '99.7%',//規格
        'pro_min': "215千克",//最小起訂量
        'pro_depot': '上海倉海倉儲',//所在倉庫
        'pro_num': 3,//數量
        'pro_img': '../../images/ucenter/testimg.jpg',//圖片連結
        'pro_price': 800//單價
    }
]複製程式碼

準備了這麼多,大家可能想到,還缺少一個,就是記錄產品是否有選中,但是這個欄位,雖然可以在上面那裡加,但是意義不大,比如在平常專案那裡!後臺的資料不會這樣返回,資料庫也不會有這個欄位,這個欄位應該是自己新增的。程式碼如下

new Vue({
    el:'#shopping-cart',
    data:{
        productList:[
            {
                'pro_name': '【斯文】甘油 | 丙三醇',//產品名稱
                'pro_brand': 'skc',//品牌名稱
                'pro_place': '韓國',//產地
                'pro_purity': '99.7%',//規格
                'pro_min': "215千克",//最小起訂量
                'pro_depot': '上海倉海倉儲',//所在倉庫
                'pro_num': 3,//數量
                'pro_img': '../../images/ucenter/testimg.jpg',//圖片連結
                'pro_price': 800//單價
            }
        ]
    },
    computed: {},
    methods:{

    },
    mounted:function () {
        //為productList新增select(是否選中)欄位,初始值為true
        var _this=this;
        //為productList新增select(是否選中)欄位,初始值為true
        this.productList.map(function (item) {
            _this.$set(item, 'select', true);
        })
        //要像上面這樣寫雙向繫結才能起效,下面的寫法是有問題的,雙向繫結不起效的!
        //this.productList.map(function (item) {item.select=true})
    }
})
          複製程式碼

步驟1

為了著重表示我修改了什麼地方,程式碼我現在只貼出修改的部分,大家對著上面的佈局,就很容易知道我改的是什麼地方了!下面也是這樣操作!

點選增加和減少按鈕(箭頭指向地方),所屬列的金額改變(紅框地方)
vue快速入門的三個小例項

執行步驟1之前,要先把列表的資料給鋪出來。利用v-for指令。程式碼如下

<tr v-for="item in productList">
    <td class="td-check"><span class="check-span"></span></td>
    <td class="td-product"><img :src="item.pro_img" width="98" height="98">
        <div class="product-info">
            <h6>{{item.pro_name}}</h6>
            <p>品牌:{{item.pro_brand}}&nbsp;&nbsp;產地:{{item.pro_place}}</p>
            <p>規格/純度:{{item.pro_purity}}&nbsp;&nbsp;起定量:{{item.pro_min}}</p>
            <p>配送倉儲:{{item.pro_depot}}</p>
        </div>
        <div class="clearfix"></div>
    </td>
    <td class="td-num">
        <div class="product-num">
            <a href="javascript:;" class="num-reduce num-do fl" @click="item.pro_num--"><span></span></a>
            <input type="text" class="num-input" v-model="item.pro_num">
            <a href="javascript:;" class="num-add num-do fr" @click="item.pro_num++"><span></span></a>
        </div>
    </td>
    <td class="td-price">
        <p class="red-text">¥<span class="price-text">{{item.pro_price.toFixed(2)}}</span></p>
    </td>
    <td class="td-total">
        <p class="red-text">¥<span class="total-text">{{item.pro_price*item.pro_num}}</span>.00</p>
    </td>
    <td class="td-do"><a href="javascript:;" class="product-delect">刪除</a></td>
</tr>
複製程式碼

這樣,列表的資料就有了!

vue快速入門的三個小例項

也可以發現,vue快速入門的三個小例項這兩個按鈕的功能已經實現了,後面的金額也會發生變化!是不是感到很驚喜!其實這裡沒什麼特別的,就是因為輸入框利用v-model繫結了數量(pro_num),然後兩個按鈕分別新增了事件@click="item.pro_num--"和@click="item.pro_num++"。比如剛開始pro_num是3,點選vue快速入門的三個小例項pro_num就變成2,點選vue快速入門的三個小例項
pro_num就變成4,然後後面的金額會改改,是因為{{item.pro_price*item.pro_num}}。只要pro_price或者pro_num的值改變了,整一塊也會改變,檢視就會重新整理,我們就能看到變化(這些事情是vue做的,這就是MVVM的魅力,資料驅動檢視改變)。

步驟2

點選所屬列選擇按鈕(箭頭指向地方),總計的金額(紅框地方)和已選產品的列數(藍框地方)和全選(黃框地方)會改變(如果已經全選了,全選按鈕自動變成全選,如果沒有全選,全選按鈕,自動取消全選)!

vue快速入門的三個小例項

首先,選擇與取消選擇,在這裡只有兩個操作(其實只有一個:改變這條記錄的select欄位)。

vue快速入門的三個小例項

然後改變vue快速入門的三個小例項,如果這條記錄selectfalse,就顯示vue快速入門的三個小例項,否則就顯示vue快速入門的三個小例項
程式碼如下

<td class="td-check"><span class="check-span" @click="item.select=!item.select" :class="{'check-true':item.select}"></span></td>複製程式碼

其實就是等於新增了@click="item.select=!item.select" :class="{'check-true':item.select}"這裡。點選這個,這條資料的select欄位就取反(true->false或者false->true)。然後:class="{'check-true':item.select}",就會根據這條資料的select欄位進行判斷,是否新增check-true類名,如果select欄位為true,就新增類名,顯示vue快速入門的三個小例項。否則不新增類名,顯示
vue快速入門的三個小例項

然後,vue快速入門的三個小例項全選按鈕,是否變成vue快速入門的三個小例項。這裡用一個computed(計算屬性)就好。程式碼如下

html

<div class="td-check fl"><span class="check-span fl check-all" :class="{'check-true':isSelectAll}"></span>全選</div>
複製程式碼

js

computed: {
    isSelectAll:function(){
        //如果productList長度為0
        if(this.productList.length===0){
            return false;
        }
        //如果productList中每一條資料的select都為true,返回true,否則返回false;
        return this.productList.every(function (val) { return val.select});
    }
}複製程式碼

程式碼我解釋下,就是計算屬性中,定義的isSelectAll依賴productList。只要productList改變,isSelectAll的返回值就會改變,然後:class="{'check-true':isSelectAll}"根絕isSelectAll返回值是否新增'check-true'類名,顯示對應的樣式!
最後,vue快速入門的三個小例項,這裡的多少件產品和總價,也是使用計算屬性,有了上一步的基礎,給出程式碼,大家一看就明白了!
html

<p class="fr product-total">¥<span>{{getTotal.totalPrice}}</span></p>
<p class="fr check-num"><span>{{getTotal.totalNum}}</span>件商品總計(不含運費):</p>複製程式碼

js

computed: {
    //檢測是否全選
    isSelectAll:function(){
        //如果productList長度為0
        if(this.productList.length===0){
            return false;
        }
        //如果productList中每一條資料的select都為true,返回true,否則返回false;
        return this.productList.every(function (val) { return val.select});
    },
    //獲取總價和產品總件數
    getTotal:function(){
        //獲取productList中select為true的資料。
        var _proList=this.productList.filter(function (val) { return val.select}),totalPrice=0;
        for(var i=0,len=_proList.length;i<len;i++){
            //總價累加
            totalPrice+=_proList[i].pro_num*_proList[i].pro_price;
        }
        //選擇產品的件數就是_proList.length,總價就是totalPrice
        return {totalNum:_proList.length,totalPrice:totalPrice}
    }
},複製程式碼

程式碼很簡單,html根據getTotal返回值顯示資料,getTotal依賴productList的資料,只要productList改變,返回值會改變,檢視也會改變!

vue快速入門的三個小例項

步驟3

點選全選按鈕(箭頭指向部分),會自動的對產品進行全選或者取消全選,下面的總計也會發生改變

vue快速入門的三個小例項
做到這一步,大家應該知道,全選或者取消全選,就是改變記錄的select。但是怎麼知道現在的列表有沒有全選呢?這個很賤,不需要在操作函式(全選與取消全選函式)裡面遍歷,大家應該還記得第二步的計算屬性isSelectAll(為true就是全選,否則不是全選),把這個傳進操作函式就好,然後操作函式,根據引數,決定執行全選,還是取消全選操作。程式碼如下!
html

<div class="td-check fl"><span class="check-span fl check-all" :class="{'check-true':isSelectAll}"@click="selectProduct(isSelectAll)"></span>全選</div>複製程式碼

js

 methods: {
    //全選與取消全選
    selectProduct:function(_isSelect){
        //遍歷productList,全部取反
        for (var i = 0, len = this.productList.length; i < len; i++) {
            this.productList[i].select = !_isSelect;
        }
    }
},
複製程式碼

vue快速入門的三個小例項

步驟4

點選刪除產品,會刪除已經選中的,全選按鈕和下面的總計,都會變化!點選每條記錄後面的刪除,會刪除當前的這條記錄。全選按鈕和下面的總計,也都會變化!

vue快速入門的三個小例項

首先,點選刪除產品,刪除已經選中。這個大家知道了怎麼做了!就是遍歷productList,如果哪條記錄的select為true,就刪除。
然後,點選每條記錄後面的刪除,刪除當前的這條記錄。這個在html遍歷productList的時候。順便帶上索引,然後把索引當成引數,傳進操作函式,然後根據索引引數,刪除productList的哪一條記錄。即可實現!程式碼如下!
html

<!--遍歷的時候帶上索引-->
<tr v-for="(item,index) in productList">
    <td class="td-check"><span class="check-span" @click="item.select=!item.select" :class="{'check-true':item.select}"></span></td>
    <td class="td-product"><img :src="item.pro_img" width="98" height="98">
        <div class="product-info">
            <h6>{{item.pro_name}}</h6>
            <p>品牌:{{item.pro_brand}}&nbsp;&nbsp;產地:{{item.pro_place}}</p>
            <p>規格/純度:{{item.pro_purity}}&nbsp;&nbsp;起定量:{{item.pro_min}}</p>
            <p>配送倉儲:{{item.pro_depot}}</p>
        </div>
        <div class="clearfix"></div>
    </td>
    <td class="td-num">
        <div class="product-num">
            <a href="javascript:;" class="num-reduce num-do fl" @click="item.pro_num--"><span></span></a>
            <input type="text" class="num-input" v-model="item.pro_num">
            <a href="javascript:;" class="num-add num-do fr" @click="item.pro_num++"><span></span></a>
        </div>
    </td>
    <td class="td-price">
        <p class="red-text">¥<span class="price-text">{{item.pro_price.toFixed(2)}}</span></p>
    </td>
    <td class="td-total">
        <p class="red-text">¥<span class="total-text">{{item.pro_price*item.pro_num}}</span>.00</p>
    </td>
    <td class="td-do"><a href="javascript:;" class="product-delect" @click="deleteOneProduct(index)">刪除</a></td>
</tr>
...
<a class="delect-product" href="javascript:;" @click="deleteProduct"><span></span>刪除所選商品</a>複製程式碼

js

//刪除已經選中(select=true)的產品
deleteProduct:function () {
    this.productList=this.productList.filter(function (item) {return !item.select})
},
//刪除單條產品
deleteOneProduct:function (index) {
    //根據索引刪除productList的記錄
    this.productList.splice(index,1);
},複製程式碼

完整程式碼

樣式圖片

vue快速入門的三個小例項

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .fl {
            float: left;
        }

        .fr {
            float: right;
        }

        blockquote, body, dd, div, dl, dt, fieldset, form, h1, h2, h3, h4, h5, h6, img, input, li, ol, p, table, td, textarea, th, ul {
            margin: 0;
            padding: 0;
        }

        .clearfix {
            zoom: 1;
        }

        .clearfix:after {
            clear: both;
        }

        .clearfix:after {
            content: '.';
            display: block;
            overflow: hidden;
            visibility: hidden;
            font-size: 0;
            line-height: 0;
            width: 0;
            height: 0;
        }

        a {
            text-decoration: none;
            color: #333;
        }

        img {
            vertical-align: middle;
        }

        .page-shopping-cart {
            width: 1200px;
            margin: 50px auto;
            font-size: 14px;
            border: 1px solid #e3e3e3;
            border-top: 2px solid #317ee7;
        }

        .page-shopping-cart .cart-title {
            color: #317ee7;
            font-size: 16px;
            text-align: left;
            padding-left: 20px;
            line-height: 68px;
        }

        .page-shopping-cart .red-text {
            color: #e94826;
        }

        .page-shopping-cart .check-span {
            display: block;
            width: 24px;
            height: 20px;
            background: url("shopping_cart.png") no-repeat 0 0;
        }

        .page-shopping-cart .check-span.check-true {
            background: url("shopping_cart.png") no-repeat 0 -22px;
        }

        .page-shopping-cart .td-check {
            width: 70px;
        }

        .page-shopping-cart .td-product {
            width: 460px;
        }

        .page-shopping-cart .td-num, .page-shopping-cart .td-price, .page-shopping-cart .td-total {
            width: 160px;
        }

        .page-shopping-cart .td-do {
            width: 150px;
        }

        .page-shopping-cart .cart-product-title {
            text-align: center;
            height: 38px;
            line-height: 38px;
            padding: 0 20px;
            background: #f7f7f7;
            border-top: 1px solid #e3e3e3;
            border-bottom: 1px solid #e3e3e3;
        }

        .page-shopping-cart .cart-product-title .td-product {
            text-align: center;
            font-size: 14px;
        }

        .page-shopping-cart .cart-product-title .td-check {
            text-align: left;
        }

        .page-shopping-cart .cart-product-title .td-check .check-span {
            margin: 9px 6px 0 0;
        }

        .page-shopping-cart .cart-product {
            padding: 0 20px;
            text-align: center;
        }

        .page-shopping-cart .cart-product table {
            width: 100%;
            text-align: center;
            font-size: 14px;
        }

        .page-shopping-cart .cart-product table td {
            padding: 20px 0;
        }

        .page-shopping-cart .cart-product table tr {
            border-bottom: 1px dashed #e3e3e3;
        }

        .page-shopping-cart .cart-product table tr:last-child {
            border-bottom: none;
        }

        .page-shopping-cart .cart-product table .product-num {
            border: 1px solid #e3e3e3;
            display: inline-block;
            text-align: center;
        }

        .page-shopping-cart .cart-product table .product-num .num-do {
            width: 24px;
            height: 28px;
            display: block;
            background: #f7f7f7;
        }

        .page-shopping-cart .cart-product table .product-num .num-reduce span {
            background: url("shopping_cart.png") no-repeat -40px -22px;
            display: block;
            width: 6px;
            height: 2px;
            margin: 13px auto 0 auto;
        }

        .page-shopping-cart .cart-product table .product-num .num-add span {
            background: url("shopping_cart.png") no-repeat -60px -22px;
            display: block;
            width: 8px;
            height: 8px;
            margin: 10px auto 0 auto;
        }

        .page-shopping-cart .cart-product table .product-num .num-input {
            width: 42px;
            height: 28px;
            line-height: 28px;
            border: none;
            text-align: center;
        }

        .page-shopping-cart .cart-product table .td-product {
            text-align: left;
            font-size: 12px;
            line-height: 20px;
        }

        .page-shopping-cart .cart-product table .td-product img {
            border: 1px solid #e3e3e3;
            margin-right: 10px;
        }

        .page-shopping-cart .cart-product table .td-product .product-info {
            display: inline-block;
            vertical-align: middle;
        }

        .page-shopping-cart .cart-product table .td-do {
            font-size: 12px;
        }

        .page-shopping-cart .cart-product-info {
            height: 50px;
            line-height: 50px;
            background: #f7f7f7;
            padding-left: 20px;
        }

        .page-shopping-cart .cart-product-info .delect-product {
            color: #666;
        }

        .page-shopping-cart .cart-product-info .delect-product span {
            display: inline-block;
            vertical-align: top;
            margin: 18px 8px 0 0;
            width: 13px;
            height: 15px;
            background: url("shopping_cart.png") no-repeat -60px 0;
        }

        .page-shopping-cart .cart-product-info .product-total {
            font-size: 14px;
            color: #e94826;
        }

        .page-shopping-cart .cart-product-info .product-total span {
            font-size: 20px;
        }

        .page-shopping-cart .cart-product-info .check-num {
            color: #333;
        }

        .page-shopping-cart .cart-product-info .check-num span {
            color: #e94826;
        }

        .page-shopping-cart .cart-product-info .keep-shopping {
            color: #666;
            margin-left: 40px;
        }

        .page-shopping-cart .cart-product-info .keep-shopping span {
            display: inline-block;
            vertical-align: top;
            margin: 18px 8px 0 0;
            width: 15px;
            height: 15px;
            background: url("shopping_cart.png") no-repeat -40px 0;
        }

        .page-shopping-cart .cart-product-info .btn-buy {
            height: 50px;
            color: #fff;
            font-size: 20px;
            display: block;
            width: 110px;
            background: #ff7700;
            text-align: center;
            margin-left: 30px;
        }

        .page-shopping-cart .cart-worder {
            padding: 20px;
        }

        .page-shopping-cart .cart-worder .choose-worder {
            color: #fff;
            display: block;
            background: #39e;
            width: 140px;
            height: 40px;
            line-height: 40px;
            border-radius: 4px;
            text-align: center;
            margin-right: 20px;
        }

        .page-shopping-cart .cart-worder .choose-worder span {
            display: inline-block;
            vertical-align: top;
            margin: 9px 10px 0 0;
            width: 22px;
            height: 22px;
            background: url("shopping_cart.png") no-repeat -92px 0;
        }

        .page-shopping-cart .cart-worder .worker-info {
            color: #666;
        }

        .page-shopping-cart .cart-worder .worker-info img {
            border-radius: 100%;
            margin-right: 10px;
        }

        .page-shopping-cart .cart-worder .worker-info span {
            color: #000;
        }

        .choose-worker-box {
            width: 620px;
            background: #fff;
        }

        .choose-worker-box .box-title {
            height: 40px;
            line-height: 40px;
            background: #F7F7F7;
            text-align: center;
            position: relative;
            font-size: 14px;
        }

        .choose-worker-box .box-title a {
            display: block;
            position: absolute;
            top: 15px;
            right: 16px;
            width: 10px;
            height: 10px;
            background: url("shopping_cart.png") no-repeat -80px 0;
        }

        .choose-worker-box .box-title a:hover {
            background: url("shopping_cart.png") no-repeat -80px -22px;
        }

        .choose-worker-box .worker-list {
            padding-top: 30px;
            height: 134px;
            overflow-y: auto;
        }

        .choose-worker-box .worker-list li {
            float: left;
            width: 25%;
            text-align: center;
            margin-bottom: 30px;
        }

        .choose-worker-box .worker-list li p {
            margin-top: 8px;
        }

        .choose-worker-box .worker-list li.cur a {
            color: #f70;
        }

        .choose-worker-box .worker-list li.cur a img {
            border: 1px solid #f70;
        }

        .choose-worker-box .worker-list li a:hover {
            color: #f70;
        }

        .choose-worker-box .worker-list li a:hover img {
            border: 1px solid #f70;
        }

        .choose-worker-box .worker-list li img {
            border: 1px solid #fff;
            border-radius: 100%;
        }
    </style>
</head>
<body>
<div class="page-shopping-cart" id="shopping-cart">
    <h4 class="cart-title">購物清單</h4>
    <div class="cart-product-title clearfix">
        <div class="td-check fl"><span class="check-span fl check-all" :class="{'check-true':isSelectAll}" @click="selectProduct(isSelectAll)"></span>全選</div>
        <div class="td-product fl">商品</div>
        <div class="td-num fl">數量</div>
        <div class="td-price fl">單價(元)</div>
        <div class="td-total fl">金額(元)</div>
        <div class="td-do fl">操作</div>
    </div>
    <div class="cart-product clearfix">
        <table>
            <tbody>
            <!--遍歷的時候帶上索引-->
            <tr v-for="(item,index) in productList">
                <td class="td-check"><span class="check-span" @click="item.select=!item.select" :class="{'check-true':item.select}"></span></td>
                <td class="td-product"><img :src="item.pro_img" width="98" height="98">
                    <div class="product-info">
                        <h6>{{item.pro_name}}</h6>
                        <p>品牌:{{item.pro_brand}}&nbsp;&nbsp;產地:{{item.pro_place}}</p>
                        <p>規格/純度:{{item.pro_purity}}&nbsp;&nbsp;起定量:{{item.pro_min}}</p>
                        <p>配送倉儲:{{item.pro_depot}}</p>
                    </div>
                    <div class="clearfix"></div>
                </td>
                <td class="td-num">
                    <div class="product-num">
                        <a href="javascript:;" class="num-reduce num-do fl" @click="item.pro_num>0?item.pro_num--:''"><span></span></a>
                        <input type="text" class="num-input" v-model="item.pro_num">
                        <a href="javascript:;" class="num-add num-do fr" @click="item.pro_num++"><span></span></a>
                    </div>
                </td>
                <td class="td-price">
                    <p class="red-text">¥<span class="price-text">{{item.pro_price.toFixed(2)}}</span></p>
                </td>
                <td class="td-total">
                    <p class="red-text">¥<span class="total-text">{{item.pro_price*item.pro_num}}</span>.00</p>
                </td>
                <td class="td-do"><a href="javascript:;" class="product-delect" @click="deleteOneProduct(index)">刪除</a></td>
            </tr>
            </tbody>
        </table>
    </div>
    <div class="cart-product-info">
        <a class="delect-product" href="javascript:;" @click="deleteProduct"><span></span>刪除所選商品</a>
        <a class="keep-shopping" href="#"><span></span>繼續購物</a>
        <a class="btn-buy fr" href="javascript:;">去結算</a>
        <p class="fr product-total">¥<span>{{getTotal.totalPrice}}</span></p>
        <p class="fr check-num"><span>{{getTotal.totalNum}}</span>件商品總計(不含運費):</p>
    </div>
</div>
</body>
<script src="../vue.min.js"></script>
<script>
    new Vue({
        el: '#shopping-cart',
        data: {
            productList: [
                {
                    'pro_name': '【斯文】甘油 | 丙三醇',//產品名稱
                    'pro_brand': 'skc',//品牌名稱
                    'pro_place': '韓國',//產地
                    'pro_purity': '99.7%',//規格
                    'pro_min': "215千克",//最小起訂量
                    'pro_depot': '上海倉海倉儲',//所在倉庫
                    'pro_num': 3,//數量
                    'pro_img': '../../images/ucenter/testimg.jpg',//圖片連結
                    'pro_price': 800//單價
                },
                {
                    'pro_name': '【斯文】甘油 | 丙三醇',//產品名稱
                    'pro_brand': 'skc',//品牌名稱
                    'pro_place': '韓國',//產地
                    'pro_purity': '99.7%',//規格
                    'pro_min': "215千克",//最小起訂量
                    'pro_depot': '上海倉海倉儲',//所在倉庫
                    'pro_num': 3,//數量
                    'pro_img': '../../images/ucenter/testimg.jpg',//圖片連結
                    'pro_price': 800//單價
                },
                {
                    'pro_name': '【斯文】甘油 | 丙三醇',//產品名稱
                    'pro_brand': 'skc',//品牌名稱
                    'pro_place': '韓國',//產地
                    'pro_purity': '99.7%',//規格
                    'pro_min': "215千克",//最小起訂量
                    'pro_depot': '上海倉海倉儲',//所在倉庫
                    'pro_num': 3,//數量
                    'pro_img': '../../images/ucenter/testimg.jpg',//圖片連結
                    'pro_price': 800//單價
                }
            ]
        },
        computed: {
            //檢測是否全選
            isSelectAll:function(){
                //如果長度為0,直接返回false
                if(this.productList.length===0){
                    return false;
                }
                //如果productList中每一條資料的select都為true,返回true,否則返回false;
                return this.productList.every(function (val) { return val.select});
            },
            //獲取總價和產品總件數
            getTotal:function(){
                //獲取productList中select為true的資料。
                var _proList=this.productList.filter(function (val) { return val.select}),totalPrice=0;
                for(var i=0,len=_proList.length;i<len;i++){
                    //總價累加
                    totalPrice+=_proList[i].pro_num*_proList[i].pro_price;
                }
                //選擇產品的件數就是_proList.length,總價就是totalPrice
                return {totalNum:_proList.length,totalPrice:totalPrice}
            }
        },
        methods: {
            //全選與取消全選
            selectProduct:function(_isSelect){
                //遍歷productList,全部取反
                for (var i = 0, len = this.productList.length; i < len; i++) {
                    this.productList[i].select = !_isSelect;
                }
            },
            //刪除已經選中(select=true)的產品
            deleteProduct:function () {
                this.productList=this.productList.filter(function (item) {return !item.select})
            },
            //刪除單條產品
            deleteOneProduct:function (index) {
                //根據索引刪除productList的記錄
                this.productList.splice(index,1);
            },
        },
        mounted: function () {
            var _this=this;
            //為productList新增select(是否選中)欄位,初始值為true
            this.productList.map(function (item) {
                _this.$set(item, 'select', true);
            })
        }
    })
</script>
</html>複製程式碼

5.todoList

執行效果

vue快速入門的三個小例項

原理分析和實現

首先,還是先把佈局寫好,和引入vue,準備vue例項,這個不多說,程式碼如下

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style>
            body{font-family: "微軟雅黑";font-size: 14px;}
            input{font-size: 14px;}
            body,ul,div,html{padding: 0;margin: 0;}
            .hidden{display: none;}
            .main{width: 800px;margin: 0 auto;}
            li{list-style-type: none;line-height: 40px;position: relative;border: 1px solid transparent;padding: 0 20px;}
            li .type-span{display: block;width: 10px;height: 10px;background: #ccc;margin: 14px 10px 0 0 ;float: left;}
            li .close{position: absolute;color: #f00;font-size: 20px;line-height: 40px;height: 40px;right: 20px;cursor: pointer;display: none;top: 0;}
            li:hover{border: 1px solid #09f;}
            li:hover .close{display: block;}
            li .text-keyword{height: 40px;padding-left: 10px;box-sizing: border-box;margin-left: 10px;width: 80%;display: none;}
            .text-keyword{box-sizing: border-box;width: 100%;height: 40px;padding-left: 10px;outline: none;}
        </style>
    </head>
    <body>
        <div id="app" class="main">
            <h2>小目標列表</h2>
            <div class="list">
                <h3>新增小目標</h3>
                <input type="text" class="text-keyword" placeholder="輸入小目標後,按回車確認"/>
                <p>共有N個目標</p>
                <p>
                    <input type="radio" name="chooseType" checked="true"/><label>所有目標</label>
                    <input type="radio" name="chooseType"/><label>已完成目標</label>
                    <input type="radio" name="chooseType"/><label>未完成目標</label>
                </p>
            </div>
            <ul>
                <li class="li1">
                    <div>
                        <span class="type-span"></span>
                        <span>html5</span>
                        <span class="close">X</span>
                    </div>
                </li>
                <li class="li1">
                    <div>
                        <span class="type-span"></span>
                        <span>css3</span>
                        <span class="close">X</span>
                    </div>
                </li>
            </ul>
        </div>
    </body>
    <script src="vue2.4.2.js"></script>
    <script type="text/javascript">
    new Vue({
        el: "#app",
        data: {
        },
        computed:{
            
        },
        methods:{
            
        }
    });
    </script>
</html>複製程式碼

佈局有了,相當於一個骨架就有了,下面實現功能,一個一個來

步驟1

輸入並回車,多一條記錄。下面的記錄文字也會改變

vue快速入門的三個小例項

首先,大的輸入框回車要新增紀錄,那麼輸入框必須繫結一個值和一個新增紀錄的方法。
程式碼如下:
然後,下面的記錄也要改變,所以,下面的記錄也要幫一個值,因為這個記錄可能會有多個,這個值就是一個陣列,也可以看到,記錄除了名稱,還有記錄是否完成的狀態,所以,繫結記錄的這個值肯定是一個物件陣列!程式碼如下
最後,記錄文字vue快速入門的三個小例項要改變。這個只是一個當前記錄的長度即可!

為了著重表示我修改了什麼地方,程式碼我現在只貼出修改的部分,大家對著上面的佈局,就很容易知道我改的是什麼地方了!下面也是這樣操作!

html程式碼

<!--利用v-model把addText繫結到input-->
<input type="text" class="text-keyword" placeholder="輸入小目標後,按回車確認" @keyup.13='addList' v-model="addText"/>
<p>共有{{prolist.length}}個目標</p>
<!--v-for遍歷prolist-->
<li class="li1" v-for="list in prolist">
    <div>
        <span class="type-span"></span>
        <span>{{list.name}}</span>
        <span class="close">X</span>
    </div>
</li>
複製程式碼

js程式碼

new Vue({
    el: "#app",
    data: {
        addText:'',
        //name-名稱,status-完成狀態
       prolist:[
               {name:"HTML5",status:false},
               {name:"CSS3",status:false},
               {name:"vue",status:false},
               {name:"react",status:false}
        ]
    },
    computed:{
        
    },
    methods:{
        addList(){
            //新增進來預設status=false,就是未完成狀態
            this.prolist.push({
                name:this.addText,
                status:false
            });
            //新增後,清空addText
            this.addText="";
        }
    }
});複製程式碼

測試一下,沒問題

vue快速入門的三個小例項

步驟2

點選切換,下面記錄會改變

vue快速入門的三個小例項

看到三個選項,也很簡單,無非就是三個選擇,一個是所有的目標,一個是所有已經完成的目標,一個是所有沒完成的目標。
首先.新建一個新的變數(newList),儲存prolist。遍歷的時候不再遍歷prolist,而是遍歷newList。改變也是改變newList。
然後.選擇所有目標的時候,顯示全部prolist,把prolist賦值給newList。
然後.選擇所有已經完成目標的時候,只顯示prolist中,status為true的目標,把prolist中,status為true的項賦值給newList,
最後.選擇所有未完成目標的時候,只顯示status為false的目標,把prolist中,status為false的項賦值給newList。

程式碼如下

html

 <ul>
    <li class="li1" v-for="list in newList">
        <div>
            <span class="status-span"></span>
            <span>{{list.name}}</span>
            <span class="close" @click='delectList(index)'>X</span>
        </div>
    </li>
</ul>複製程式碼

js

new Vue({
    el: "#app",
    data: {
        addText:'',
        //name-名稱,status-完成狀態
       prolist:[
               {name:"HTML5",status:false},
               {name:"CSS3",status:false},
               {name:"vue",status:false},
               {name:"react",status:false}
        ],
        newList:[]
    },
    computed:{
        noend:function(){
            return this.prolist.filter(function(item){
                return !item.status
            }).length;
        }
    },
    methods:{
        addList(){
            //新增進來預設status=false,就是未完成狀態
            this.prolist.push({
                name:this.addText,
                status:false
            });
            //新增後,清空addText
            this.addText="";
        },
        chooseList(type){
            //type=1時,選擇所有目標
            //type=2時,選擇所有已完成目標
            //type=3時,選擇所有未完成目標
            switch(type){
                case 1:this.newList=this.prolist;break;
                case 2:this.newList=this.prolist.filter(function(item){return item.status});break;
                case 3:this.newList=this.prolist.filter(function(item){return !item.status});break;
            }
        },
        delectList(index){
            //根據索引,刪除陣列某一項
            this.prolist.splice(index,1);
            //更新newList  newList可能經過this.prolist.filter()賦值,這樣的話,刪除了prolist不會影響到newList  那麼就要手動更新newList
            this.newList=this.prolist;
        },
    },
    mounted(){
        //初始化,把prolist賦值給newList。預設顯示所有目標
        this.newList=this.prolist;
    }
});
複製程式碼

執行結果

vue快速入門的三個小例項

步驟3

紅色關閉標識,點選會刪除該記錄。前面按鈕點選會切換該記錄完成狀態,顏色也改變,記錄文字也跟著改變

vue快速入門的三個小例項

首先點選紅色關閉標識,點選會刪除該記錄。這個應該沒什麼問題,就是刪除prolist的一條記錄!
然後前面按鈕點選會切換該記錄完成狀態。這個也沒什麼,就是改變prolist的一條記錄的status欄位!
最後記錄文字的改變,就是記錄prolist中status為false的有多少條,prolist中status為true的有多少條而已

html程式碼

<!--如果noend等於0,就是全部完成了就顯示‘全部完成了’,如果沒有就是顯示已完成多少條(prolist.length-noend)和未完成多少條(noend)-->
<p>共有{{prolist.length}}個目標,{{noend==0?"全部完成了":'已完成'+(prolist.length-noend)+',還有'+noend+'條未完成'}}</p>


<ul>
    <li class="li1" v-for="(list,index) in newList">
        <div>
            <span class="status-span" @click="list.status=!list.status" :class="{'status-end':list.status}"></span>
            <span>{{list.name}}</span>
            <span class="close" @click='delectList(index)'>X</span>
        </div>
    </li>
</ul>複製程式碼

js

new Vue({
    el: "#app",
    data: {
        addText:'',
        //name-名稱,status-完成狀態
       prolist:[
               {name:"HTML5",status:false},
               {name:"CSS3",status:false},
               {name:"vue",status:false},
               {name:"react",status:false}
        ],
        newList:[]
    },
    computed:{
        //計算屬性,返回未完成目標的條數,就是陣列裡面status=false的條數
        noend:function(){
            return this.prolist.filter(function(item){
                return !item.status
            }).length;
        }
    },
    methods:{
        addList(){
            //新增進來預設status=false,就是未完成狀態
            this.prolist.push({
                name:this.addText,
                status:false
            });
            //新增後,清空addText
            this.addText="";
        },
        chooseList(type){
            switch(type){
                case 1:this.newList=this.prolist;break;
                case 2:this.newList=this.prolist.filter(function(item){return item.status});break;
                case 3:this.newList=this.prolist.filter(function(item){return !item.status});break;
            }
        },
        delectList(index){
            //根據索引,刪除陣列某一項
            this.prolist.splice(index,1);
            //更新newList  newList可能經過this.prolist.filter()賦值,這樣的話,刪除了prolist不會影響到newList  那麼就要手動更新newList
            this.newList=this.prolist;
        },
    },
    mounted(){
        this.newList=this.prolist;
    }
});
複製程式碼

執行結果

vue快速入門的三個小例項

步驟4

文字雙擊會出現輸入框,可輸入文字,如果回車或者失去焦點,就改變文字,如果按下ESC就恢復原來的文字

vue快速入門的三個小例項

首先.雙擊出現輸入框,就是雙擊文字後,給當前的li設定一個類名(‘eidting’),然後寫好樣式。當li出現這個類名的時候,就出現輸入框,並且隱藏其它內容。
然後.回車或者失去焦點,就改變文字這個只需要操作一個,就是把類名(‘eidting’)清除掉。然後輸入框就會隱藏,其它內容顯示!
最後.按下ESC就恢復原來的文字,就是出現輸入框的時候,用一個變數(‘beforeEditText’)先儲存當前的內容,然後按下了ESC,就把變數(‘beforeEditText’)賦值給當前操作的值!

程式碼如下:

html

<ul>
    <li class="li1" v-for="(list,index) in newList" :class="{'eidting':curIndex===index}">
        <div>
            <span class="status-span" @click="list.status=!list.status" :class="{'status-end':list.status}"></span>
            <span @dblclick="curIndex=index">{{list.name}}</span>
            <span class="close" @click='delectList(index)'>X</span>
        </div>
        <input type="text" class="text2" v-model='list.name' @keyup.esc='cancelEdit(list)' @blur='edited' @focus='editBefore(list.name)' @keyup.enter='edited'/>
    </li>
</ul>複製程式碼

css(加上)

li div{display: block;}
li.eidting div{display: none;}
li .text2{height: 40px;padding-left: 10px;box-sizing: border-box;margin-left: 10px;width: 80%;display: none;}
li.eidting .text2{display: block;}複製程式碼

js

methods:{
        addList(){
            //新增進來預設status=false,就是未完成狀態
            this.prolist.push({
                name:this.addText,
                status:false
            });
            //新增後,清空addText
            this.addText="";
        },
        chooseList(type){
            //type=1時,選擇所有目標
            //type=2時,選擇所有已完成目標
            //type=3時,選擇所有未完成目標
            switch(type){
                case 1:this.newList=this.prolist;break;
                case 2:this.newList=this.prolist.filter(function(item){return item.status});break;
                case 3:this.newList=this.prolist.filter(function(item){return !item.status});break;
            }
        },
        delectList(index){
            //根據索引,刪除陣列某一項
            this.prolist.splice(index,1);
            //更新newList  newList可能經過this.prolist.filter()賦值,這樣的話,刪除了prolist不會影響到newList  那麼就要手動更新newList
            this.newList=this.prolist;
        },
        //修改前
        editBefore(name){
            //先記錄當前項(比如這一項,{name:"HTML5",status:false})
            //beforeEditText="HTML5"
            this.beforeEditText=name;
        },
        //修改完成後
        edited(){
            //修改完了,設定curIndex="",這樣輸入框就隱藏,其它元素就會顯示。因為在li元素 寫了::class="{'eidting':curIndex===index}"  當curIndex不等於index時,eidting類名就清除了!
            //輸入框利用v-model繫結了當前項(比如這一項,{name:"HTML5",status:false})的name,當在輸入框編輯的時候,比如改成‘HTML’,實際上當前項的name已經變成了‘HTML’,所以,這一步只是清除eidting類名,隱藏輸入框而已
            //還有一個要注意的就是雖然li遍歷的是newList,比如改了newList的這一項({name:"HTML5",status:false}),比如改成這樣({name:"HTML",status:true})。實際上prolist的這一項({name:"HTML5",status:false}),也會被改成({name:"HTML",status:true})。因為這裡是一個物件,而且公用一個堆疊!修改其中一個,另一個會被影響到
            this.curIndex="";
        },
        //取消修改
        cancelEdit(val){
            //上面說了輸入框利用v-model繫結了當前項(比如這一項,{name:"HTML5",status:false})的name,當在輸入框編輯的時候,比如改成‘HTML’,實際上當前項的name已經變成了‘HTML’,所以,這一步就是把之前儲存的beforeEditText賦值給當前項的name屬性,起到一個恢復原來值得作用!
            val.name=this.beforeEditText;
            this.curIndex="";
        }
 },複製程式碼

執行結果

vue快速入門的三個小例項

還有一個小細節,大家可能注意到了,就是雙擊文字,出來輸入框的時候,還要自己手動點選一下,才能獲得焦點,我們想雙擊了,輸入框出來的時候,自動獲取焦點,怎麼辦?自定義指令就行了!

computed:{...},
methods:{...},
mounted(){...},
directives:{
    "focus":{
        update(el){
            el.focus();
        }
    }
}
複製程式碼

然後html 呼叫指令

<input type="text" class="text2" v-model='list.name' @keyup.esc='cancelEdit(list)' @blur='edited' @focus='editBefore(list.name)' @keyup.enter='edited' v-focus/>複製程式碼

完整程式碼

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        body{font-family: "微軟雅黑";font-size: 14px;}
        input{font-size: 14px;}
        body,ul,div,html{padding: 0;margin: 0;}
        .hidden{display: none;}
        .main{width: 800px;margin: 0 auto;}
        li{list-style-type: none;line-height: 40px;position: relative;border: 1px solid transparent;padding: 0 20px;}
        li .status-span{display: block;width: 10px;height: 10px;background: #ccc;margin: 14px 10px 0 0 ;float: left;}
        li .status-span.status-end{
            background: #09f;
        }
        li .close{position: absolute;color: #f00;font-size: 20px;line-height: 40px;height: 40px;right: 20px;cursor: pointer;display: none;top: 0;}
        li:hover{border: 1px solid #09f;}
        li:hover .close{display: block;}
        li div{display: block;}
        li.eidting div{display: none;}
        li .text2{height: 40px;padding-left: 10px;box-sizing: border-box;margin-left: 10px;width: 80%;display: none;}
        li.eidting .text2{display: block;}
        li .text-keyword{height: 40px;padding-left: 10px;box-sizing: border-box;margin-left: 10px;width: 80%;display: none;}
        .text-keyword{box-sizing: border-box;width: 100%;height: 40px;padding-left: 10px;outline: none;}
    </style>
</head>
<body>
<div id="app" class="main">
    <h2>小目標列表</h2>
    <div class="list">
        <h3>新增小目標</h3>
        <input type="text" class="text-keyword" placeholder="輸入小目標後,按回車確認" @keyup.13='addList' v-model="addText"/>
        <!--如果noend等於0,就是全部完成了就顯示‘全部完成了’,如果沒有就是顯示已完成多少條(prolist.length-noend)和未完成多少條(noend)-->
        <p>共有{{prolist.length}}個目標,{{noend==0?"全部完成了":'已完成'+(prolist.length-noend)+',還有'+noend+'條未完成'}}</p>
        <p>
            <input type="radio" name="chooseType" checked="true" @click='chooseList(1)'/><label>所有目標</label>
            <input type="radio" name="chooseType" @click='chooseList(2)'/><label>已完成目標</label>
            <input type="radio" name="chooseType" @click='chooseList(3)'/><label>未完成目標</label>
        </p>
    </div>
    <ul>
        <li class="li1" v-for="(list,index) in newList" :class="{'eidting':curIndex===index}">
            <div>
                <span class="status-span" @click="changeType(index)" :class="{'status-end':list.status}"></span>
                <span @dblclick="curIndex=index">{{list.name}}</span>
                <span class="close" @click='delectList(list)'>X</span>
            </div>
            <input type="text" class="text2" v-model='list.name' @keyup.esc='cancelEdit(list)' @blur='edited' @focus='editBefore(list.name)' @keyup.enter='edited' v-focus/>
        </li>
    </ul>
</div>
</body>
<script src="vue.min.js"></script>
<script type="text/javascript">
    new Vue({
        el: "#app",
        data: {
            addText:'',
            //name-名稱,status-完成狀態
            prolist:[
                {name:"HTML5",status:false},
                {name:"CSS3",status:false},
                {name:"vue",status:false},
                {name:"react",status:false}
            ],
            newList:[],
            curIndex:'',
            beforeEditText:"",
            curType:0
        },
        computed:{
            //計算屬性,返回未完成目標的條數,就是陣列裡面status=false的條數
            noend:function(){
                return this.prolist.filter(function(item){
                    return !item.status
                }).length;
            }
        },
        methods:{
            addList(){
                //新增進來預設status=false,就是未完成狀態
                this.prolist.push({
                    name:this.addText,
                    status:false
                });
                //新增後,清空addText
                this.addText="";
            },
            chooseList(type){
                //type=1時,選擇所有目標
                //type=2時,選擇所有已完成目標
                //type=3時,選擇所有未完成目標
                this.curType=type;
                switch(type){
                    case 1:this.newList=this.prolist;break;
                    case 2:this.newList=this.prolist.filter(function(item){return item.status});break;
                    case 3:this.newList=this.prolist.filter(function(item){return !item.status});break;
                }
            },
            /*改變單條資料的完成狀態*/
            changeType(index){
                this.newList[index].status=!this.newList[index].status;
                //更新資料
                this.chooseList(this.curType);
            },
            delectList(list){
                var index=this.prolist.indexOf(list);
                //根據索引,刪除陣列某一項
                this.prolist.splice(index,1);
                //更新newList  newList可能經過this.prolist.filter()賦值,這樣的話,刪除了prolist不會影響到newList  那麼就要手動更新newList
                //this.newList=this.prolist;
                this.chooseList(this.curType);
            },
            //修改前
            editBefore(name){
                //先記錄當前項(比如這一項,{name:"HTML5",status:false})
                //beforeEditText="HTML5"
                this.beforeEditText=name;
            },
            //修改完成後
            edited(){
                //修改完了,設定curIndex="",這樣輸入框就隱藏,其它元素就會顯示。因為在li元素 寫了::class="{'eidting':curIndex===index}"  當curIndex不等於index時,eidting類名就清除了!
                //輸入框利用v-model繫結了當前項(比如這一項,{name:"HTML5",status:false})的name,當在輸入框編輯的時候,比如改成‘HTML’,實際上當前項的name已經變成了‘HTML’,所以,這一步只是清除eidting類名,隱藏輸入框而已
                //還有一個要注意的就是雖然li遍歷的是newList,比如改了newList的這一項({name:"HTML5",status:false}),比如改成這樣({name:"HTML",status:true})。實際上prolist的這一項({name:"HTML5",status:false}),也會被改成({name:"HTML",status:true})。因為這裡是一個物件,而且公用一個堆疊!修改其中一個,另一個會被影響到
                this.curIndex="";
            },
            //取消修改
            cancelEdit(val){
                //上面說了輸入框利用v-model繫結了當前項(比如這一項,{name:"HTML5",status:false})的name,當在輸入框編輯的時候,比如改成‘HTML’,實際上當前項的name已經變成了‘HTML’,所以,這一步就是把之前儲存的beforeEditText賦值給當前項的name屬性,起到一個恢復原來值得作用!
                val.name=this.beforeEditText;
                this.curIndex="";
            }
        },
        mounted(){
            //初始化,把prolist賦值給newList。預設顯示所有目標
            this.newList=this.prolist;
        },
        directives:{
            "focus":{
                update(el){
                    el.focus();
                }
            }
        }
    });
</script>
</html>
複製程式碼

6.小結

好了,三個小例項在這裡就說完了!別看文章這麼長,其實都是基礎,可能是我比較囉嗦而已!如果大家能熟透這幾個小例項,相信用vue做專案也是信手拈來。基礎的語法在這裡了,有了基礎,高階的寫法也不會很難學習!如果以後,我有什麼要分享的,我會繼續分享。最後一句老話,如果覺得我哪裡寫錯了,寫得不好,歡迎指點!


-------------------------華麗的分割線--------------------
想了解更多,關注關注我的微信公眾號:守候書閣

vue快速入門的三個小例項


相關文章