美文网首页Vue.js
Vue.js第1课-起步

Vue.js第1课-起步

作者: e20a12f8855d | 来源:发表于2019-05-09 22:36 被阅读47次

    一、Vue.js 实现 HelloWorld

    先来看一个简单地用 Vue.js 实现的 HelloWorld 例子:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>HelloWorld</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    
    <body>
    
        <div id="app">{{msg}}</div>
        <script>
            var app = new Vue({
                el: '#app',
                data: {
                    msg: 'Hello World!'
                }
            });
            console.log(app); // wn {_uid: 0, _isVue: true, $options: {…}, _renderProxy: wn, _self: wn, …}
            console.log(app.$el); // <div id="app">Hello World!</div>
            console.log(app.$data); // {__ob__: we}
            console.log(app.$data.msg); // Hello World!
    
            setTimeout(function () {
                app.$data.msg = 'Bye!'
            }, 2000);
        </script>
    
    </body>
    
    </html>
    

    通过控制台的几条打印数据及页面的渲染,可以看到,通过“实例.$属性”可以查询或改变数据。

    下面的例子我将不再粘贴完整的 HTML 结构了,只放主要的逻辑代码到笔记中。

    二、Vue.js 实现 TodoList

    <div id="app">
        <input type="text" v-model="inputValue">
        <button v-on:click="btnClick">添加</button>
        <ul>
            <li v-for="item in list">{{item}}</li>
        </ul>
    </div>
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                list: [],
                inputValue: ''
            },
            methods: {
                btnClick: function () {
                    console.log(this.inputValue);
                    this.list.push(this.inputValue);
                    this.inputValue = '';
                }
            }
        });
    </script>
    

    上面代码中,给 input 绑定一个 v-model 指令,值和 data 中的 inputValue 关联,然后通过 v-on 给 button 绑定一个 click 事件 “btnClick”,事件写到实例的 methods 中,在该事件中,通过 this 可以获取到当前实例的属性和值,实现向 data 中 list 数组里添加 inputVlaue 的值。最后通过 v-for 指令,将 list 数组中的值循环渲染到页面上。

    三、jQuery 实现 TodoList

    下面通过 jQuery 使用面向对象编写来实现 TodoList:

    <script src='https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js'></script>
    <div>
        <input id="ipt" type="text">
        <button id="btn">添加</button>
        <ul id="ul"></ul>
    </div>
    <script>
        // jQuery TodoList  MVP 设计模式
        // 使用面向对象编写
        // 创建一个构造函数
        function Page() {};
        // 通过 $.extend 方法在 Page 的 prototype 上增加一些方法
        $.extend(Page.prototype, {
            // 初始化方法
            init: function () {
                this.bindEvents();
            },
            // 绑定事件
            bindEvents: function () {
                var btn = $("#btn");
                btn.on('click', $.proxy(this.handleBtnClick, this));
            },
            handleBtnClick: function () {
                var ipt = $("#ipt");
                var iptVal = ipt.val(); // 输入的值
                var ul = $("#ul");
                ul.append("<li>" + iptVal + "</li>");
                ipt.val("");
                console.log(iptVal);
            }
        });
        // 创建一个实例
        var page = new Page();
        page.init();
    </script>
    

    该方法和 Vue.js 实现的效果是一样的。

    四、组建化修改 TodoList

    1、全局组件的使用

    创建一个全局组件 TodoList,如果组件的名称是驼峰命名法,那么在调用该组件时需要将大写改为小写,中间用“-”连接:

    <div id="app">
        <input type="text" v-model="inputValue">
        <button v-on:click="btnClick">添加</button>
        <ul>
            <!-- <li v-for="item in list">{{item}}</li> -->
            <todo-list v-bind:content="item" v-for="item in list"></todo-list>
        </ul>
    </div>
    <script>
        Vue.component('TodoList',{
            props: ['content'],
            template : '<li>{{content}}</li>'
        });
        var app = new Vue({
            el: '#app',
            data: {
                list: [],
                inputValue: ''
            },
            methods: {
                btnClick: function () {
                    console.log(this.inputValue);
                    this.list.push(this.inputValue);
                    this.inputValue = '';
                }
            }
        });
    </script>
    

    补充:v-bind 给 HTML 标签设置属性。

    2、局部组件的使用

    先创建一个局部变量 TodoList,然后注册一个局部组件,把 TodoList 注册到 vue 事例中:

    <div id="app">
        <input type="text" v-model="inputValue">
        <button v-on:click="btnClick">添加</button>
        <ul>
            <!-- <li v-for="item in list">{{item}}</li> -->
            <todo-list v-bind:content="item" v-for="item in list"></todo-list>
        </ul>
    </div>
    <script>
        // 创建一个局部变量 TodoList
        var TodoList = {
            props: ['content'],
            template: '<li>{{content}}</li>'
        };
    
        var app = new Vue({
            el: '#app',
            // 注册一个局部组件,把 TodoList 注册到 vue 事例中
            components: {
                TodoList: TodoList
            },
            data: {
                list: [],
                inputValue: ''
            },
            methods: {
                btnClick: function () {
                    console.log(this.inputValue);
                    this.list.push(this.inputValue);
                    this.inputValue = '';
                }
            }
        });
    </script>
    

    该方式和全局组件实现的效果一样。

    五、组件间传值

    在 TodoList 的基础上,我们想实现这样一个功能,点击当前元素,当前元素就被删除的效果。

    先来思考一下如何给每一个子组件都添加一个点击事件?我们把事件方法写到父组件的 methods 中,此时点击子组件,会发现根本触发不了,是因为子组件的事件方法要写在子组件里,所以我们把事件方法放到子组件中的 methods 试一下:

    <div id="app">
        <input type="text" v-model="inputValue">
        <button v-on:click="btnClick">添加</button>
        <ul>
            <todo-list v-bind:content="item" v-for="item in list" @click="childClickFun">
            </todo-list>
        </ul>
    </div>
    <script>
        var TodoList = {
            props: ['content'],
            template: "<li>{{content}}</li>",
            methods: {
                childClickFun: function () {
                    console.loh("child");
                }
            }
        };
        var app = new Vue({
            el: '#app',
            components: {
                TodoList: TodoList
            },
            data: {
                list: [],
                inputValue: ''
            },
            methods: {
                btnClick: function () {
                    this.list.push(this.inputValue);
                    this.inputValue = '';
                }
            }
        });
    </script>
    

    打开页面,点击子组件,发现有报错:“childClickFun” 没有在实例上定义,而是在呈现期间引用。

    所以子组件的方法应该写在子组件的 methods 中,父组件的方法就应该写到父组件中。我们知道,父组件向子组件通过 props 传值,那子组件如何向父组件传值呢?子组件可以通过 $emit() 向父组件传值,我们来试一下:

    <div id="app">
        <input type="text" v-model="inputValue">
        <button v-on:click="btnClick">添加</button>
        <ul>
            <todo-list v-bind:content="item" v-bind:index="index" v-for="(item,index) in list" @click="clickFun">
            </todo-list>
        </ul>
    </div>
    <script>
        var TodoList = {
            props: ['content', 'index'],
            template: "<li @click='childClickFun'>{{content}}</li>",
            methods: {
                childClickFun: function () {
                    this.$emit("click", this.index);
                }
            }
        };
        var app = new Vue({
            el: '#app',
            components: {
                TodoList: TodoList
            },
            data: {
                list: [],
                inputValue: ''
            },
            methods: {
                btnClick: function () {
                    this.list.push(this.inputValue);
                    this.inputValue = '';
                },
                clickFun: function (index) {
                    console.log(index);
                }
            }
        });
    </script>
    

    上面代码,我在子组件中定义了一个 childClickFun,在父组件中定义了一个 clickFun。我们先给子组件 todo-list 设置一个属性 index,这个 index 是在 v-for 循环中添加的一个循环项,这样设置完成后,还需要在子组件中通过 props 接收一下。接着在子组件的 childClickFun 中通过 emit() 向外触发事件,这个 emit() 中第一个参数传递触发的事件,第二个参数点击的位置,也就是 this.index,然后在子组件的 template 中添加这个点击事件(注意:emit() 中传入的事件名称要和 template 中 @ 后面的名称一致,可以设置其他名字)。最后我们在父组件的 clickFun 中传一个参数 index,这个 index 就是当前点击的元素的位置,我们打开页面看一下:

    现在弄明白了父子组件之间的传值问题,就可以实现最初我们想要实现的那个点击当前元素删除的功能了。

    <div id="app">
        <input type="text" v-model="inputValue">
        <button v-on:click="btnClick">添加</button>
        <ul>
            <todo-list v-bind:content="item" v-bind:index="index" v-for="(item,index) in list"
                @delete="handleItemDelete">
            </todo-list>
        </ul>
    </div>
    <script>
        var TodoList = {
            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',
            components: {
                TodoList: TodoList
            },
            data: {
                list: [],
                inputValue: ''
            },
            methods: {
                btnClick: function () {
                    this.list.push(this.inputValue);
                    this.inputValue = '';
                },
                handleItemDelete: function (index) {
                    console.log(this.list)
                    this.list.splice(index, 1);
                }
            }
        });
    </script>
    

    附上该系列文章代码地址 Vue.js_Learning

    相关文章

      网友评论

        本文标题:Vue.js第1课-起步

        本文链接:https://www.haomeiwen.com/subject/yprnoqtx.html