最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 从基础到项目Vue2.0实战带你开发去哪网App——学习笔记

    正文概述 掘金(tangxd3)   2021-07-15   605

    第2章 课程介绍

    2.1 课程学习方法

    1.官方文档的阅读

    2.Vue实例的练习

    3.实战

    2.2 hello world

    1.Vue不支持IE8及以下的浏览器(支持所有兼容ECMAScript5的浏览器)

    2.<script>引入js的方式进行学习(开发版本)

    3.el:限制Vue处理Dom的范围 data:定义数据 {{}}:插值表达式

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>2.2节Hello World</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="app">{{ content }}</div>
        <script>
            // 直接操作DOM写法
            // var dom = document.getElementById('app');
            // dom.innerHTML = 'hello Vuejs';
            // setTimeout(function() {
            //     dom.innerHTML = 'bye Vue.js'
            // }, 2000)
    
            var app = new Vue({
                el: '#app',
                data: {
                    content: 'hello Vuejs'
                }
            })
            setTimeout(function() {
                app.$data.content = 'bye Vue.js'
            }, 2000)
            
        </script>
    </body>
    </html>
    

    2.3 开发TodoList(v-model、v-for、v-on)

    1.TodoList参考:www.todolist.cn

    2.v-for:用来循环数据

    <li v-for="item in list">{{ item }}</li>

    3.v-on:click:绑定click事件

    <button v-on:click="handleBtnClick">提交</button>

    4.v-model:数据的双向绑定

    <input type="text" v-model="inputValue">

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>2.3节TodoList-V1.0部分功能</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="app">
            <!-- v-model:数据的双向绑定 -->
            <input type="text" v-model="inputValue">
            <!-- v-on:click:绑定click事件 -->
            <button v-on:click="handleBtnClick">提交</button>
            <ul>
                <!-- v-for:用来循环数据 -->
                <li v-for="item in list">{{ item }}</li>
            </ul>
        </div>
        <script>
            var app = new Vue({
                el: '#app',
                data: {
                    list: [],
                    inputValue: ''
                },
                methods: {
                    handleBtnClick: function(){
                        this.list.push(this.inputValue)
                        this.inputValue = ''
                    }
                }
            })
        </script>
    </body>
    </html>
    

    2.4 MVVM(设计)模式

    1.MVP -> 使用jQuery完成TodoList:面向DOM

    View->Presenter->Model

    View<-Presenter<-Model

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>2.4节TodoList-jquery部分功能</title>
        <script src="../jquery.js"></script>
    </head>
    <body>
        <div>
            <input id="input" type="text">
            <button id="btn">提交</button>
            <ul id="list"></ul>
        </div>
        <script>
            // MVP设计模式 M:模型层 (无);V:视图;P:控制器;
            function Page() {   
            }
            $.extend(Page.prototype, {
                init: function () {
                    var btn = $('#btn');
                    btn.on('click', $.proxy(this.handleBtnClick, this))
                },
                handleBtnClick: function () {
                    var inputEle = $('#input');
                    var inputValue = $('#input').val();
                    var ulEle = $('#list');
                    ulEle.append('<li>' + inputValue + '</li>');
                    inputEle.val('');
                }
            })
            var page = new Page();
            page.init();
        </script>
    </body>
    </html>
    

    2.MVVM -> 通过操作数据来改变视图:面向数据

    View->ViewModel->Model

    View<-ViewModel<-Model

    2.1 View:DOM Model:Plain JavaScript Objects ViewModel:Vue

    2.5 前端组件化

    1.一个整体切分为不同的部分,每个部分就是一个组件

    2. 一个组件就是页面上的一个区域

    2.6 使用组件改造TodoList

    1.全局组件

    1.1创建全局组件:

    Vue.component("TodoItem", {
        props: ['content'],
        template: "<li>{{content}}</li>"
    })
    

    1.2使用全局组件:

    <todo-item v-bind:content="item"  v-for="item in list"></todo-item>
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>2.6节TodoList-V2.0部分功能组件化-全局组件</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="app">
            <!-- v-model:数据的双向绑定 -->
            <input v-model="inputValue" type="text">
            <!-- v-on:click:绑定click事件 -->
            <button v-on:click="handleBtnClick">提交</button>
            <!-- v-for:用来循环数据 -->
            <!-- v-bind:把数据绑定到组件 -->
            <ul>
                <!-- <li v-for="item in list">{{ item }}</li> -->
                <todo-item v-bind:content="item"  v-for="item in list"></todo-item>
            </ul>
        </div>
        <script>
            // component:创建全局组件
            Vue.component("TodoItem", {
                props: ['content'],
                template: "<li>{{content}}</li>"
            })
            var app = new Vue({
                el: '#app',
                data: {
                    list: [],
                    inputValue: ''
                },
                methods: {
                    handleBtnClick: function(){
                        this.list.push(this.inputValue)
                        this.inputValue = ''
                    }
                }
            })
        </script>
    </body>
    </html>
    

    2. 局部组件

    2.1创建局部组件:

    var TodoItem = {
        props: ['content'],
        template: "<li>{{content}}</li>" 
    }
    

    2.2注册局部组件:

    components: { TodoItem },
    

    2.2使用局部组件:

    <todo-item v-bind:content="item"  v-for="item in list"></todo-item>
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>2.6节TodoList-V2.0部分功能组件化-局部组件</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="app">
            <!-- v-model:数据的双向绑定 -->
            <input v-model="inputValue" type="text">
            <!-- v-on:click:绑定click事件 -->
            <button v-on:click="handleBtnClick">提交</button>
            <!-- v-for:用来循环数据 -->
            <!-- v-bind:把数据绑定到组件 -->
            <ul>
                <!-- <li v-for="item in list">{{ item }}</li> -->
                <todo-item v-bind:content="item"  v-for="item in list"></todo-item>
            </ul>
        </div>
        <script>
            var TodoItem = {
                props: ['content'],
                template: "<li>{{content}}</li>" 
            }
            var app = new Vue({
                el: '#app',
                data: {
                    list: [],
                    inputValue: ''
                },
                components: {
                    TodoItem
                },
                methods: {
                    handleBtnClick: function(){
                        this.list.push(this.inputValue)
                        this.inputValue = ''
                    }
                }
            })
        </script>
    </body>
    </html>
    

    2.7 简单的组件间传值

    1.父组件--->子组件

    父组件:在使用子组件时使用v-bind属性

    v-bind: content="item"  
    v-bind: index="index"  
    

    子组件:在使用子组件中使用props属性接受父组件传过来值

    props:['content', 'index'],
    

    2.子组件--->父组件

    子组件:在子组件的method方法中使用$emit方法向外触发一个事件

    this.$emit("delete", this.index)
    

    子组件:在使用子组件的标签上使用v-on监听delete事件然后触发自身的handleItemDelete方法

    v-on:delete="handleItemDelete"
    

    3.简写:v-bind:---》: v-on---》@

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>2.7节TodoList-V3.0完整功能</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="app">
            <!-- v-model:数据的双向绑定 -->
            <input v-model="inputValue" type="text">
            <!-- v-on:click:绑定click事件 -->
            <button v-on:click="handleBtnClick">提交</button>
            <!-- v-for:用来循环数据 -->
            <!-- v-bind:把数据绑定到组件 -->
            <ul>
                <!-- <li v-for="item in list">{{ item }}</li> -->
                <todo-item v-bind:content="item" v-bind:index="index"  v-for="(item, index) in list" 
                v-on:delete="handleItemDelete"></todo-item>
            </ul>
        </div>
        <script>
            var TodoItem = {
                props: ['content', 'index'],
                template: "<li v-on:click='handleItemClick'>{{content}}</li>" ,
                methods: {
                    handleItemClick: function() {
                        // $.emit:向父组件触发事件
                        this.$emit("delete", this.index)
                    }
                }
            }
            var app = new Vue({
                el: '#app',
                data: {
                    list: [],
                    inputValue: ''
                },
                components: {
                    TodoItem
                },
                methods: {
                    handleBtnClick: function(){
                        this.list.push(this.inputValue);
                        this.inputValue = '';
                    },
                    handleItemDelete: function (index) {
                        this.list.splice(index, 1);
                    }
                }
            })
        </script>
    </body>
    </html>
    

    2.8 本章小结

    Vue官网阅读‘基础’--->‘介绍’


    第3章 Vue基础精讲

    3.1 Vue实例

    1.Vue实例的创建

    var vm = new Vue({})
    // 这是一个根实例
    Vue.component('item', {
        template: '<div>hello</div>'    
    })
    // 组件也是一个实例
    

    2.Vue实例的属性

    el data method 可以在控制台用vm.$elvm.$datavm.$method

    3.2 Vue实例的生命周期

    1.生命周期函数定义:Vue实例在某一时间点会自动执行的函数(共11个)

    8个常用的生命周期函数:beforeCreate ---> created ---> (判断el) ---> (判断template) ---> beforeMount ---> mounted ---> (执行vm.$destory) ---> beforeDestory ---> destoryed ---> (当data改变时) ---> beforeUpdate ---> update 3个(不常用):activated、 deactivated、 errorCaptured

    2.Vue官网阅读‘Vue实例’

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vue的生命周期</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="app">{{ test }}</div>
        <script>
            // 生命周期函数就是Vue实例在某一个时间点自动执行的函数
            var vm = new Vue({
                el: '#app',
                data: {
                    test: 'hell Vue'
                },
                //页面渲染时执行beforeCreate、created、beforeMount、mounted
                beforeCreate: function () {
                    console.log("beforeCreate")
                },
                created: function () {
                    console.log("created")
                },
                beforeMount: function () {
                    console.log("beforeMount")
                },
                mounted: function () {
                    console.log("mounted")
                },
                //when vm.$destroy() is called
                beforeDestroy: function () {
                    console.log("beforeDestroy")
                },
                destroyed: function () {
                    console.log("destroyed")
                },
                //when data changes
                beforeUpdate: function () {
                    console.log("beforeUpdate")
                },
                updated: function () {
                    console.log("updated")
                },
            })
        </script>
    </body>
    </html>
    

    3.3 Vue的模板语法

    1.插值表达式:{{}}(与v-text作用完全相同)

    2.v-text:不解析html语法

    3.v-html:解析html语法

    4.插值表达式与v-text和v-html中的语法都时JavaScript表达式

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>模板语法</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="app">
            <div>{{ content }}</div>
            <!-- 此处content为JS表达式 -->
            <div v-text="content"></div>
            <!-- v-html:不进行转义直接解释输出 -->
            <div v-html="'Hello' + content"></div>
        </div>
        <script>
            var app = new Vue({
                el: '#app',
                data: {
                    content: '<h1>Vue</h1>'
                }
            })
        </script>
    </body>
    </html>
    

    3.4 计算属性、方法、侦听器

    1.计算属性

    特点:内置缓存,依赖值无变化就不会进行计算

    2.方法

    特点:无内置缓存,只要页面重新渲染就要重新执行

    3.侦听器

    特点:侦听的变量变化时才会执行程序

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>计算属性、方法、监听器</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="app">
            {{ fullName }}
            <!-- 方法:{{ fullName() }} -->
            {{ age }}
        </div>
        <script>
            var app = new Vue({
                el: '#app',
                data: {
                    firstName: 'vience',
                    lastName: 'tang',
                    fullName: 'vience tang',//watch
                    age: 23
                },
                //计算属性(推荐使用)
                //内置缓存,依赖值无变化就不会进行计算
                // computed: {
                //     fullName: function() {
                //         console.log("计算属性");
                //         return this.firstName + " " + this.lastName;
                //     }
                // }
                //方法
                //无内置缓存只要刷新就要重新执行
                // methods: {
                //     fullName: function () {
                //         console.log("方法");
                //         return this.firstName + " " + this.lastName;
                //     }
                // }
                //侦听的变量变化时才会执行程序
                watch: {
                    firstName: function () {
                        console.log("监听firstName");
                        this.fullName = this.firstName + " " + this.lastName;
                    },
                    lastName: function () {
                        console.log("监听lastName");
                        this.fullName = this.firstName + " " + this.lastName;
                    }
                }
            })   
        </script>
    </body>
    </html>
    

    3.5 计算属性的setter和getter

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>计算属性的setter和getter</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="app">
            {{ fullName }}
        </div>
        <script>
            var app = new Vue({
                el: '#app',
                data: {
                    firstName: 'vience',
                    lastName: 'tang',
                },
                computed: {
                    fullName: {
                        get: function() {
                            return this.firstName + " " + this.lastName;
                        },
                        set: function(value) {
                            var arr = value.split(" ");
                            this.firstName = arr[0];
                            this.lastName = arr[1];
                        }
                    }
                }
            })   
        </script>
    </body>
    </html>
    

    3.6 Vue中的样式绑定

    1.class样式绑定

    对象方式::class="{activated: isActivated}" 数组方式::class="[activated]"

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vue中的样式绑定-class</title>
        <script src="../vue.js"></script>
        <style>
            .activated { color: red; }
        </style>
    </head>
    <body>
        <div id="app">
            <!-- <div :class="{activated: isActivated}" @click="handleDivClick">
                Hello world
            </div> -->
            <div :class="[activated]" @click="handleDivClick">
                Hello world
            </div>
        </div>
        <script>
            var vm = new Vue({
                el: '#app',
                data: {
                    // isActivated: false,
                    activated: ''
                },
                methods: {
                    handleDivClick: function () {
                        // this.isActivated = !this.isActivated
                        this.activated = this.activated ===  'activated' ? '' : 'activated'
                    }
                }
            })   
        </script> 
    </body>
    </html>
    

    2.style样式绑定

    对象方式::style="styleOBj" 数组方式::style="[styleOBj, {fontSize: '20px'}]"

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vue中的样式绑定-style</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="app">
            <!-- <div :style="styleOBj" @click="handleDivClick">
                Hello world
            </div> -->
            <div :style="[styleOBj, {fontSize: '20px'}]" @click="handleDivClick">
                Hello world
            </div>
        </div>
        <script>
            var app = new Vue({
                el: '#app',
                data: {
                    styleOBj: {
                        color: 'black'
                    }
                },
                methods: {
                    handleDivClick: function () {
                       this.styleOBj.color = this.styleOBj.color === 'black' ? 'red' : 'black' 
                    }
                }
            })   
        </script> 
    </body>
    </html>
    

    3.7 Vue中的条件渲染

    1.v-if:值为true时显示,值为false时消失

    特点:通过DOM的生成与删除实现,比较耗费性能

    2.v-show:值为true时显示,值为false时消失

    特点:通过CSS中display的值为none来进行隐藏,节省性能

    3.v-if v-else-if v-else

    注意点1:必须连在一起进行使用 注意点2:若在v-if和v-else(v-else-if)中同事使用input标签时一定要定义不同的key值,若无则会复用已经再在的input标签

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vue中的条件渲染</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="app">
            <!-- 连在一起写 -->
            <!-- <div v-if="show === 'a'">This is A</div>
            <div v-else-if="show === 'b'">This is B</div>
            <div v-else>This is others</div> -->
            <!-- 删除新加DOM -->
            <div v-if="show">{{msg}}</div>
            <div v-else>Bye World</div>
            <!-- 若v-if下与v-else下都有一个input输入框时,需要使用不同的key值进行区别,因为VUE会默认减少不必要的渲染而默认使用之前的input -->
            <!-- 使用display:none 优先使用 减少DOM的删除与渲染-->
            <div v-show="show">{{msg}}</div>
        </div>
        <script>
            var app = new Vue({
                el: '#app',
                data: {
                    show: false,
                    // show: 'a',
                    msg: 'Hello world'
                }
            })   
        </script> 
    </body>
    </html>
    

    3.8 Vue中的列表渲染

    1.数组的列表渲染

    注意点:使用后端放回的唯一值作为key值

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vue中的列表渲染</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="app">
            <!-- <div v-for='item in list'>{{item}}</div> -->
            <!-- 不推荐使用index做为key值,因为使用index作为key值时会存在相同的情况,而且还比较耗费性能 -->
            <!-- <div v-for='(item, index) of list' :key='index'>{{index}}---{{item}}</div> -->
            <div v-for='item of list' :key='item.id'>{{item.id}}---{{item.text}}</div>
        </div>
        <script>
            var app = new Vue({
                el: '#app',
                data: {
                    // list: ["hello", "vience", "nice", "to", "meet", "you"]
                    list: [ { id: '000001', text: 'hello' }, { id: '000002', text: 'vience' }, { id: '000003', text: 'nice' }, { id: '000004', text: 'to' }, { id: '000005', text: 'meet' }, { id: '000006', text: 'you' } ]
                }
            })   
        </script> 
    </body>
    </html>
    

    2.操作数组

    注意点:通过数组下标来操作数组,页面不会发生重新渲染,若想发生重新渲染则应该使用下面的两种方法

    1.操作数组的方法(变异方法7个):push pop shift unshift splice sort reserve

    控制台操作: vm.list.splice(1, 1, {id: '222222', text: 'Tang'})

    2.数组是引用类型,直接改变引用即可

    控制台操作: vm.list = [ { id: '000001', text: 'hello' }, { id: '222222', text: 'Tang' }, { id: '000003', text: 'nice' }, { id: '000004', text: 'to' }, { id: '000005', text: 'meet' }, { id: '000006', text: 'you' } ]

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vue中的列表渲染---操作数组</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="app">
            <!-- <div v-for='item in list'>{{item}}</div> -->
            <!-- 不推荐使用index做为key值,因为使用index作为key值时会存在相同的情况,而且还比较耗费性能 -->
            <!-- <div v-for='(item, index) of list' :key='index'>{{index}}---{{item}}</div> -->
            <div v-for='item of list' :key='item.id'>{{item.id}}---{{item.text}}</div>
            <!-- 注意点:通过数组下标来操作数组,页面不会发生重新渲染,若想发生重新渲染则应该使用下面的两种方法 -->
            <!-- 1.操作数组的方法:push pop shift unshift splice sort reserve -->
            <!-- 控制台操作:vm.list.splice(1, 1, {id: '222222', text: 'Tang'}) -->
            <!-- 2.数组是引用类型,直接改变引用即可 -->
            <!-- 控制台操作:vm.list = [ { id: '000001', text: 'hello' }, { id: '222222', text: 'Tang' }, { id: '000003', text: 'nice' }, { id: '000004', text: 'to' }, { id: '000005', text: 'meet' }, { id: '000006', text: 'you' } ] -->
        </div>
        <script>
            var vm = new Vue({
                el: '#app',
                data: {
                    // list: ["hello", "vience", "nice", "to", "meet", "you"]
                    list: [ { id: '000001', text: 'hello' }, { id: '000002', text: 'vience' }, { id: '000003', text: 'nice' }, { id: '000004', text: 'to' }, { id: '000005', text: 'meet' }, { id: '000006', text: 'you' } ]
                }
            })   
        </script> 
    </body>
    </html>
    

    ###3.对象循环渲染 <div v-for='(item, key, index) of userInfo'>{{index}}---{{key}}---{{item}}</div> 注意点:若想给对象增加属性,则需要改变对象的引用

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vue中的列表渲染---对象</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="app">
            <div v-for='(item, key, index) of userInfo'>{{index}}---{{key}}---{{item}}</div>
            <!-- 若想给对象增加属性,则需要改变对象的引用 -->
            <!-- 控制台输入:vm.userInfo =  { id: '000001', name: 'vience', age: 23, salary: 'secret', address: '南京' } -->
        </div>
        <script>
            var vm = new Vue({
                el: '#app',
                data: { userInfo: { id: '000001', name: 'vience', age: 23, salary: 'secret' } }
            })   
        </script> 
    </body>
    </html>
    

    3.9 Vue中的set方法

    Vue.set(vm.userInfo, 'address', '南京') vm.$set(vm.userInfo, 'address', '南京')

    1.对象中的set方法

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vue中的set方法---对象</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="app">
            <div v-for='(item, key, index) of userInfo'>{{index}}---{{key}}---{{item}}</div>
            <!-- 若想给对象增加属性,则需要改变对象的引用 -->
            <!-- 控制台输入:vm.userInfo =  { id: '000001', name: 'vience', age: 23, salary: 'secret', address: '南京' } -->
            <!-- 使用set方法也可以改变对象 -->
            <!-- 控制台输入:Vue.set(vm.userInfo, 'address', '南京') 或者 vm.$set(vm.userInfo, 'address', '南京')  -->
        </div>
        <script>
            var vm = new Vue({
                el: '#app',
                data: { userInfo: { id: '000001', name: 'vience', age: 23, salary: 'secret' } }
            })   
        </script> 
    </body>
    </html>
    

    2.数组中的set方法

    Vue.set(vm.userInfo, 1, 5) vm.$set(vm.userInfo, 2, 10)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Vue中的set方法---数组</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="app">
            <div v-for='(item, index) of userInfo'>{{index}}---{{item}}</div>
            <!-- 使用set方法改变数组 -->
            <!-- 控制台输入:Vue.set(vm.userInfo, 1, 5) 或者 vm.$set(vm.userInfo, 2, 10)  -->
        </div>
        <script>
            var vm = new Vue({
                el: '#app',
                data: { userInfo: ['1', '2', '3', '4'] }
            })   
        </script> 
    </body>
    </html>
    

    第4章 深入理解Vue组件

    4.1 组件使用的细节点

    1.通过is="row"解决table、ul、ol、select中出现的bug

    <tr is="row"></tr>

    2.子组件之中的data必须是一个函数,返回一个对象,而不是一个对象

    data: function() {
        return {
            content: 'This is a row'
        }
    },
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>4.1节组件使用中的细节点</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="root">
            <!-- 通过is="row"解决table、ul、ol、select中出现的bug -->
            <!-- <table>
                <tbody>
                    <tr is="row"></tr>
                    <tr is="row"></tr>
                    <tr is="row"></tr>
                </tbody>
            </table> -->
            <!-- <table>
                <tbody>
                    <tr is="row"></tr>
                    <tr is="row"></tr>
                    <tr is="row"></tr>
                </tbody>
            </table> -->
            <div ref='hello' @click="handleClick" >
                hello world
            </div>
        </div>
        <script>
            // Vue.component('row', {
            // 子组件之中的data必须是一个函数,返回一个对象,而不是一个对象
            // data: function() {
            //     return {
            //         content: 'This is a row'
            //     }
            // },
            //     template: '<tr><td>{{content}}</td></tr>'
            // })
            var vm = new Vue({
                el: '#root',
                methods: {
                    handleClick: function() {
                        console.log(this.$refs.hello.innerHTML)
                        // alert('123')
                    }
                }
            })  
        </script>
    </body>
    </html>
    

    3.ref的使用

    3.1 ref使用div标签上时,通过this.$refs.XXX获取的是该标签对应的DOM元素

    3.1 ref使用子组件上时,通过this.$refs.XXX获取的是子组件的引用

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>4.1节组件使用中的细节点---ref的用法</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="root">
            <!-- ref使用div标签上时,通过this.$refs.XXX获取的是该标签对应的DOM元素 -->
            <!-- ref使用子组件上时,通过this.$refs.XXX获取的是子组件的引用 -->
            <counter ref='one' @change='handleChange'></counter>
            <counter ref='two' @change='handleChange'></counter>
            <div>{{ total }}</div>
        </div>
        <script>
            Vue.component('counter', {
                template: '<div @click="handleClick">{{ number }}</div>',
                data: function() {
                    return { number: 0 }
                },
                methods: {
                    handleClick: function() {
                        this.number ++
                        this.$emit('change')
                    }
                }
            })
            var vm = new Vue({
                el: '#root',
                data: { total: 0 },
                methods: {
                    handleChange: function() {
                        this.total = this.$refs.one.number + this.$refs.two.number
                    }
                }
            })  
        </script>
    </body>
    </html>
    

    4.2 父子组件之间的数据传递

    1.父组件 ---> 子组件

    父组件通过属性的形式向子组件传递数据 <counter :count='2'></counter> 子组件使用props接收父组件传来的数组 props: ['count'],

    2.子组件 ---> 父组件

    子组件使用this.emit(inc,2,2)方法向父组件传递一个触发事件(可以携带一个或多个参数)this.emit('inc', 2, 2)方法向父组件传递一个触发事件(可以携带一个或多个参数) `this.emit(′inc′,2,2)方法向父组件传递一个触发事件(可以携带一个或多个参数)‘this.emit('inc', 2)父组件通过对事件进行监听来接收子组件传过来的值<counter :count='2' @inc='hanleIncrease'>`

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>4.2节父子组件间的数据传递</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="root">
            <counter :count='2' @inc='hanleIncrease'></counter>
            <counter :count='3' @inc='hanleIncrease'></counter>
            <div>{{ total }}</div>
        </div>
        <script>
            var counter = {
                props: ['count'],
                data: function() {
                    return { number: this.count }
                },
                template: '<div @click="handleClick">{{ number }}</div>',
                methods: {
                    handleClick: function() {
                        // 单向数据流:子组件不能修改父组件传递过来的值,可以通过clone一个副本进行修改
                        this.number = this.number + 2
                        // 子组件通过this.$emit('inc', 2,2)方法向父组件传递一个触发事件(可以携带一个或多个参数)
                        this.$emit('inc', 2)
                    }
                }
            }
            var vm = new Vue({
                el: '#root',
                data: { total: 5 },
                components: { counter },
                methods: {
                    hanleIncrease: function(val) {
                        this.total += val
                    }
                }
            })  
        </script>
    </body>
    </html>
    

    4.3 组件参数校验与非props特性

    1.组件参数校验

    props: ['content'] props: { content: String } props: { content: [String, Number] }

    props: {
        content: {
            type: String,
            // required: true,
            // default: 'default value'
            validator: function(value) {
                return (value.length > 5)
            }
        }
    }
    

    2.非props特性

    非props特性: 子组件没有接受对应的值,而组件使用了,就会报错;父组件调用子组件时,传值的属性会显示在DOM中

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>4.3节组件参数校验与非props特性</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="root">
            <child content='hello world'></child>
        </div>
        <script>
            Vue.component('child',{
                // props特性:父组件传值,子组件要接收对应的值,父组件调用子组件时,传值的属性不会显示在DOM中
                // 非props特性: 子组件没有接受对应的值,而组件使用了,就会报错;父组件调用子组件时,传值的属性会显示在DOM中
                // props: ['content']
                // props: { content: String }
                // props: { content: [String, Number] }
                props: {
                    content: {
                        type: String,
                        // required: true,
                        // default: 'default value'
                        validator: function(value) {
                            return (value.length > 5)
                        }
                    }
                },
                template: '<div>{{ content }}</div>'
            })
            var vm = new Vue({ el: '#root', })  
        </script>
    </body>
    </html>
    

    4.4 给组件绑定原生事件

    <child @click.native='handleClick'></child>

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>4.4节给组件绑定原生事件</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="root">
            <!-- 在子组件上绑定的事件属于自定义事件 -->
            <!-- <child @click='handleClick'></child> -->
            <child @click.native='handleClick'></child>
        </div>
        <script>
            Vue.component('child',{
                // 在div元素上绑定的时间属于原生事件
                // template: '<div @click="handleClick">Child</div>',
                // methods: {
                //     handleClick: function() {
                //         this.$emit('click')
                //     }
                // }
                template: '<div>Child</div>',
            })
            var vm = new Vue({
                el: '#root',
                methods: {
                    handleClick: function() {
                        alert('click')
                    }
                }
            })  
        </script>
    </body>
    </html>
    

    4.5 非父子组件间的传值

    1. Vuex

    2. Bus/总线/发布订阅模式/观察者模式

    Bus创建:

    Vue.prototype.bus = new Vue()

    事件触发:

    this.bus.$emit('change', this.selfContent)

    事件监听(单向数据流,不能直接改变父组件传来的值,通过clone改变副本):

    this.bus.$on('change', function(msg){
        this_ .selfContent = msg
    })
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>4.5节非父子组件间的传值</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="root">
            <!-- Bus/总线/发布订阅模式/观察者模式 -->
            <child content='vience'></child>
            <child content='tang'></child>
        </div>
        <script>
            Vue.prototype.bus = new Vue()
            Vue.component('child',{
                data: function() {
                    return {
                        selfContent: this.content
                    }
                },
                props: { content: String },
                template: '<div @click="handleClick">{{selfContent}}</div>',
                methods: {
                    handleClick: function() {
                        this.bus.$emit('change', this.selfContent)
                    }
                },
                mounted: function() {
                    var this_ = this
                    this.bus.$on('change', function(msg){
                        this_ .selfContent = msg
                    })
                }
            })
            var vm = new Vue({
                el: '#root',
            })  
        </script>
    </body>
    </html>
    

    4.6 在vue中使用插槽(slot)

    1. 插槽一般用于父组件向子组件传递一段DOM结构()

    2. 默认内容

    3. 具名插槽(支持默认内容)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>4.6节在vue中使用插槽</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="root">
            <!-- slot:用于父组件向子组件传递DOM结构 -->
            <!-- <child content='<p>vience</p>'></child> -->
            <child>
                <!-- 当传入的DOM结构为空时slot显示默认内容 -->
                <!-- <p>vience</p> -->
                <!-- 具名插槽(支持默认内容) -->
                <div class="header" slot="header">header</div>
                <div class="footer" slot="footer">footer</div>
            </child>
        </div>
        <script>
            Vue.component('child',{
                props: { content: String },
                // template: `<div>
                //                 <p>hello</p>
                //                 <div v-html='this.content'></div>
                //             </div>`,
                // template: `<div>
                //                 <p>hello</p>
                //                 <slot>默认内容</slot>
                //             </div>`,
                template: `<div>
                                <slot name='header'></slot>
                                <div>content</div>
                                <slot name='footer'></slot>
                            </div>`,
            })
            var vm = new Vue({ el: '#root', })  
        </script>
    </body>
    </html>
    

    4.7 作用域插槽

    使用场景:当子组件做循环或者某一部分显示的DOM由外部传入时使用作用域插槽

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>4.7节作用域插槽</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="root">
            <child>
                <template slot-scope="props">
                    <!-- <li> {{props.item}} - hello </li> -->
                    <h1> {{props.item}} </h1>
                </template>
            </child>
        </div>
        <script>
            Vue.component('child',{
                data: function() {
                    return { list: [1, 2, 3, 4] }
                },
                template: `<div><ul> <slot v-for='item of list' :item=item></slot> </ul></div>`,
            })
            var vm = new Vue({ el: '#root' })  
        </script>
    </body>
    </html>
    

    4.8 动态组件与v-once指令

    1. 动态组件:<component :is='type'></component>

    2. v-once:放在缓存中重复使用

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>4.8节动态组件与v-once指令</title>
        <script src="../vue.js"></script>
    </head>
    <body>
        <div id="root">
                <child-one v-if="type=== 'child-one'"></child-one>
                <child-two v-if="type=== 'child-two'"></child-two>
                <!-- <component :is='type'></component> -->
                <button @click="handleBtnClick">change</button>
        </div>
        <script>
            Vue.component('child-one',{
                template: `<div v-once>child-one</div>`,
            })
            Vue.component('child-two',{
                template: `<div v-once>child-two</div>`,
            })
            var vm = new Vue({ 
                el: '#root',
                data: {
                    type: 'child-one'
                },
                methods: {
                    handleBtnClick: function() {
                        this.type = (this.type === 'child-one' ? 'child-two' : 'child-one')
                    }
                }
            })  
        </script>
    </body>
    </html>
    

    第5章 Vue中的动画特效

    5.1 Vue中的CSS动画原理

    1. 过渡动画效果

    通过某一时刻往标签上增加或者移除clss来实现动画效果

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>5.1节Vue中的CSS动画原理</title>
        <script src="../vue.js"></script>
        <style>
            .v-enter, .v-leave-to  { opacity: 0; }
            .v-enter-active, .v-leave-active { transition: opacity 3s; }
        </style>
    </head>
    <body>
        <div id="root">
            <!-- 通过某一时刻往标签上增加或者移除clss来实现动画效果 -->
            <!-- 过渡动画效果 -->
            <transition>
                <!-- <div v-if='show'>hello world</div> -->
                <div v-show='show'>hello world</div>
            </transition>
            <button @click="handleBtnClick">切换</button>
        </div>
        <script>
            var vm = new Vue({ 
                el: '#root',
                data: { show: true },
                methods: {
                    handleBtnClick: function() {
                        this.show = !this.show
                    }
                }
            })  
        </script>
    </body>
    </html>
    

    5.2 Vue中使用animate.css库

    1. 使用link引入animate.css文件

    <link rel="stylesheet" href="../animate.css">

    2. 给transition1标签增加enter-active-class和leave-active-class属性并对这两个属性赋值为animated和所需动画效果即可

    <transition name='fade' enter-active-class='animated swing' leave-active-class='animated shake'>
        <div v-show='show'>hello world</div>
    </transition>
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>5.1节Vue中使用animate.css库</title>
        <script src="../vue.js"></script>
        <link rel="stylesheet" href="../animate.css">
        <!-- <style>
            @keyframes bounce-in {
                0% { transform: scale(0); }
                50% { transform: scale(1.5); }
                100% { transform: scale(1); }
            }
            .active {  transform-origin: left center; animation: bounce-in 1s; }
            .leave { transform-origin: left center; animation: bounce-in 1s reverse; }
        </style> -->
    </head>
    <body>
        <div id="root">
            <!-- <transition name='fade' enter-active-class='active' leave-active-class='leave'>
                <div v-show='show'>hello world</div>
            </transition> -->
            <transition name='fade' enter-active-class='animated swing' leave-active-class='animated shake'>
                    <div v-show='show'>hello world</div>
                </transition>
            <button @click="handleBtnClick">切换</button>
        </div>
        <script>
            var vm = new Vue({ 
                el: '#root',
                data: { show: true },
                methods: {
                    handleBtnClick: function() {
                        this.show = !this.show
                    }
                }
            })  
        </script>
    </body>
    </html>
    

    5.3 在Vue中同时使用过渡和动画

    1. 第一次显示时出现时显示动画

    appear appear-active-class='animated swing'

    2. 在Vue中同时使用过渡和动画

    <style>
        .fade-enter, .fade-leave-to  { opacity: 0; }
        .fade-enter-active, .fade-leave-active { transition: opacity 3s; }
    </style>
     <transition type='transition' name='fade' appear appear-active-class='animated swing' enter-active-class='animated swing fade-enter-active' leave-active-class='animated shake fade-leave-active'>
    

    3. 在Vue中同时使用过渡和动画时动画时长设置

    动画时长以transition为准(3s) type='transition' 自定义动画时长 :duration='1000' :duration='{enter:5000, leave:10000}'

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>5.1节在Vue中同时使用过渡和动画</title>
        <script src="../vue.js"></script>
        <link rel="stylesheet" href="../animate.css">
        <style>
            .fade-enter, .fade-leave-to  { opacity: 0; }
            .fade-enter-active, .fade-leave-active { transition: opacity 3s; }
        </style>
    </head>
    <body>
        <div id="root">
            <!-- appear appear-active-class='animated swing' 第一次显示时出现动画 -->
            <!-- type='transition' 动画时长以transition为准(3s) -->
            <!-- :duration='1000' 自定义动画时长 :duration='{enter:5000, leave:10000}' -->
            <transition type='transition' name='fade' appear appear-active-class='animated swing' enter-active-class='animated swing fade-enter-active' leave-active-class='animated shake fade-leave-active'>
                    <div v-show='show'>hello world</div>
                </transition>
            <button @click="handleBtnClick">切换</button>
        </div>
        <script>
            var vm = new Vue({ 
                el: '#root',
                data: { show: true },
                methods: {
                    handleBtnClick: function() {
                        this.show = !this.show
                    }
                }
            })  
        </script>
    </body>
    </html>
    

    5.4 Vue中JS动画与Velocity.jsde结合

    1. JS动画钩子

    入场:before-enter,enter,after-enter 离场:before-leave,leave,after-leave

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>5.4节Vue中JS动画与Velocity.jsde结合</title>
        <script src="../vue.js"></script>
        <script src="../velocity.js"></script>
    </head>
    <body>
        <div id="root">
            <!-- 离场动画同理 -->
            <transition name='fade' @before-enter='handleBeforeEnter' @enter='handleEnter' @after-enter='handleAfterEnter'>
                    <div v-show='show'>hello world</div>
                </transition>
            <button @click="handleBtnClick">切换</button>
        </div>
        <script>
            var vm = new Vue({ 
                el: '#root',
                data: { show: true },
                methods: {
                    handleBtnClick: function() {
                        this.show = !this.show
                    },
                    // handleBeforeEnter: function(el) { el.style.color = 'red' },
                    // handleEnter: function(el, done) {
                    //     setTimeout(() => { el.style.color = 'green' }, 2000)
                    //     setTimeout(() => { done() }, 4000)
                    // },
                    // handleAfterEnter: function(el) { el.style.color = '#000000' }
                    handleBeforeEnter: function(el) {
                        el.style.opacity = 0
                    },
                    handleEnter: function(el, done) {
                        Velocity(el, {opacity: 1}, {duration: 1000, complete: done})
                    },
                    handleAfterEnter: function(el) {
                        console.log('动画结束')
                    }
                }
            })  
        </script>
    </body>
    </html>
    

    5.5 Vue中多个元素或组件间的过渡

    1. 多个元素之间

    mode='in-out':先进入后隐藏 mode='out-in':先隐藏后进入

    2. 多个组件之间

    <component :is='type'></component>

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>5.5节Vue中多个元素或组件间的过渡</title>
        <script src="../vue.js"></script>
        <style>
            .v-enter, .v-leave-to  { opacity: 0; }
            .v-enter-active, .v-leave-active { transition: opacity 1s; }
        </style>
    </head>
    <body>
        <div id="root">
            <!-- mode='in-out':先进入后隐藏 mode='out-in':先隐藏后进入 -->
            <!-- <transition mode='out-in'>
                <div v-if='show' key='hello'>hello world</div>
                <div v-else key='bye'>bye world</div>
            </transition> -->
            <!-- <transition mode='out-in'>
                <child v-if='show'></child>
                <child-one v-else></child-one>
            </transition> -->
            <transition mode='out-in'>
                <component :is='type'></component>
            </transition>
            <button @click="handleBtnClick">切换</button>
        </div>
        <script>
            Vue.component('child', {
                template: '<div>child</div>'
            })
            Vue.component('child-one', {
                template: '<div>child-one</div>'
            })
            var vm = new Vue({ 
                el: '#root',
                data: { 
                    // show: true,
                    type: 'child'
                },
                methods: {
                    handleBtnClick: function() {
                        // this.show = !this.show
                        this.type = this.type === 'child' ? 'child-one' : 'child'
                    }
                }
            })  
        </script>
    </body>
    </html>
    

    5.6 Vue中的列表过渡

    对循环的div外部添加transition-group标签 <transition-group></transition-group>

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>5.6节Vue中的列表过渡</title>
        <script src="../vue.js"></script>
        <style>
            .v-enter, .v-leave-to  { opacity: 0; }
            .v-enter-active, .v-leave-active { transition: opacity 1s; }
        </style>
    </head>
    <body>
        <div id="root">
            <transition-group>
                <div v-for='item of list' :key='item.id'>{{ item.title }}</div>
            </transition-group>
            <button @click="handleBtnClick">Add</button>
        </div>
        <script>
            var count = 0;
            var vm = new Vue({ 
                el: '#root',
                data: { list: [] },
                methods: {
                    handleBtnClick: function() {
                        this.list.push({ id: count++, title: 'hello world' })
                    }
                }
            })  
        </script>
    </body>
    </html>
    

    5.7 Vue中的动画封装

    1. 封装模板,写CSS样式

    <style>
        .v-enter, .v-leave-to  { opacity: 0; }
        .v-enter-active, .v-leave-active { transition: opacity 1s; }
    </style>
    

    2. 用JS动画封装在组件中(推荐使用方式)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>5.7节Vue中的动画封装</title>
        <script src="../vue.js"></script>
        <!-- <style>
            .v-enter, .v-leave-to  { opacity: 0; }
            .v-enter-active, .v-leave-active { transition: opacity 1s; }
        </style> -->
    </head>
    <body>
        <div id="root">
            <fade :show='show'>
                <div>hello world</div>
            </fade>
            <fade :show='show'>
                <h1>hello world</h1>
            </fade>
            <button @click="handleBtnClick">toggle</button>
        </div>
        <script>
            Vue.component('fade', {
                props: ['show'],
                template: `<transition @before-enter='handleBeforeEnter' @enter='handleEnter' @after-enter='handleAfterEnter'><slot v-if='show'></slot></transition>`,
                methods: {
                    handleBeforeEnter: function(el) { el.style.color = 'red' },
                    handleEnter: function(el, done) {
                        setTimeout(() => { el.style.color = 'green' }, 2000)
                        setTimeout(() => { done() }, 4000)
                    },
                    handleAfterEnter: function(el) { el.style.color = '#000000' }
                }
            })
            var vm = new Vue({ 
                el: '#root',
                data: { show: false },
                methods: {
                    handleBtnClick: function() {
                        this.show = !this.show
                    }
                }
            })  
        </script>
    </body>
    </html>
    

    第6章 Vue 项目预热

    6.1 环境配置

    1.配置vue开发环境

    参考:www.jianshu.com/p/134149147…

    2.在gitee上创建项目方便管理

    2.1 在gitee上创建项目

    2.2 安装git

    2.3 git clone 线上代码并在线下创建vue项目,并上传至线上

    6.2 项目代码介绍

    6.3 单文件组件与Vue中的路由

    <router-view/>:显示的是当前路由地址所对应的内容

    6.4 单页应用VS多页应用

    1.多页应用(页面跳转--->返回HTML)

    特点:首屏时间快,SEO效果好,页面切换慢

    2.单页应用(页面跳转--->JS渲染)

    特点:页面切换快,首屏时间稍慢,SEO效果差

    6.4 项目代码初始化

    1.修改index.html的mate标签

    <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    

    2.重置CSS样式

    import '@/assets/styles/reset.css'

    3.解决1像素边框问题

    import '@/assets/styles/border.css'

    4.解决300毫秒点击延迟问题

    npm install fastclick --save
    import FastClick from 'fastclick'
    FastClick.attach(document.body)
    

    开发实战

    知识点1

    1.git 切换新的分支开发并最后合并到主分支

    ①:在gitee上创建新的分支(index-nnn)

    ②:在项目下面的git Bash中执行git pull

    ③:继续执行git checkout 'index-nnn'

    ④:继续执行git status 查看所在分支

    ⑤:开发完成后执行git status 查看代码变更内容

    ⑥:执行git add . 把修改的代码提交到本地缓存中

    ⑦:执行git commit -m 'XXX' 填写备注XXX

    ⑧:执行git push 把修改的代码提交到线上的新建分支上

    ⑨:执行git checkout master 切换所在分支为主分支

    ⑩:执行git merge origin/index-nnn 查看新建分支与主分支内容差别

    ####十一:执行git push 把新建分支的内容提交到主分支上


    起源地下载网 » 从基础到项目Vue2.0实战带你开发去哪网App——学习笔记

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元