vue-内置指令

条件渲染

v-if v-else-if v-else

vue在渲染元素时,出于效率考虑,会尽可能地复用已有的元素而非重新渲染

example:

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="main.css"/>
</head>
<div id="app">
    <template v-if="type === 'name'">
        <label>用户名:</label>
        <input placeholder="输入用户名">
    </template>
    <template v-else>
        <label>邮箱:</label>
        <input placeholder="输入邮箱">
    </template>
    <button @click="handleToggleClick">切换输入类型</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="main.js"></script>
</body>
</html>

  

js

var app = new Vue({
    el: '#app',
    data: {
        type: 'name'
    },
    methods: {
        handleToggleClick: function() {
            this.type = this.type === 'name' ? 'mail' : 'name';
        }
    }
});

  

输入内容后,点切换按钮,虽然dom变了,只是替换了placehoder,input元素被复用

如果不希望这样做,可以使用vue.js提供的key属性,让你自己决定是否复用元素,key的值必须是唯一的

v-show

v-show是改变元素的css属性display,当v-show表达式的值为false时,元素会隐藏

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="main.css"/>
</head>
<div id="app">
    <p v-show="status === 1">当status为1时显示该行</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="main.js"></script>
</body>
</html>

  

js

var app = new Vue({
    el: '#app',
    data: {
        status: 1
    }
});

  

列表渲染指令v-for

当需要将一个数组遍历或枚举一个对象循环显示时,就用到v-for,表达式需要结合in来实现

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="main.css"/>
</head>
<div id="app">
    <ul>
        <li v-for="book in books">{{ book.name }}</li>
    </ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="main.js"></script>
</body>
</html>

  

js

var app = new Vue({
    el: '#app',
    data: {
        books: [
            { name:'python核心编程'},
            { name:'go学习笔记'},
            { name:'vue.js实战'}
        ]
    }
});

  

在表达式中,books是数据,book是当前每个元素,元素.name能取出对应的值

v-for也能取出当前项的索引

<li v-for="(book,index) in books">{{index}}-{{ book.name }}</li>

  

v-for也能用在内置标签<template>上,将多个元素进行渲染

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="main.css"/>
</head>
<div id="app">
    <template v-for="book in books">
        <ul>
            <li>书名:{{book.name}}</li>
            <li>作者:{{book.author}}</li>
        </ul>
    </template>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="main.js"></script>
</body>
</html>

  

js

var app = new Vue({
    el: '#app',
    data: {
        books: [
            {
                name:'python核心编程',
                author:'a'
            },
            {
                name:'go学习笔记',
                author: 'b'
            },
            {
                name:'vue.js实战',
                author:'c'
            }
        ]
    }
});

  

除数组外,对象的属性也是可以遍历的,两个可选参数,键值和索引

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="main.css"/>
</head>
<div id="app">
    <ul>
        <li v-for="(value,key,index) in user"> {{index}}-{{key}}:{{value}}
        </li>
    </ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="main.js"></script>
</body>
</html>

  

js

var app = new Vue({
    el: '#app',
    data: {
        user: {
            name:'somebody',
            age:28,
            gender:'男'
        }
    }
});

  

数组更新

vue的核心是数据与视图的双向绑定,当修改数组时m,Vue会检测到数据变化,所以用v-for渲染的视图也会立即更新

push pop shift splice sort reverse

example:将之前一个示例的数据books添加一项

app.books.push({
    name: 'css揭秘',
    author: 'd'
});

  

使用以上方法会该改变被这些方法调用的原始数组,有些方法不会改变原数组

filter slice concat

example:找出书名包含vue的

app.books = app.books.filter(function (item) {
    return item.name.match(/vue/);
});

  

vue在检测到数组变化时,并不是直接重新渲染整个列表,而是最大化复用dom,含有相同元素的项不会被重新渲染,因此新数组来替换旧数据

需要注意的是,以下变动的数组中,vue是不能检测到的,也不会触发视图更新

  • 通过索引直接设置项
  • 修改数组长度

解决第一个问题可以用vue内置的set方法

Vue.set(app.books,2,{
    name: 'javascript',
    author: 'd',
});

  

也可以用splice方法

app.books.splice(2,1,{
    name: 'javascript',
    author: 'e'
});

  

过滤与排序

如果不想改变原数组,想通过一个数组的副本来做过滤或排序的显示,可以用计算属性来返回过滤或排序后的数组

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="main.css"/>
</head>
<div id="app">
    <template v-for="book in filterBooks">
        <ul>
            <li>书名:{{book.name}}</li>
            <li>作者:{{book.author}}</li>
        </ul>
    </template>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="main.js"></script>
</body>
</html>

  

js

var app = new Vue({
    el: '#app',
    data: {
        books: [
            {
                name:'python核心编程',
                author:'a'
            },
            {
                name:'go学习笔记',
                author: 'b'
            },
            {
                name:'vue.js实战',
                author:'c'
            }
        ]
    },
    computed: {
        filterBooks: function () {
            return this.books.filter(function (book) {
                return book.name.match(/vue/);
            })
        }
    }
});

  

排序和搜索类似,不会修改books

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="main.css"/>
</head>
<div id="app">
    <template v-for="book in sortedBooks">
        <ul>
            <li>书名:{{book.name}}</li>
            <li>作者:{{book.author}}</li>
        </ul>
    </template>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="main.js"></script>
</body>
</html>

  

js

var app = new Vue({
    el: '#app',
    data: {
        books: [
            {
                name:'python核心编程',
                author:'a'
            },
            {
                name:'go语言学习笔记',
                author: 'b'
            },
            {
                name:'vue.js实战',
                author:'c'
            }
        ]
    },
    computed: {
        sortedBooks: function () {
            return this.books.sort(function (a,b) {
                return a.name.length < b.name.length
            })
        }
    }
});

  

方法与事件

example:监听一个按钮的点击事件,设置计数器,每次点击加1

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="main.css"/>
</head>
<div id="app">
    点击次数:{{ counter }}
    <button @click="counter++">+1</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="main.js"></script>
</body>
</html>

  

js

var app = new Vue({
    el: '#app',
    data: {
        counter:0
    }
})

  

@click的表达式可以直接使用JavaScript语句,也可以是一个在Vue实例中methods选项内的函数名

example:再加一个加10的按钮

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="main.css"/>
</head>
<div id="app">
    点击次数:{{ counter }}
    <button @click="handleAdd()">+1</button>
    <button @click="handleAdd(10)">+10</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="main.js"></script>
</body>
</html>

 

js

var app = new Vue({
    el: '#app',
    data: {
        counter:0
    },
    methods:{
        handleAdd:function (count) {
            count = count || 1;
            this.counter += count
        }
    }
})

  

练习:计算属性/指令开发购物车

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>购物车示例</title>
    <link rel="stylesheet" href="main.css"/>
</head>
<div id="app">
    <template v-if="list.length">
        <table>
            <thead>
                <tr>
                    <th>
                        <button @click="allChoose">全选</button>
                    </th>
                    <th></th>
                    <th>商品名称</th>
                    <th>商品单价</th>
                    <th>商品数量</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="(item,index) in list">
                    <td>
                        <input type="checkbox" v-model="item.checked">
                    </td>
                    <td>{{ index+1 }}</td>
                    <td>{{ item.name }}</td>
                    <td>{{ item.price }}</td>
                    <td>
                        <button @click="handleReduce(index)" :disabled="item.count === 1">-</button>
                        {{item.count}}
                        <button @click="handleAdd(index)">+</button>
                    </td>
                    <td>
                        <button @click="handleRemove(index)">移除</button>
                    </td>
                </tr>
            </tbody>
        </table>
        <div>总价:{{totalPrice}}</div>
    </template>
    <div v-else>购物车为空</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="main.js"></script>
</body>
</html>

  

 js

var app = new Vue({
    el:'#app',
    data: {
        list:[
            {
                id:1,
                name:'iphone',
                price:6188,
                count:1,
                checked:true,
            },
            {
                id:2,
                name:'ipad',
                price:5888,
                count:1,
                checked:true,
            },
            {
                id:3,
                name:'mbp',
                price:18888,
                count :1,
                checked:true,
            }
        ]
    },
    computed:{
        totalPrice:function () {
            var total=0;
            for (var i=0;i< this.list.length;i++) {
                var item = this.list[i];
                var status = this.list[i].checked;
                if (status === true)
                    total += item.price * item.count;
            }
            return total.toString().replace(/\B(?=(\d{3})+$)/g,',');
        }
    },
    methods:{
        handleReduce: function (index) {
            if (this.list[index].count === 1) return;
            this.list[index].count--;
        },
        handleAdd: function (index) {
            this.list[index].count++;
        },
        handleRemove: function (index) {
            this.list.splice(index,1)
        },
        allChoose: function () {
            for (var i=0;i< this.list.length;i++) {
                this.list[i].checked = true;
            }
        }
    }

});

  

css

table {
    border:1px solid #e9e9e9;
}
th,td {
    padding: 8px 16px;
    border: 1px solid #e9e9e9;
    text-align: left;
}

  

 

posted @ 2018-09-04 09:49  hongpeng0209  阅读(400)  评论(0编辑  收藏  举报