Vue的基础学习

Vue 的基本语法

1.Hello Vuejs

<div id="app">
    <p>{{message}}</p>
    <li v-for="item in movies">{{item}}</li>
    <h3>当前计数:{{counter}}</h3>
    <!-- 简写方式 -->
    <!-- <button v-on:click="counter++">+</button>
    <button v-on:click="counter--">-</button> -->
    <button v-on:click="add">+</button>
    <button @click="sub">-</button>
</div>
<script src="../js/vue.js"></script>
<script>
    //let:定义变量 coonst:定义常量
    const app = new Vue({
        el: '#app',//用于挂载要管理的元素
        data: {//定义数据
            message: '你好!',
            movies: ['战狼2', '哪吒', '星际穿越'],
            counter: 0
        },
        methods: {
            add:function(){
                this.counter++
            },
            sub:function(){
                this.counter--
            }
        }
    })
</script>

2.Mustache 语法

<div id="app">
    <h2>{{message}}</h2>
    <!--mustache语法中,不仅仅可以直接写变量,也可以写简单的表达式-->
    <h2>{{firstName+lastName}}</h2>
    <h2>{{firstName+' '+lastName}}</h2>
    <h2>{{firstName}} {{lastName}}</h2>
    <h2>{{counter*2}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: 'hello',
            firstName: 'chen',
            lastName: 'ganpin',
            counter: 100
        }
    })
</script>

3.指令的使用

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    .active {
      color: red;
    }
  </style>
</head>
<body>
<div id="app">
  <!--v-once表示元素和组件只渲染一次,不会随着数据的改变而改变-->
  <h2 v-once>{{message}}</h2>
  <!--v-text类似于mustache语法,但不常用,不够灵活-->
  <h2 v-text="message"></h2>
  <!--v-html 以html解析-->
  <h2 v-html="url"></h2>
  <!--原样输出,不解析-->
  <h2 v-pre>{{message}}</h2>
  <hr/>
  <!--动态绑定属性-->
  <img v-bind:src="imageUrl" alt="" width="20px">
  <a v-bind:href="aHref">百度</a>
  <a :href="aHref">百度</a><!--语法糖写法-->
  <!--动态绑定class(对象语法)-->
  <!--1.直接通过{}绑定一个类-->
  <!--2.可以通过判断,传入多个值-->
  <!--3.和普通的类同时存在,并不冲突-->
  <!--<h2 class="title" :class="{key1: value1,key2:value2}">{{message}}</h2>-->
  <h2 class="title" :class="{active: isActive,line:isLine}">{{message}}</h2>
  <h2 class="title" :class="getClass()">{{message}}</h2>
  <!--动态绑定class(数组语法)-->
  <h2 class="title" :class="[message,aHref]">{{message}}</h2>
  <!--动态绑定style(对象语法)-->
  <!--<h2 :style="{key(属性名):value(属性值)}">{{message}}</h2>-->
  <h2 :style="{fontSize: size}">{{message}}</h2>
  <button v-on:click="btnClick">按钮</button>
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: 'hello',
            url: '<a href="https://www.baidu.com">百度</a>',
            imageUrl: 'https://cn.vuejs.org/images/logo.png',
            aHref: 'https://www.baidu.com',
            isActive: true,
            isLine: true,
            size: '30px'
        },
        methods: {
            btnClick: function () {
                this.isActive = !this.isActive
            },
            getClass: function () {
                return {active: this.isActive, line: this.isLine}
            }
        }
    })
</script>
</body>
</html>

4.计算属性的使用

<!--计算属性会进行缓存,如果多次使用时,计算属性只会调用一次-->
<div id="app">
  <h2>{{fullName}}</h2>
  <h2>总价:{{totalPrice}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            firstName: 'Lebron',
            lastName: 'James',
            books: [
                {id: 101, name: '计算机', price: 95},
                {id: 102, name: '计算机大全', price: 68},
                {id: 103, name: '计算机系统', price: 78}
            ]
        },
        computed: {
            fullName: function () {
                return this.firstName + ' ' + this.lastName
            },
            //这是完整写法
            /*fullName: {
                //计算属性一般是没有set方法的,只读属性
                get: function () {
                    return this.firstName + ' ' + this.lastName
                }
            },*/
            totalPrice: function () {
                let result = 0;
                for (let book of this.books) {
                    result += book.price;
                }
                return result;
            }
        }
    })
</script>

5.事件监听

<div id="app">
  <!--.stop修饰符的使用-->
  <!--不加.stop点击按钮会同时触发 divClick 和 btnClick 方法-->
  <div @click="divClick">
    abc
    <button @click.stop="btnClick">按钮</button>
  </div>
  <hr/>
  <!--.prevent修饰符的使用-->
  <!--阻止点击时的自动提交-->
  <form action="/baidu">
    <input type="submit" value="提交" @click.prevent="submitClick">
  </form>
  <hr/>
  <!--监听某个键盘的键帽-->
  <!--只有输入回车键才会触发回调-->
  <input type="text" @keyup.enter="keyUp">
  <hr/>
  <!--.once 只触发一次回调-->
  <button @click.once="btn2Click">只点一次</button>
</div>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: 'hello'
        },
        methods: {
            btnClick() {
                console.log("btnClick")
            },
            divClick() {
                console.log("divClick")
            },
            submitClick() {
                console.log("submitClick")
            },
            keyUp() {
                console.log("keyUp")
            },
            btn2Click() {
                console.log("btn2Click")
            }
        }
    })
</script>

6.v-model 的原理


<div id="app">
  <!--v-model的使用-->
  <!--<input type="text" v-model="message">-->
  <!--v-model的实现原理-->
  <!--<input type="text" :value="message" @input="valueChange">-->
  <!--以上代码可以简写为-->
  <input type="text" :value="message" @input="message=$event.target.value">
  {{message}}
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: 'hello'
        },
        methods: {
            valueChange(event) {
                this.message = event.target.value;
            }
        }
    })
</script>

7. v-model 结合各种类型

<div id="app">
  <!--v-model能自动实现互斥单选 默认选中-->
  <label for="male">
    <input type="radio" id="male" value="" v-model="sex"></label>
  <label for="female">
    <input type="radio" id="female" value="" v-model="sex"></label>
  <h3>你选择的性别是:{{sex}}</h3>
  <hr><!--单选-->
  <label for="agree">
    <input type="checkbox" id="agree" v-model="isAgree">同意协议
  </label>
  <button :disabled="!isAgree">下一步</button>
  <hr><!--多选-->
  <input type="checkbox" value="篮球" v-model="hobbies">篮球
  <input type="checkbox" value="足球" v-model="hobbies">足球
  <input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球
  <h3>你当前的爱好是:{{hobbies}}</h3>
  <!--vue的值绑定示例-->
  <label :for="item" v-for="item in originHobbies">
    <input type="checkbox" :value="item" :id="item" v-model="hobbies">{{item}}
  </label>
  <hr><!--select选择一个-->
  <select name="fruit" v-model="fruit">
    <option value="苹果">苹果</option>
    <option value="香蕉">香蕉</option>
    <option value="雪梨">雪梨</option>
  </select>
  <h3>你选择的水果是:{{fruit}}</h3>
  <hr><!--select选择多个-->
  <select name="fruits" v-model="fruits" multiple><!--按住ctrl就能选中多个-->
    <option value="苹果">苹果</option>
    <option value="香蕉">香蕉</option>
    <option value="雪梨">雪梨</option>
    <option value="榴莲">榴莲</option>
  </select>
  <h3>你选择的水果是:{{fruits}}</h3>
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            sex: '男',//这个属性会被默认选中
            isAgree: false,//这个属性会被默认选中
            hobbies: [],
            originHobbies: ['篮球', '足球', '乒乓球', '羽毛球', '台球', '高尔夫球'],
            fruit: '香蕉',//这个属性会被默认选中
            fruits: []
        }
    })
</script>

8.v-model 修饰符的使用

<div id="app">
  <!--lazy修饰符:只有在输入回车或失去焦点时改变值-->
  <input type="text" v-model.lazy="message">{{message}}
  <hr>
  <!--number修饰符:让传过去的值自动转换为number类型-->
  <input type="number" v-model.number="age">
  <h3>{{age}} - {{typeof age}}</h3>
  <hr>
  <!--trim修饰符-->
  <input type="text" v-model.trim="name">
  <h3>名字:{{name}}</h3>
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: 'hello',
            age: 0,
            name: ''
        }
    })
</script>

Vue 格式化日期

<script src="https://cdn.bootcss.com/vue/2.6.11/vue.js"></script>
<!-- 引入moment日期格式化js -->
<script src="https://cdn.bootcss.com/moment.js/2.24.0/moment.js"></script>
<div id="app">
	<h2>{{date|dateFormat}}</h2><!-- 2015-10-20 -->
</div>
<script>
	const app = new Vue({
		el: '#app',
		data: {
			date: '2015-10-20T00:00:00',
		},
		filters: {
			dateFormat(el) {
				return moment(el).format("YYYY-MM-DD")
			}
		}
	})
</script>

组件化

1. 组件化的基本使用


<div id="app">
  <!--3.使用组件-->
  <my-cpn></my-cpn>
  <my-cpn></my-cpn>
</div>
<div id="app2">
  <my-cpn></my-cpn>
</div>
<script src="../js/vue.js"></script>
<script>
    //1.创建组件构造器对象
    const cpnC = Vue.extend({
        template: `
        <div>
          <h3>我是标题</h3>
          <p>我是内容</p>
          <p>我是内容2</p>
        </div>
        `
    });
    //2.注册组件(全局组件,能在app2中使用)
    Vue.component('my-cpn', cpnC);

    const app = new Vue({
        el: '#app',
        //2.注册组件(局部组件,只能在app中使用)
        /*components: {
            //cpn使用组件时的标签名
            cpn: cpnC
        }*/
    });
    //在开发中一般不会创建多个Vue实例
    const app2 = new Vue({
        el: '#app2'
    })
</script>

2. 父组件与子组件


<div id="app">
  <cpn2></cpn2>
  <!--这里不能直接使用cpnC1-->
  <!--<cpn1></cpn1>--><!--会报错`Unknown custom element: <cpn1>`如果要使用,需要再注册一次 -->
</div>
<script src="../js/vue.js"></script>
<script>
    //子组件
    const cpnC1 = Vue.extend({
        template: `
        <div>
          <h2>我是标题1</h2>
          <p>我是内容1</p>
        </div>
      `
    });
    //父组件
    const cpnC2 = Vue.extend({
        template: `
          <div>
            <h2>我是标题2</h2>
            <p>我是内容2</p>
            <cpn1></cpn1>
          </div>
        `,
        components: {
            cpn1: cpnC1
        }
    });
    //把这个当成根组件
    const app = new Vue({
        el: '#app',
        data: {
            message: 'hello'
        },
        components: {
            cpn2: cpnC2
        }
    })
</script>

3.组件的语法糖注册方式

<div id="app">
  <cpn1></cpn1>
  <cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
    //注册全局组件语法糖
    Vue.component('cpn1', {//这里的cpn1必须加 `''`
        template: `
      <div>
        <h2>我是标题</h2>
        <p>我是内容</p>
      </div>
      `
    });

    const app = new Vue({
        el: '#app',
        //注册局部组件的语法糖
        components: {
            cpn2: {//这里的cpn2不用
                template: `
                  <div>
                    <h2>我是标题</h2>
                    <p>我是内容</p>
                  </div>`
            }
        }
    })
</script>

4.组件模板的分离写法

<div id="app">
  <cpn></cpn>
  <cpn2></cpn2>
</div>

<!--方式一:script标签 注意类型  `type="text/x-template"`-->
<script type="text/x-template" id="cpn">
  <div>
    <h2>我是标题</h2>
    <p>我是内容</p>
  </div>
</script>

<template id="cpn2">
  <!--模板必须只有一个根标签-->
  <div>
    <h2>我是标题2</h2>
    <p>我是内容2</p>
  </div>
</template>
<script src="../js/vue.js"></script>
<script>
    //全局组件
    Vue.component('cpn', {
        template: '#cpn'
    });
    const app = new Vue({
        el: '#app',
        data: {
            message: 'hello'
        },
        //局部组件
        components: {
            cpn2: {
                template: '#cpn2'
            }
        }
    })
</script>

5. 组件通信 - 父传子


<div id="app">
  <!--这里的 cInfo 目前只能写成 c-info 因为html标签目前不支持驼峰写法-->
  <cpn :c-info="info"></cpn>
</div>

<template id="cpn">
  <h2>{{cInfo}}</h2>
</template>
<script src="../js/vue.js"></script>
<script>
    //父传子:props
    const cpn = {
        template: '#cpn',
        props: {
            cInfo: {
                type: Object,//指定类型
                default() {//默认值
                    return {}
                }
            }
        }
    };

    const app = new Vue({
        el: '#app',
        data: {
            info: {
                name: 'Manaphy',
                age: 18,
                height: 1.88
            }
        },
        components: {
            cpn
        }
    })
</script>

6.组件通信 - 子传父

<div id="app">
<!--3.父组件从这里接收数据-->
<cpn @item-click="cpnClick"></cpn>
<div>{{message}}</div>
</div>
<template id="cpn">
<div>
 <!--1.绑定自定义方法-->
 <button v-for="item in categories" @click="btnClick(item)">{{item.name}}</button>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
 const cpn = {
     template: '#cpn',
     data() {
         return {
             categories: [
                 {id: '001', name: '热门推荐'},
                 {id: '002', name: '手机数码'},
                 {id: '003', name: '家用家电'},
                 {id: '004', name: '电脑办公'},
             ]
         }
     },
     methods: {
         btnClick(item) {
             //2.子组件通过这里发射数据
             this.$emit('item-click', item)//这里的item-click 不能用 itemClick 在脚手架中可以用
         }
     }
 };
 const app = new Vue({
     el: '#app',
     data: {
         message: 'hello'
     },
     components: {
         cpn
     }, methods: {
         //4.在这里处理数据
         cpnClick(item) {
             this.message = item.name
         }
     }
 })
</script>

7.组件通信 - 父访问子

<div id="app">
  <cpn></cpn>
  <cpn></cpn>
  <cpn ref="chen"></cpn>
  <button @click="btnClick">按钮</button>
</div>

<template id="cpn">
  <div>我是子组件</div>
</template>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        methods: {
            btnClick() {
                //一般使用$children拿到所有的子组件
                console.log(this.$children);//获取子组件对象数组
                console.log(this.$children[0].name);//获取子组件的属性
                this.$children[0].showMessage();//调用子组件的方法
                //更多的是使用$refs拿到单个子组件
                console.log(this.$refs.chen.name);
                this.$refs.chen.showMessage()
            }
        },
        components: {
            cpn: {
                template: '#cpn',
                data() {
                    return {
                        name: 'manaphy'
                    }
                },
                methods: {
                    showMessage() {
                        console.log('showMessage')
                    }
                }
            }
        }
    })
</script>

8.组件通信 - 子访问父

<div id="app">
  <cpn></cpn>
</div>

<template id="cpn">
  <div>
    <div>我是子组件</div>
    <button @click="btnClick">按钮</button>
  </div>
</template>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            message: 'hello'
        },
        components: {
            cpn: {
                template: '#cpn',
                methods: {
                    btnClick() {
                        //访问父组件
                        //开发中用得极少,因为组件复用性会变差
                        console.log(this.$parent.message);
                        //访问根组件
                        console.log(this.$root.message);

                    }
                }
            }
        }
    })
</script>

9.组件化高级 - 插槽的基本使用

<div id="app">
  <cpn><button>按钮</button></cpn>
  <cpn><span>span</span></cpn>
  <cpn><i>哈哈哈</i></cpn>
</div>

<template id="cpn">
  <div>
    <h3>我是子组件</h3>
    <slot></slot>
    <!--<cpn><button>按钮</button></cpn>--><!--在插槽中添加内容表示使用没有添加内容时使用默认值-->
  </div>
</template>
<script src="../js/vue.js"></script>
<script>
    const cpn = {
        template: '#cpn'
    };
    const app = new Vue({
        el: '#app',
        components: {
            cpn
        }
    })
</script>

10.组件化高级 - 具名插槽的使用

<div id="app">
  <cpn>
    <span slot="center">标题</span>
    <button slot="center">按钮</button>
  </cpn>
</div>

<template id="cpn">
  <div>
    <slot name="left"><span>左边</span></slot>
    <slot name="center"><span>中间</span></slot>
    <slot name="right"><span>右边</span></slot>
  </div>
</template>
<script src="../js/vue.js"></script>
<script>
    const cpn = {
        template: '#cpn'
    }
    const app = new Vue({
        el: '#app',
        components: {
            cpn
        }
    })
</script>

11.组件化高级 - 作用域插槽的案例

<div id="app">
  <cpn></cpn>
  <cpn>
    <!--2.目的是获取子组件中的pLanguages-->
    <template slot-scope="slot"><!--该 slot 名字可自定义-->
      <!--通过slot.data获取子组件的数据-->
      <!--<span v-for="item in slot.data">{{item}} - </span>-->
      <span>{{slot.data.join(' - ')}}</span>
    </template>
  </cpn>
</div>

<template id="cpn">
  <div>
    <slot :data="pLanguages"><!--1.通过data(该名字可自定义)将子组件的数据传递给插槽-->
      <ul>
        <li v-for="item in pLanguages">{{item}}</li><!--这里pLanguages是子组件的数据-->
      </ul>
    </slot>
  </div>
</template>
<script src="../js/vue.js"></script>
<script>
    const cpn = {
        template: '#cpn',
        data() {
            return {
                pLanguages: ['Java', 'Python', 'Go', 'javaScript', 'C']
            }
        }
    };
    const app = new Vue({
        el: '#app',
        components: {
            cpn
        },

    })
</script>

经典案例

购物车案例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>图书购物车</title>
  <style>
    table {
      border: 1px solid #e9e9e9;
      border-collapse: collapse;
      border-spacing: 0;
    }

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

    th {
      background-color: #f7f7f7;
      color: #5c6b77;
      font-weight: 600;
    }
  </style>
</head>
<body>
<div id="app">
  <div v-if="books.length">
    <table>
      <thead>
      <tr>
        <th></th>
        <th>书籍名称</th>
        <th>出版日期</th>
        <th>价格</th>
        <th>购买数量</th>
        <th>操作</th>
      </tr>
      </thead>
      <tbody>
      <tr v-for="(item,index) in books">
        <td>{{item.id}}</td>
        <td>{{item.name}}</td>
        <td>{{item.date}}</td>
        <td>{{item.price|showPrice}}</td>
        <td>
          <button @click="decrement(index)" :disabled="item.count==1">-</button>
          {{item.count}}
          <button @click="increment(index)">+</button>
        </td>
        <td>
          <button @click="remove(index)">移除</button>
        </td>
      </tr>
      </tbody>
    </table>
    <h3>总价格: {{totalPrice|showPrice}}</h3>
  </div>
  <div v-else>
    <h3>购物车为空</h3>
  </div>
</div>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el: '#app',
        data: {
            books: [
                {
                    id: 1,
                    name: '《算法导论》',
                    date: '2006-9',
                    price: 85.00,
                    count: 1
                },
                {
                    id: 2,
                    name: '《UNIX编程艺术》',
                    date: '2006-2',
                    price: 59.00,
                    count: 1
                },
                {
                    id: 3,
                    name: '《编程珠玑》',
                    date: '2008-10',
                    price: 39.00,
                    count: 1
                },
                {
                    id: 4,
                    name: '《代码大全》',
                    date: '2006-3',
                    price: 128.00,
                    count: 1
                },
            ]
        },
        methods: {
            decrement(index) {
                this.books[index].count--
            },
            increment(index) {
                this.books[index].count++
            },
            remove(index) {
                this.books.splice(index, 1)
            }
        },
        computed: {
            totalPrice() {
                /*方式一*/
                /*let totalPrice = 0;
                for (const book of this.books) {
                    totalPrice += book.count * book.price;
                }
                return totalPrice;*/
                /*方式二*/
                /*return this.books.reduce(function (preValue, book) {
                    return preValue + book.price * book.count
                }, 0)*/
                /*方式三*/
                return this.books.reduce(((previousValue, book) => previousValue + book.price * book.count),0);

            }
        },
        filters: {
            showPrice(price) {
                return '¥' + price.toFixed(2)
            }
        }
    })
</script>
</body>
</html>

选项卡案例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type="text/css">
    .tab ul {
      overflow: hidden;
      padding: 0;
      margin: 0;
    }

    .tab ul li {
      box-sizing: border-box;
      padding: 0;
      float: left;
      width: 100px;
      height: 45px;
      line-height: 45px;
      list-style: none;
      text-align: center;
      border-top: 1px solid blue;
      border-right: 1px solid blue;
    }

    .tab ul li:first-child {
      border-left: 1px solid blue;
    }

    .tab ul li.active {
      background-color: orange;
    }

    .tab div {
      width: 500px;
      height: 300px;
      display: none;
      text-align: center;
      font-size: 30px;
      line-height: 300px;
      border: 1px solid blue;
      border-top: 0;
    }

    .tab div.current {
      display: block;
    }
  </style>
</head>
<body>
<div id="app">
  <div class="tab">
    <ul>
      <li @click='change(index)' :class='currentIndex==index?"active":""' v-for='(item,index) in list'>
        {{item.title}}
      </li>
    </ul>
    <div :class='currentIndex==index?"current":""' v-for='(item, index) in list'>
      <img :src="item.path" alt="">
    </div>
  </div>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            currentIndex: 0, // 选项卡当前的索引
            list: [
                {
                    id: 1,
                    title: 'apple',
                    path: 'img/apple.png'
                },
                {
                    id: 2,
                    title: 'orange',
                    path: 'img/orange.png'
                },
                {
                    id: 3,
                    title: 'lemon',
                    path: 'img/lemon.png'
                }]
        },
        methods: {
            change(index) {
                this.currentIndex = index;
            }
        }
    });
</script>
</body>
</html>
发布了25 篇原创文章 · 获赞 1 · 访问量 1977

猜你喜欢

转载自blog.csdn.net/weixin_45631876/article/details/104619125
今日推荐