首页 > 技术文章 > vue基础

fly-book 2019-07-08 15:39 原文

修改数据绑定的语法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
    <div id="div1">
        ${gareen.name}
        ${gareen.hp}
    </div>
    <script>
        var gareen={"name":"盖伦","hp":600};
        new Vue({
            delimiters: ["${","}"], //修改数据绑定的语法,默认为{{}}
            el:'#div1',
            data:{
                message:gareen
            }
        })
    </script>
</body>
</html>

通过ref获取标签

  <div ref="box">我是一个div</div>
    <button @click="boxColor()">点击设置div背景</button>
 methods:{
            boxColor(){
                console.log(this.$refs.box);
                this.$refs.box.style.background='red'
            }
        }

结果:

<div data-v-3f6fee2c="" style="background: red;">我是一个div</div>

$data

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>hello world</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
    <div id="app">
        {{content}}
    </div>
    <script>
        // var dom = document.getElementById('app')
        // dom.innerHTML = 'Hello World'
        var app = new Vue({
            el:'#app',
            data:{
                content:'Hello World'
            }
        });
        setTimeout(function () { //2秒后执行
            app.$data.content = 'bye world'
        },2000)
    </script>
</body>
</html>

监听事件

  • v-on 监听事件,v-on 缩写为 @
  • 事件冒泡
  • 事件修饰符 阻止冒泡 .stop
  • 事件修饰符 优先触发 .capture
  • 事件修饰符 只有自己能触发,子元素无法触发.self
  • 事件修饰符 只能提交一次 .once
  • 事件修饰符 阻止提交 .prevent
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>监听事件</title>
    <script src="js/vue.min.js"></script>
    <style type="text/css">
        *{
            margin: 0 auto;
            text-align: center;
            line-height: 40px;
        }
    </style>
</head>
<body>
    <div id="div1">
        一共点击了{{clickNumber}}次!
        <!-- v-on 缩写@  -->
        <button @click="count">点击</button>
        <hr>
        <span>事件冒泡</span>
        <div style="background: green" @click="doc('father')">
            father
            <div style="background: blue" @click="doc('me')">
                me
                <div style="background: red" @click="doc('son')">
                    son
                </div>
            </div>
        </div>
        <hr>
        <span>事件修饰符 阻止冒泡 .stop</span>
        <div style="background: green" @click.stop="doc('father')">
            father
            <div style="background: blue" @click.stop="doc('me')">
                me
                <div style="background: red" @click.stop="doc('son')">
                    son
                </div>
            </div>
        </div>
        <hr>
        <span>事件修饰符 优先触发 .capture 当冒泡中包含此事件,先触发此事件</span>
        <div style="background: green" @click="doc('father')">
            father
            <div style="background: blue" @click.capture="doc('me')">
                me
                <div style="background: red" @click="doc('son')">
                    son
                </div>
            </div>
        </div>
        <hr>
        <span>事件修饰符 只有自己可以触发 .self</span>
        <div style="background: green" @click="doc('father')">
            father
            <div style="background: blue" @click.self="doc('me')">
                me
                <div style="background: red" @click="doc('son')">
                    son
                </div>
            </div>
        </div>
        <hr>
        <span>事件修饰符 只能触发一次 .once</span>
        <div style="background: green" @click="doc('father')">
            father
            <div style="background: blue" @click.once="doc('me')">
                me
                <div style="background: red" @click="doc('son')">
                    son
                </div>
            </div>
        </div>
        <hr>
        <span>事件修饰符 阻止提交,不会跳转 .prevent</span><br>
        <a href="http://www.baidu.com" @click="doc('doc')" >正常的链接 http://www.baidu.com</a><br>
        <a href="http://www.baidu.com" @click.prevent="doc('doc')" >prevent doc()之后的链接 http://www.baidu.com</a><br>
        <a href="http://www.baidu.com" @click.prevent >纯prevent之后的链接 http://www.baidu.com</a><br>
        <form @submit="doc('doc')" action="http://www.baidu.com">
            <button type="submit">正常的form</button>
        </form>
        <form @submit.prevent="doc('doc')" action="http://www.baidu.com">
            <button type="submit">prevent doc()之后的form</button>
        </form>
        <form @submit.prevent action="http://www.baidu.com">
            <button type="submit">纯prevent之后的form</button>
        </form>
    </div>
    <script>
        new Vue({
            el:'#div1',
            data:{
                clickNumber:0
            },
            methods:{
              count:function () {
                  this.clickNumber++;
              },
              doc:function (msg) {
                  alert(msg);
              }
            }
        })
    </script>
</body>
</html>

条件语句

  • v-if
  • v-else
  • v-else-if
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>条件语句</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
    <div id="div1">
        <button @click="toggle">切换隐藏显示</button>
        <div v-if="show">这一条是看得见的</div>
        <hr>
        <button @click="choujiang">抽奖</button>
        <div v-if="show2">中奖了</div>
        <div v-else>谢谢回顾</div>
        <hr>
        <button @click="suangua"> 算卦? </button>
        <div v-if="number>98"> 神仙</div>
        <div v-else-if="number>95"> 国家领导人</div>
        <div v-else-if="number>90"> 大富商</div>
        <div v-else-if="number>80"> 大企业主</div>
        <div v-else-if="number>70"> 演艺明星</div>
        <div v-else-if="number>60"> 小企业主</div>
        <div v-else-if="number>50"> 普通公务员</div>
        <div v-else-if="number>40"> 小个体户</div>
        <div v-else-if="number>30"> 血汗工厂工人</div>
        <div v-else-if="number>20"> 偏远山区农民</div>
        <div v-else> 流浪汉</div>
    </div>
    <script>
        new Vue({
            el:'#div1',
            data:{
                show:true,
                show2:false,
                number:0
            },
            methods:{
                toggle:function () {
                    this.show = !this.show;
                },
                choujiang:function () {
                    this.show2=Math.random()<0.5
                },
                suangua:function () {
                    this.number=Math.random()*100
                }
            }
        })
    </script>
</body>
</html>

用 key 管理可复用的元素

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用 key 管理可复用的元素</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
    <div id="div1">
        <template v-if="loginType === 'username'">
            <label>name</label>
            <input placeholder="your name">
        </template>
        <template v-else>
            <label>email</label>
            <input placeholder="your email">
        </template>
        <hr>
        <template v-if="loginType === 'username'">
            <label>name</label>
            <input placeholder="your name" key="name-input">
        </template>
        <template v-else>
            <label>email</label>
            <input placeholder="your email" key="email-input">
        </template>
        <button @click="changeLoginType">切换</button>
    </div>
    <script>
        new Vue({
            el:'#div1',
            data:{
                loginType:'username'
            },
            methods:{
                changeLoginType:function () {
                    if (this.loginType==='username'){
                        this.loginType = 'email'
                    }else {
                        this.loginType = 'username'
                    }
                }
            }
        })
    </script>
</body>
</html>

循环语句

  • v-for 循环语句
  • index用法
  • 纯数字遍历
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>循环语句</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
    <div id="div1">
        <table>
            <tr>
                <th>name</th>
                <th>hp</th>
            </tr>
            <tr v-for="hero in heros">
                <td>{{hero.name}}</td>
                <td>{{hero.hp}}</td>
            </tr>
        </table>
        <hr>
        <table>
            <tr>
                <th>no</th>
                <th>name</th>
                <th>hp</th>
            </tr>
            <tr v-for="hero,index in heros">
                <td>{{index+1}}</td>
                <td>{{hero.name}}</td>
                <td>{{hero.hp}}</td>
            </tr>
        </table>
        <hr>
        <div v-for="i in 10">
            {{i}}
        </div>
    </div>
<script>
    var data = [
        {name:"盖伦",hp:341},
        {name:"提莫",hp:225},
        {name:"安妮",hp:427},
        {name:"死歌",hp:893}
    ];
    new Vue({
        el:'#div1',
        data:{
            heros:data
        }
    })

</script>
</body>
</html>

in也可以用of代替

<div v-for="i of 10">
       {{i}}
</div>

属性绑定

  • v-bind 做属性绑定
  • v-bind:href 简写成 :href
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>属性绑定</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
    <div id="div1">
<!--        v-bind 简写: -->
        <a :href="page" :style="style">百度</a>
    </div>
<script>
    new Vue({
        el:'#div1',
        data:{
            page:'http://www.baidu.com',
            style:'color: red'
        }
    })
</script>
</body>
</html>

双向绑定

  • v-model 双向绑定
  • 多种风格数据的绑定
  • 修饰符
  • 修饰符 .lazy
  • 修饰符 .number
  • 修饰符 .trim
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>双向绑定</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
    <div id="div1">
        <table border="1">
            <tr>
                <td>视图类型</td>
                <td>输入数据</td>
                <td>绑定到Vue上的数值</td>
            </tr>
            <tr>
                <td>单行文本</td>
                <td>
                    <input v-model="input" placeholder="输入数据">
                </td>
                <td><p>{{ input }}</p></td>
            </tr>
            <tr>
                <td>多行文本</td>
                <td>
                    <textarea v-model="textarea" placeholder="输入数据"></textarea>
                </td>
                <td><p>{{ textarea }}</p></td>
            </tr>
            <tr>
                <td>单个复选框</td>
                <td>
                    <input type="checkbox" id="checkbox" v-model="checked">
                </td>
                <td><p>{{ checked }}</p></td>
            </tr>
            <tr>
                <td>单个复选框</td>
                <td>
                    默认值是true或者false,也可以修改为自定义的值<br>
                    <input type="checkbox" id="toggle" true-value="yes" false-value="no" v-model="toggle">
                </td>
                <td><p>{{ toggle }}</p></td>
            </tr>
            <tr>
                <td>多个复选框</td>
                <td>
                    <input type="checkbox" id="teemo" value="teemo" v-model="checkedes">
                    <label for="teemo">teemo</label>
                    <input type="checkbox" id="gareen" value="gareen" v-model="checkedes">
                    <label for="gareen">gareen</label>
                    <input type="checkbox" id="annie" value="annie" v-model="checkedes">
                    <label for="annie">annie</label>
                </td>
                <td><p>{{ checkedes }}</p></td>
            </tr>
            <tr>
                <td>单选按钮</td>
                <td>
                    <input type="radio" id="one" value="One" v-model="radio">
                    <label for="one">One</label>
                    <br>
                    <input type="radio" id="two" value="Two" v-model="radio">
                    <label for="two">Two</label>
                </td>
                <td><p>{{ radio }}</p></td>
            </tr>
            <tr>
                <td>单选选择框</td>
                <td>
                    <select v-model="selected" size="5">
                        <option disabled value="">请选择</option>
                        <option>AD</option>
                        <option>AC</option>
                        <option>ADC</option>
                    </select>
                </td>
                <td><p>{{ selected }}</p></td>
            </tr>
            <tr>
                <td>
                    多选选择框
                </td>
                <td>
                    (通过ctrl或者shift进行多选)<br>
                    <select v-model="selecteds" multiple size="5">
                        <option disabled value="">请选择</option>
                        <option>AD</option>
                        <option>AC</option>
                        <option>ADC</option>
                    </select>
                </td>
                <td><p>{{ selecteds }}</p></td>
            </tr>
        </table>
        <hr>
        <table border="1">
            <tr>
                <td>视图类型</td>
                <td>输入数据</td>
                <td>绑定到Vue上的数值</td>
            </tr>
            <tr>
                <td>在失去焦点的时候,才会进行数据绑定了</td>
                <td>
                    <input v-model.lazy="input" placeholder="输入数据">
                </td>
                <td><p>{{ input }}</p></td>
            </tr>
        </table>
        <hr>
        <table border="1">
            <tr>
                <td>视图类型</td>
                <td>输入数据</td>
                <td>绑定到Vue上的数值</td>
                <td>数值类型</td>
            </tr>
            <tr>
                <td>
                    通过.number方式确保获取到的是数字类型
                </td>
                <td>
                    <input v-model="input1" type="number" placeholder="输入数据">
                </td>
                <td>
                    <p>{{ input1 }}</p>
                </td>
                <td>
                    <p>{{ typeof input1 }}</p>
                </td>
            </tr>
            <tr>
                <td>
                    单行文本2
                </td>
                <td>
                    <input v-model.number="input2"   type="number"  placeholder="输入数据">
                </td>
                <td>
                    <p>{{ input2 }}</p>
                </td>
                <td>
                    <p>{{ typeof input2 }}</p>
                </td>
            </tr>
        </table>
        <hr>
        <table border="1" >
            <tr>
                <td>视图类型</td>
                <td>输入数据</td>
                <td>绑定到Vue上的数值</td>
            </tr>
            <tr>
                <td>
                    trim 去掉前后的空白
                </td>
                <td>
                    <input v-model.trim="input" placeholder="输入数据">
                </td>
                <td>
                    <p>"{{ input }}"</p>
                </td>
            </tr>
            <tr>
                toggles
                <input type="checkbox" v-model="toggles" true-value="yes" false-value="no">
                {{toggles}}
            </tr>
        </table>
    </div>
<script>
    new Vue({
        el:'#div1',
        data:{
            input:'',
            input1:'',
            input2:'',
            textarea:'',
            checked:'',
            checkedes:[],
            radio:'',
            selected:'',
            selecteds:[],
            toggle:'',
            toggles:''
        }
    })
</script>
</body>
</html>

计算属性

  • computed
  • computed 和 methods 的区别:
    computed 是有缓存的,只要没有变化,会直接返回以前计算出来的值,而不会再次计算。 这样如果是复杂计算,就会节约不少时间。而methods每次都会调用
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>计算属性</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
    <div id="div1">
        <h4>model</h4>
        <span>美元汇率:{{exchange}}</span><br>
        ¥ <input v-model="rmb"> <br> $: {{rmb/exchange}}
        <hr>
        <h4>computed</h4>
        <span>美元汇率:{{exchange}}</span><br>
        ¥ <input v-model="rmb"> <br> $: {{dollar}}
        <hr>
        <h4>methods</h4>
        <span>美元汇率:{{exchange}}</span><br>
        ¥ <input v-model="rmb"> <br> $: {{getDollar()}}
    </div>
    <script>
       new Vue({
           el:'#div1',
           data:{
               exchange:6.8702,
               rmb:0
           },
           computed:{
               dollar:function () {
                   return this.rmb/this.exchange
               }
           },
           methods:{
               getDollar:function () {
                   return this.rmb/this.exchange
               }
           }
       })
    </script>
</body>
</html>

监听属性

  • watch
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>监听属性</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
    <div id="div1">
        <h4>watch</h4>
        <span>美元汇率:{{exchange}}</span><br>
        ¥: <input v-model.number="rmb"> <br>
        $: <input v-model.number="dol"> <br>
    </div>
    <script>
        new Vue({
            el:'#div1',
            data:{
                exchange:6.8702,
                rmb:0,
                dol:0
            },
            watch:{
                rmb:function (val) {
                    this.rmb=val;
                    this.dol=this.rmb/this.exchange;
                },
                dol:function (val) {
                    this.dol=val;
                    this.rmb=this.dol*this.exchange;
                }
            }
        })
    </script>
</body>
</html>

过滤器

  • 一个过滤器
  • 多个过滤器
  • 全局过滤器
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>过滤器</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
    <div id="div1">
        多个过滤器: <input v-model="data"/> {{ data|cap|capL }}
        全局过滤器: <input v-model="data"/> {{ data|glCap|glCapL }}
    </div>
    <script>
        //全局过滤器
        Vue.filter('glCap', function (value) {
            if (!value) return '';
            value = value.toString();
            return value.charAt(0).toUpperCase() + value.slice(1)
        });

        Vue.filter('glCapL', function (value) {
            if (!value) return '';
            value = value.toString();
            return value.substring(0,value.length-1)+ value.charAt(value.length-1).toUpperCase()
        });
        new Vue({
            el: '#div1',
            data: {
                data:''
            },
            filters:{
                cap:function(value) {
                    if (!value) return ''; //如果为空,则返回空字符串
                    value = value.toString();
                    return value.charAt(0).toUpperCase() + value.substring(1)
                },
                capL:function(value) {
                    if (!value) return ''; //如果为空,则返回空字符串
                    value = value.toString();
                    return value.substring(0,value.length-1)+ value.charAt(value.length-1).toUpperCase()
                }
            }
        })
    </script>
</body>
</html>

组件

  • 局部组件
  • 全局组件
  • 参数
  • 动态参数
  • 自定义事件
  • 遍历 json 数组
  • 最开始效果步骤里的代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
    <div id="div1">
        <prod></prod>
        <prod></prod>
        <glprod></glprod>
        <glprod></glprod>
        <glprod2 msg="gl休闲包2"></glprod2>
        <hr>
        动态参数: <input v-model="msg">
        <glprod2 :msg="msg"></glprod2>
        <hr>
        <glprod3 :msg="msg" sale="12"></glprod3>
        <hr>
        <prod3 :msg="msg" sale="13" @increment="increment" @increment2="increment2"></prod3>
        <hr>
        <button-counter></button-counter>
        <button-counter></button-counter>
        <button-counter></button-counter>
        <hr>
        <button-counter2></button-counter2>
        <button-counter2></button-counter2>
        <button-counter2></button-counter2>
    </div>
<script>
    Vue.component('button-counter',{
        data:function () { //一个组件的data必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝
            return{
                count:0
            }
        },
        template:'<button @click="count++">{{count}}</button>'
    });
    var buttonCounter2Data = {
        count2:0
    };
    Vue.component('button-counter2',{
        data:function () { //此情况会影响到其它所有实例
            return buttonCounter2Data
        },
        template:'<button @click="count2++">{{count2}}</button>'
    });
    Vue.component('glprod',{  //名字 不能包含大写字母
        template:'<div>gl休闲包</div>'
    });
    Vue.component('glprod2',{
        props:['msg'],
        template:'<div>{{msg}}</div>'
    });
    Vue.component('glprod3',{
        props:['msg','sale'],
        template:'<div @click="addSale">{{msg}}:{{sale}}</div>',
        methods:{
            addSale:function(){
                this.sale++
            }
        }
    });
    new Vue({
        el: '#div1',
        data:{
            msg:''
        },
        components:{
            'prod':{
                template:'<div>休闲包</div>'
            },
            'prod3':{
                props:['msg','sale'],
                template:'<div @click="addSale">{{msg}}:{{sale}}</div>',
                methods:{
                    addSale:function(){
                        this.sale++;
                        this.$emit("increment",this.sale);
                        this.$emit("increment2");
                    }
                }
            }
        },methods:{
            increment:function(val){
                console.log(val);
            },
            increment2:function(){
                console.log('hello');
            }
        }
    })
</script>
</body>
</html>

自定义指令

  • 带参数的自定义指令
  • 钩子函数
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>自定义指令</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
<div id="div1">
    <span v-redpro>hello</span>
    <hr>
    <h4>带参数的指令</h4>
    <span v-redpro2="{color:'green',text:'Pro+'}">hello</span>
    <hr>
    <h4>钩子函数</h4>
    <div v-xart:hello.x.y="{a:'b'}"></div>
</div>
<script>
    Vue.directive('redpro',function (el) {
        el.innerHTML = el.innerHTML+' Pro';
        el.style.color = 'red';
    });
    Vue.directive('redpro2',function (el, binding) {
        el.innerHTML = el.innerHTML + 'Pro' + binding.value.text;
        el.style.color = binding.value.color;
    });
    Vue.directive('xart',{
       bind:function (el, binding, vnode) {
           var s = JSON.stringify;
           el.innerHTML =
               'name: '       + s(binding.name) + '<br>' +   //指令的名字 xart
               'value: '      + s(binding.value) + '<br>' +   //指令的value  {"a":"b"}
               'expression: ' + s(binding.expression) + '<br>' +  // 指令表达式  {a:'b'}
               'argument: '   + s(binding.arg) + '<br>' +  // 指令的参数   hello
               'modifiers: '  + s(binding.modifiers) + '<br>' +  // 一个包含修饰符的对象  .x.y
               'vnode keys: ' + Object.keys(vnode).join(', ')  //虚拟节点
       },
        update:function (newValue, oldValue) {
            // 值更新时的工作
            // 也会以初始值为参数调用一次
        },
        unbind:function () {
            // 清理工作
            // 例如,删除 bind() 添加的事件监听器
        }
    });
    new Vue({
        el:'#div1'
    })
</script>
</body>
</html>

路由 vue-router

  • vue-router.min.js
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue-router</title>
    <script src="js/vue.min.js"></script>
    <script src="js/vue-router.min.js"></script>
    <style>
        #pro div{
            width: 500px;
            height: 500px;
        }
    </style>
</head>
<body>
    <div id="app">
        <div>
            <router-link to="/home">首页</router-link>
            <router-link to="/product">用户</router-link>
            <router-link to="/setting">设置</router-link>
        </div>
        <div id="pro">
            <router-view></router-view>
        </div>
    </div>
    <script>
        //声明组件模版
        var home = {template:'<div style="background: red">首页内容</div>'};
        var user = {template:'<div style="background: green">用户内容</div>'};
        var setting = {template:'<div style="background: yellow">设置内容</div>'};
        // 定义路由
        var routes = [
            {path:'/',redirect:'/home'}, //默认渲染
            {path:'/home',component:home},
            {path:'/product',component:user},
            {path:'/setting',component:setting}
        ];
        var router = new VueRouter({
            routes:routes
        });
        new Vue({
            el:'#app',
            router:router  //router:router 可写为 router
        })
    </script>
</body>
</html>

DOM的is属性

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue 组件 DOM的is属性</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
    <div id="div1">
        <form @submit.prevent="addNewTodo">
            <label for="new-todo">add a todo</label>
            <input
                v-model="newTodoText"
                id="new-todo"
                placeholder="E.g.Feed the cat"
            >
            <button>add</button>
        </form>
        <ul>
            <!--is属性声明所在的元素为todo-item组件-->
            <li
                is="todo-item"
                v-for="(todo,index) in todos"
                :key="todo.id"
                :title="todo.title"
                @remove="todos.splice(index,1)"
            ></li>
        </ul>
    </div>
<script>
    Vue.component('todo-item',{
        template:'<li>{{title}}<button @click="$emit(\'remove\')">remove</button></li>',
        props:['title']
    });
    new Vue({
        el:'#div1',
        data:{
            newTodoText:'',
            todos: [
                {
                    id: 1,
                    title: 'Do the dishes'
                },
                {
                    id: 2,
                    title: 'Take out the trash'
                },
                {
                    id: 3,
                    title: 'Mow the lawn'
                }
            ],
            nextTodoId: 4
        },
        methods:{
            addNewTodo:function () {
                this.todos.push({
                    id:this.nextTodoId++,
                    title:this.newTodoText
                });
                this.newTodoText=''
            }
        }
    })

</script>
</body>
</html>

fetch.js (一种 ajax 框架)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>fetch</title>
    <script src="js/fetch.min.js"></script>
</head>
<body>
    <div id="div1">

    </div>
    <script>
        var url = 'http://static.how2j.cn/study/json.txt';
        fetch(url).then(function (res) {
            res.json().then(function (jsonObj) {
                var jString = JSON.stringify(jsonObj);
                document.getElementById("div1").innerText = "通过fetch获取到的json数据:"+jString;
            }).catch(function (err) {
                console.log(err)
            })
        })
    </script>
</body>
</html>

axios.js (一种 ajax 框架)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>axios</title>
    <script src="js/axios.min.js"></script>
</head>
<body>
    <div id="div1"></div>
    <script>
        var url = 'http://static.how2j.cn/study/json.txt';
        axios.get(url).then(function (res) {
            var jsonObj = res.data;
            var jString = JSON.stringify(jsonObj);
            document.getElementById('div1').innerText = "通过 axios 获取到的json数据:"+jString;
        })
    </script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>axios</title>
    <script src="js/vue.min.js"></script>
    <script src="js/axios.min.js"></script>
    <script src="js/fetch.min.js"></script>
</head>
<body>
    <div id="div1">
        <table border="1">
            <tr v-for="hero in heros">
                <td>{{hero.name}}</td>
                <td>{{hero.hp}}</td>
            </tr>
            <tr v-for="hero in heros2">
                <td>{{hero.name}}</td>
                <td>{{hero.hp}}</td>
            </tr>
        </table>
    </div>
    <script>
        // [
        //     {"name":"gareen","hp":"355"},
        //     {"name":"teemo","hp":"287"},
        //     {"name":"annie","hp":"420"}
        // ]
        var url = 'jsons.txt';
        new Vue({
            el:'#div1',
            data:{
                heros:[],  
                heros2:[]
            },
            mounted:function () { //加载成功
                that = this;
                axios.get(url).then(function (res) {
                    var jsonObj = res.data;
                    that.heros2 = jsonObj;
                    // var jString = JSON.stringify(jsonObj);
                    //document.getElementById('div1').innerText = "通过 axios 获取到的json数据:"+jString;
                });
                fetch(url).then(function (res) {
                    res.json().then(function (jsonObject) {
                        that.heros = jsonObject
                    }).catch(function (err) {
                        console.log(err);
                    })
                })
            }
        })
    </script>
</body>
</html>

crud

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>crud</title>
    <script src="js/vue.min.js"></script>
    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
</head>
<body>
    <div id="div1">
        <table id="heroListTable">
            <thead>
                <tr>
                    <th>name</th>
                    <th>hp</th>
                    <th>操作</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="hero in heros">
                    <td>{{hero.name}}</td>
                    <td>{{hero.hp}}</td>
                    <td>
                        <a href="#nowhere" @click="edit(hero)">编辑</a>
                        <a href="#nowhere" @click="deleteHero(hero.id)">删除</a>
                    </td>
                </tr>
                <tr>
                    <td>
                        name:<input type="text" v-model="heroAdd.name"><br>
                        hp:<input type="number" v-model="heroAdd.hp"><br>
                        <button @click="add">增加</button>
                    </td>
                    <td></td>
                </tr>
            </tbody>
        </table>
        <div id="divUpdate">
            name:
            <input type="text" v-model="heroUpdate.name" />
            <br>
            hp:
            <input type="number" v-model="heroUpdate.hp" />
            <input type="hidden" v-model="heroUpdate.id" />
            <br>
            <button type="button"  @click="update">修改</button>
        </div>
    </div>
    <script>
        $("#divUpdate").hide();
        var data = {
            heros: [
                { id: 1, name: '盖伦', hp: 318},
                { id: 2, name: '提莫', hp: 320},
                { id: 3, name: '安妮', hp: 419},
                { id: 4, name: '死歌', hp: 325},
                { id: 5, name: '米波', hp: 422},
            ],
            heroAdd: { id: 0, name: '', hp: '0'},
            heroUpdate: { id: 0, name: '', hp: '0'},
            updateObj:{ id: 0, name: '', hp: '0'}
        };
        var maxId = 5;
        for (var i = 0;i<data.heros.length;i++){
            if (data.heros[i].id>maxId)
                maxId = this.heros[i].id;
        }
        new Vue({
            el:'#div1',
            data:data,
            methods:{
                add:function (ev) {
                    maxId++;
                    this.heroAdd.id = maxId;
                    if (this.heroAdd.name.length==0){
                        this.heroAdd.name="name#"+this.heroAdd.id;
                    }
                    this.heros.push(this.heroAdd);
                    this.heroAdd={ id: 0, name: '', hp: '0'};
                },
                deleteHero:function (id) {
                    for (var i=0;i<this.heros.length;i++){
                        if (this.heros[i].id===id){
                            this.heros.splice(i,1) //(index,要删除的数量)
                        }
                    }
                },
                edit: function (hero) {
                    $("#heroListTable").hide();
                    $("#divUpdate").show();
                    var copy = JSON.parse(JSON.stringify(hero));
                    this.heroUpdate = hero;
                },
                update:function(){
                    //因为v-model,已经同步修改了,所以只需要进行恢复显示就行了
                    $("#heroListTable").show();
                    $("#divUpdate").hide();
                }
            }
        })
    </script>
</body>
</html>

侦听器

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.min.js"></script>
    <script src="js/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
</head>
<body>
    <div id="div1">
        <input v-model="question">
        <p>{{answer}}</p>
        <img v-if='image' :src="image">
    </div>
    <script>
        new Vue({
            el:'#div1',
            data:{
                question:'',
                answer:"no answer",
                image:''
            },
            watch:{
                question:function (newQuestion,oldQuestion) {
                    this.answer = 'waiting...';
                    this.debouncedGetAnswer()
                }
            },
            created:function () {
                // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
                // 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
                // AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
                // `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
                // 请参考:https://lodash.com/docs#debounce
                this.debouncedGetAnswer=_.debounce(this.getAnswer, 500)
            },
            methods:{
                getAnswer:function () {
                    if (this.question.indexOf('?') === -1) {
                        this.answer = '问题通常包含一个问号. ;-)';
                        return
                    }
                    this.answer = '思考中...';
                    var vm = this;
                    axios.get('https://yesno.wtf/api')
                        .then(function (response) {
                            vm.answer = _.capitalize(response.data.answer);
                            vm.image= response.data.image
                        })
                        .catch(function (error) {
                            vm.answer = 'error'
                        })
                }
            }
        })
    </script>
</body>
</html>

监听子组件事件

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
<div id="blog">
    <div
            :style="{fontSize: postFontSize + 'em'}"
    >
        <blog-post
                v-for="post in posts"
                :key="post.id"
                :post="post"
                @enlargetext="postFontSize += 0.1"
        ></blog-post>

    </div>

</div>
<script>
    Vue.component('blog-post', {
        props: ['post'],
        template: '\
                <div class="blog-post"> \
                    <h3>{{post.title}}</h3> \
                    <button @click="$emit(\'enlargetext\')">text</button> \
                    <div v-html="post.content"></div> \
                </div> \
            '
    });
    new Vue({
        el: '#blog',
        data: {
            posts: [
                {id: 1, title: 'My journey with Vue', content: '...content...'},
                {id: 2, title: 'Blogging with Vue', content: '...content...'},
                {id: 3, title: 'Why Vue is so fun', content: '...content...'}
            ],
            postFontSize: 1
        }
    })
</script>
</body>
</html>

$event

 <br>
    <button data-ids="123" @click="eventFn($event)">事件对象</button>

  eventFn(val){
                alert(val.srcElement.dataset.ids)//123
                console.log(val)
            }

使用事件抛出一个值---$event

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>使用事件抛出一个值</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
<div id="blog">
    <div
            :style="{fontSize: postFontSize + 'em'}"
    >
        <blog-post
                v-for="post in posts"
                :key="post.id"
                :post="post"
                @enlargetext="postFontSize += $event"
        ></blog-post> <!--当在父级组件监听这个事件的时候,我们可以通过 $event 访问到被抛出的这个值-->
        <hr>
        <blog-post
                v-for="post in posts"
                :key="post.id"
                :post="post"
                @enlargetext="onEnlargeText"
        ></blog-post>
    </div>
</div>
<script>
    Vue.component('blog-post', {
        props: ['post'],
        template: '\
                <div class="blog-post"> \
                    <h3>{{post.title}}</h3> \
                    <button @click="$emit(\'enlargetext\',0.1)">text</button> \
                    <div v-html="post.content"></div> \
                </div> \
            '
    });
    new Vue({
        el: '#blog',
        data: {
            posts: [
                {id: 1, title: 'My journey with Vue', content: '...content...'}
            ],
            postFontSize: 1
        },
        methods:{
            onEnlargeText:function (amount) {
                this.postFontSize+=amount
            }
        }
    })
</script>
</body>
</html>

在组件上使用v-model

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>在组件上使用v-model</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
<div id="blog">
    <input v-model="searchText">
    <hr>
    <!-- 等价于:-->
    <input
        :value="searchText"
        @input="searchText = $event.target.value"
    >
    <hr>
    <custom-input
        :value="searchText"
        @input="searchText = $event"
    ></custom-input>
    <hr>
    <custom-input v-model="searchText"></custom-input>
</div>
<script>
    Vue.component('custom-input', {
        props: ['value'],//将其 value 特性绑定到一个名叫 value 的 prop 上在其 input 事件被触发时,将新的值通过自定义的 input 事件抛出

        template: '\
              <input :value="value" \
                     @input="$emit(\'input\',$event.target.value)" \
              > \
            '
    });
    new Vue({
        el: '#blog',
        data:{
            searchText:''
        }
    })
</script>
</body>
</html>

通过插槽分发内容---

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>通过插槽分发内容</title>
    <script src="js/vue.min.js"></script>
</head>
<body>
    <div id="div1">
        <alert-box>
            Something bad happened.
        </alert-box>
    </div>

    <script>
        Vue.component('alert-box',{
            template: '\
                <div> \
                  <strong>Error!</strong> \
                  <slot></slot> \
                </div> \
              '
        });
        new Vue({
            el:'#div1',

        })
    </script>
</body>
</html>

动态组件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动态组件</title>
    <script src="js/vue.min.js"></script>
    <style>
        .tab-button {
            padding: 6px 10px;
            border-top-left-radius: 3px;
            border-top-right-radius: 3px;
            border: 1px solid #ccc;
            cursor: pointer;
            background: #f0f0f0;
            margin-bottom: -1px;
            margin-right: -1px;
        }
        .tab-button:hover {
            background: yellow;
        }
        .tab-button.active {
            background: red;
        }
        .tab {
            border: 1px solid green;
            padding: 10px;
        }
    </style>
</head>
<body>
    <div id="dynamic-component-demo" class="demo">
        <button
                v-for="tab in tabs"
                :key="tab"
                :class="['tab-button', { active: currentTab === tab }]"
                @click="currentTab = tab"
        >{{ tab }}</button>

        <component
                v-bind:is="currentTabComponent"
                class="tab"
        ></component>
    </div>

    <script>
        Vue.component('tab-home', {
            template: '<div>Home component</div>'
        });
        Vue.component('tab-posts', {
            template: '<div>Posts component</div>'
        });
        Vue.component('tab-archive', {
            template: '<div>Archive component</div>'
        });

        new Vue({
            el: '#dynamic-component-demo',
            data: {
                currentTab: 'Home',
                tabs: ['Home', 'Posts', 'Archive']
            },
            computed: {
                currentTabComponent: function () {
                    return 'tab-' + this.currentTab.toLowerCase()
                }
            }
        })
    </script>
</body>
</html>

keep-alive的使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件注册</title>
    <script src="js/vue.min.js"></script>
    <style>
        .dynamic-component-demo-tab-button {
            padding: 6px 10px;
            border-top-left-radius: 3px;
            border-top-right-radius: 3px;
            border: 1px solid #ccc;
            cursor: pointer;
            background: #f0f0f0;
            margin-bottom: -1px;
            margin-right: -1px;
        }

        .dynamic-component-demo-tab-button:hover {
            background: yellow;
        }

        .dynamic-component-demo-tab-button.dynamic-component-demo-active {
            background: red;
        }

        .dynamic-component-demo-tab {
            border: 1px solid #ccc;
            padding: 10px;
        }

        .dynamic-component-demo-posts-tab {
            display: flex;
        }

        .dynamic-component-demo-posts-sidebar {
            max-width: 40vw;
            margin: 0 !important;
            padding: 0 10px 0 0 !important;
            list-style-type: none;
            border-right: 1px solid #ccc;
        }

        .dynamic-component-demo-posts-sidebar li {
            white-space: nowrap;
            text-overflow: ellipsis;
            overflow: hidden;
            cursor: pointer;
        }

        .dynamic-component-demo-posts-sidebar li:hover {
            background: #eee;
        }

        .dynamic-component-demo-posts-sidebar li.dynamic-component-demo-active {
            background: lightblue;
        }

        .dynamic-component-demo-post-container {
            padding-left: 10px;
        }

        .dynamic-component-demo-post > :first-child {
            margin-top: 0 !important;
            padding-top: 0 !important;
        }
    </style>
</head>
<body>
<div id="dynamic-component-demo" class="demo">
    <button class="dynamic-component-demo-tab-button"
            :class="{ 'dynamic-component-demo-active': currentTab == 'Posts' }"
            @click="currentTab = 'Posts'"
    >Posts
    </button>
    <button class="dynamic-component-demo-tab-button"
            :class="{ 'dynamic-component-demo-active': currentTab == 'Archive' }"
            @click="currentTab = 'Archive'"
    >Archive
    </button>
    <component v-bind:is="currentTabComponent" class="dynamic-component-demo-tab"></component>
    <br>
    <button class="dynamic-component-demo-tab-button"
            :class="{ 'dynamic-component-demo-active': currentTab == 'Posts' }"
            @click="currentTab = 'Posts'"
    >Posts
    </button>
    <button class="dynamic-component-demo-tab-button"
            :class="{ 'dynamic-component-demo-active': currentTab == 'Archive' }"
            @click="currentTab = 'Archive'"
    >Archive
    </button>
    <!-- 失活的组件将会被缓存!-->
    <keep-alive>
         <component v-bind:is="currentTabComponent" class="dynamic-component-demo-tab"></component>
    </keep-alive>
</div>
<script>
    Vue.component('tab-posts', {
        data: function () {
            return {
                posts: [
                    {
                        id: 1,
                        title: 'Cat Ipsum',
                        content: '<p>Dont wait for the storm to pass, dance in the rain kick up litter decide to want nothing to do with my owner today demand to be let outside at once, and expect owner to wait for me as i think about it cat cat moo moo lick ears lick paws so make meme, make cute face but lick the other cats. Kitty poochy chase imaginary bugs, but stand in front of the computer screen. Sweet beast cat dog hate mouse eat string barf pillow no baths hate everything stare at guinea pigs. My left donut is missing, as is my right loved it, hated it, loved it, hated it scoot butt on the rug cat not kitten around</p>'
                    },
                    {
                        id: 2,
                        title: 'Hipster Ipsum',
                        content: '<p>Bushwick blue bottle scenester helvetica ugh, meh four loko. Put a bird on it lumbersexual franzen shabby chic, street art knausgaard trust fund shaman scenester live-edge mixtape taxidermy viral yuccie succulents. Keytar poke bicycle rights, crucifix street art neutra air plant PBR&B hoodie plaid venmo. Tilde swag art party fanny pack vinyl letterpress venmo jean shorts offal mumblecore. Vice blog gentrify mlkshk tattooed occupy snackwave, hoodie craft beer next level migas 8-bit chartreuse. Trust fund food truck drinking vinegar gochujang.</p>'
                    },
                    {
                        id: 3,
                        title: 'Cupcake Ipsum',
                        content: '<p>Icing dessert soufflé lollipop chocolate bar sweet tart cake chupa chups. Soufflé marzipan jelly beans croissant toffee marzipan cupcake icing fruitcake. Muffin cake pudding soufflé wafer jelly bear claw sesame snaps marshmallow. Marzipan soufflé croissant lemon drops gingerbread sugar plum lemon drops apple pie gummies. Sweet roll donut oat cake toffee cake. Liquorice candy macaroon toffee cookie marzipan.</p>'
                    }
                ],
                selectedPost: null
            }
        },
        template: '\
                    <div class="dynamic-component-demo-posts-tab">\
                      <ul class="dynamic-component-demo-posts-sidebar">\
                        <li\
                          v-for="post in posts"\
                          :key="post.id"\
                          :class="{ \'dynamic-component-demo-active\': post === selectedPost }"\
                          @click="selectedPost = post"\
                        >\
                          {{ post.title }}\
                        </li>\
                      </ul>\
                      <div class="dynamic-component-demo-post-container">\
                        <div \
                          v-if="selectedPost"\
                          class="dynamic-component-demo-post"\
                        >\
                          <h3>{{ selectedPost.title }}</h3>\
                          <div v-html="selectedPost.content"></div>\
                        </div>\
                        <strong v-else>\
                          Click on a blog title to the left to view it.\
                        </strong>\
                      </div>\
                    </div>\
                  '
    });
    Vue.component('tab-archive', {
        template: '<div>Archive component</div>'
    });
    new Vue({
        el: '#dynamic-component-demo',
        data: {
            currentTab: 'Posts',
            tabs: ['Posts', 'Archive']
        },
        computed: {
            currentTabComponent: function () {
                return 'tab-' + this.currentTab.toLowerCase()
            }
        }
    })
</script>

</body>
</html>

推荐阅读