Fork me on GitHub

vue.js

介绍

官网

生态圈

 

 

挂载点/模板/实例

vue只会对它所对应的挂载点(el)内的内容产生作用。

挂载点里的内容称为模版(template),模版可以通过template写在vue中,和写在挂载点下面的作用是一样的。

vue实例(new Vue({}))绑定到挂载点后会自动对模版和数据内容进行处理,生成要最终展示的内容。

        <div id="root"></div>
        
        <script>
            /*vue实例*/
            new Vue({
                el:"#root",   //挂载点(dom)
                template: '<h1>hello {{message}}!</h1>',   //模板
                data:{
                    message:"world"
                }
            })
        </script>

$访问vue实例属性

vue实例变量.$属性 可以访问vue实例的属性。

<div id="app">
    {{a}}
</div>

<script type="text/javascript">
var data = { a : 1 };
var vm = new Vue({
    el   : "#app",
    data : data
});

vm.$watch('a', function(newVal, oldVal){
    console.log(newVal, oldVal);
})

vm.$data.a = "test...."

</script>

生命周期

<div id="app">
    {{msg}}
</div>
<script type="text/javascript">
var vm = new Vue({
    el : "#app",
    data : {
        msg : "hi vue",
    },
    //在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
    beforeCreate:function(){
        console.log('beforeCreate');
    },
    /* 在实例创建完成后被立即调用。
    在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。
    然而,挂载阶段还没开始,$el 属性目前不可见。 */
    created    :function(){
        console.log('created');
    },
    //在挂载开始之前被调用:相关的渲染函数首次被调用
    beforeMount : function(){
        console.log('beforeMount');

    },
    //el 被新创建的 vm.$el 替换, 挂在成功    
    mounted : function(){
        console.log('mounted');
    
    },
    //数据更新时调用
    beforeUpdate : function(){
        console.log('beforeUpdate');
            
    },
    //组件 DOM 已经更新, 组件更新完毕 
    updated : function(){
        console.log('updated');
            
    }
});
setTimeout(function(){
    vm.msg = "change ......";
}, 3000);
</script>

模板语法-数据展示

{{}}插值表达式

{{ }} 用于输出对象属性和函数返回值,表达式内可以做运算和函数操作。

<div id="app">
    {{msg}}
    <p>Using mustaches: {{ rawHtml }}</p>
    <p v-html="rawHtml"></p>
    <div v-bind:class="color">test...</div>
    <p>{{ number + 1 }}</p>
    <p>{{ 1 == 1 ? 'YES' : 'NO' }}</p>
    <p>{{ message.split('').reverse().join('') }}</p>
</div>
<script type="text/javascript">
var vm = new Vue({
    el : "#app",
    data : {
        msg : "hi vue",
        rawHtml : '<span style="color:red">this is should be red</span>',
        color:'blue',
        number : 10,
        ok : 1,
        message : "vue"
    }
});
vm.msg = "hi....";
</script>

 

v-text/v-html指令显示数据

        <div id="root">
            <div v-text="message"></div> <!--v-text以文本形式显示data中指定数据-->
            <div v-html="content"></div> <!--v-html以html形式解析data中指定数据-->
        </div>
        
        <script>
            /*vue实例*/
            new Vue({
                el:"#root",   //挂载点(dom)
                data:{
                    message:"world",
                    content:"<h1>hello world<h1>"
                }
            })
        </script>

模板语法-事件

v-on:click事件和方法(@)

v-on:click(@click)调用vue的methods中声明的方法,v-on:可以简写成@符号

<div id="root">
    <div v-on:click="this.handleClick">{{content}}</div>  <!--v-on:可以写成 @click="this.handleClick"-->
</div>

<script>
    /*vue实例*/
    new Vue({
        el:"#root",   //挂载点(dom)
        data:{
            content:"hello",
        },
        methods:{
                handleClick: function(){
                    this.content = 'world';
                }
        }
    })
</script>

@click.stop.stop阻止点击事件传播,只触发click方法

<div id="app">
    <p v-if="seen">现在你看到我了</p>
    <a v-bind:href="url">...</a>
    <div @click="click1">
        <div @click.stop="click2"><!-- .stop阻止点击事件传播,只触发click方法, -->
            click me
        </div>
    </div>
</div>
<script type="text/javascript">
var vm = new Vue({
    el : "#app",
    data : {
        seen : false,
        url : "https://cn.vuejs.org/v2/guide/syntax.html#%E6%8C%87%E4%BB%A4"
    },
    methods:{
        click1 : function () {
            console.log('click1......');
        },
        click2 : function () {
            console.log('click2......');
        }
    }
});
</script>

事件绑定

<div id="app">
    <div id="example-1">
        <button v-on:click="counter += 1"> 数值 :  {{ counter }} </button><br />
        <button v-on:dblclick="greet('abc', $event)">Greet</button>
    </div>
</div>
<script type="text/javascript">
var vm = new Vue({
    el : "#app",
    data : {
        counter: 0,
        name : "vue"
    },
    methods:{
        greet : function (str, e) {
            alert(str);
            console.log(e);
        }
    }
});
</script>

 

修饰符

修饰符是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault(),这样只会执行绑定的方法,不会执行事件默认的操作。

<form v-on:submit.prevent="onSubmit"></form>

其他事件修饰符

Vue.js 为 v-on 提供了事件修饰符来处理 DOM 事件细节,如:event.preventDefault() 或 event.stopPropagation()。

Vue.js通过由点(.)表示的指令后缀来调用修饰符。

  • .stop
  • .prevent
  • .capture
  • .self
  • .once
<!-- 阻止事件传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件时不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联  -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符,阻止submit事件默认操作 -->
<form v-on:submit.prevent></form>
<!-- 添加事件侦听器时使用事件捕获模式,带此关键字会优先执行,然后执行子组件在执行父组件 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 -->
<div v-on:click.self="doThat">...</div>

<!-- click 事件只能点击一次,2.1.4版本新增 -->
<a v-on:click.once="doThis"></a>

按键修饰符

Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:

<!-- 只有在 keyCode 是 13 时调用 vm.submit() -->
<input v-on:keyup.13="submit">

记住所有的 keyCode 比较困难,所以 Vue 为最常用的按键提供了别名:

<!-- 同上 -->
<input v-on:keyup.enter="submit">
<!-- 缩写语法 -->
<input @keyup.enter="submit">

属性绑定和双向数据绑定

v-bind:属性绑定(:)

v-bind:属性绑定可以简写为:,属性双引号中的值是js表达式可以用js操作符操作。

class和style通过v-bind:修改

<div id="app">
    <div 
    class="test" 
    v-bind:class="[ isActive ? 'active' : '', isGreen ? 'green' : '']" 
    style="width:200px; height:200px; text-align:center; line-height:200px;">
        hi vue
    </div>
    
    <div 
    :style="{color:color, fontSize:size, background: isRed ? '#FF0000' : ''}">
        hi vue
    </div>
</div>
<script type="text/javascript">
var vm = new Vue({
    el : "#app",
    data : {
        isActive : true,
        isGreen : true,
        color : "#FFFFFF",
        size : '50px',
        isRed : true
    }
});
</script>
<style>
.test{font-size:30px;}
.green{color:#00FF00;}
.active{background:#FF0000;}
</style>

v-model双向绑定

双向绑定是指vue实例中的data和挂载点中的dom属性绑定,可以实现属性的值改变vue实例中的数据,不仅仅是vue实例的data数据影响dom。

<div id="root">
    <div v-bind:title="title">{{content}}</div>   <!--v-bind:缩写成:,意思是title属性值绑定为vue实例data中的title的值-->
    <input v-model="content" />
</div>

<script>
    /*vue实例*/
    new Vue({
        el:"#root",   //挂载点(dom)
        data:{
            content:"hello",
            title:"this is hello world"
        }
    })
</script>

表单数据绑定

通过data属性和v-model绑定表单数据。

<div id="app">
    <div id="example-1">
        <input v-model="message" placeholder="edit me">
        <p>Message is: {{ message }}</p>
        <textarea v-model="message2" placeholder="add multiple lines"></textarea>
        <p style="white-space: pre-line;">{{ message2 }}</p>
        <br />
        
        <div style="margin-top:20px;">
            <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
            <label for="jack">Jack</label>
            <input type="checkbox" id="john" value="John" v-model="checkedNames">
            <label for="john">John</label>
            <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
            <label for="mike">Mike</label>
            <br>
            <span>Checked names: {{ checkedNames }}</span>
        </div>
        
        <div style="margin-top:20px;">
            <input type="radio" id="one" value="One" v-model="picked">
            <label for="one">One</label>
            <br>
            <input type="radio" id="two" value="Two" v-model="picked">
            <label for="two">Two</label>
            <br>
            <span>Picked: {{ picked }}</span>
        </div>
        <button type="button" @click="submit">提交</button>
    </div>
    
</div>
<script type="text/javascript">
var vm = new Vue({
    el : "#app",
    data : {
        message : "test",
        message2 :"hi",
        checkedNames : ['Jack', 'John'],
        picked : "Two"
    },
    methods: {
        submit : function () {
            console.log(this.message);
            
        }
    }
});
</script>

 

computed计算属性watch监听属性

<div id="root">
    姓:<input v-model="firstName" />
    名:<input v-model="lastName" />
    <div>{{fullName}}</div>
    <div>{{count}}</div>
</div>

<script>
    /*vue实例*/
    new Vue({
        el:"#root",   //挂载点(dom)
        data:{
            firstName:"",
            lastName:"",
            count:0
        },
        computed:{  //计算属性,通过已有的data数据计算出新的属性,依赖变更时会重新计算
            fullName:function(){
                return this.firstName +' '+this.lastName;
          }
        },
        watch:{  //监听器,监听数据的变化,当数据发生变化时执行
          fullName:function(){  //当fullName属性值变化时
                this.count++;
          }
        }
    })
</script>

过滤器

过滤器函数接受表达式的值作为第一个参数。

<div id="app">
  {{ message | capitalize }}
</div>
    
<script>
new Vue({
  el: '#app',
  data: {
    message: 'abcd'
  },
  filters: {
    capitalize: function (value) {
      if (!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
  }
})
</script>

v-if、v-show标签 

v-if值为ture,将元素插入dom,false删除dom。

v-show值为ture是显示dom,false时不显示,通过css样式,style="display: none;"。(性能高一点,不用每次新建dom)

<div id="root">
    <div v-if="show">hello</div>
    <div v-show="show">world</div>
    <button @click="handleClick">toggle</button>
</div>

<script>
    /*vue实例*/
    new Vue({
        el:"#root",   //挂载点(dom)
        data:{
            show:true
        },
        methods:{
            handleClick:function(){
                this.show = !this.show;
            }
        }
    })
</script>

多个v-if

<div id="app">
    <div v-if="type === 'A'">
      A
    </div>
    <div v-else-if="type === 'B'">
      B
    </div>
    <div v-else-if="type === 'C'">
      C
    </div>
    <div v-else>
      Not A/B/C
    </div>
</div>
    
<script>
new Vue({
  el: '#app',
  data: {
    type: 'C'
  }
})
</script>

v-for标签

v-for 指令可以用来遍历数组(val,index)、对象(val,key,index)、整数。

遍历每一个数据

<div id="root">
    <ul>
        <!-- 遍历list中的每一项放入item中,index为下标,:key的作用是用来加速渲染一定要唯一 -->
        <li v-for="(item,index) of list" :key="index">{{item}}</li> 
    </ul>
</div>

<script>
    /*vue实例*/
    new Vue({
        el:"#root",   //挂载点(dom)
        data:{
            list:['a','b','c']
        }
    })
</script>

v-for遍历数组/对象

<div id="app">
    <ul>
        <li v-for="item,index in items" :key="index">
        {{index}}{{ item.message }}
        </li>
    </ul>
    <ul>
        <li v-for="value, key in object">
            {{key}} : {{ value }}
        </li>
    </ul>
</div>
<script type="text/javascript">
var vm = new Vue({
    el : "#app",
    data : {
        items : [
            { message: 'Foo' },
            { message: 'Bar' }
        ],
        object: {
            title: 'How to do lists in Vue',
            author: 'Jane Doe',
            publishedAt: '2016-04-10'
        }
    }
});
</script>

动态修改数组

<div id="root">
    <div>
        <input v-model="inputVal"/>
        <button @click="handleSubmit">提交</button>  <!-- 通过提交事件的handleSubmit方法操作vue.$list数据,下面会自动显示list数据.(vue是数据驱动型,操作的是数据不是dom) -->
    </div>
    <ul>
        <!-- 仅仅是显示list中的值,当list中的值变化时这里也会跟着变 -->
        <li v-for="(item,index) of list" :key="index">{{item}}</li>
    </ul>
</div>
<script>
    /*vue实例*/
    new Vue({
        el:"#root",   //挂载点(dom)
        data: {
            inputVal: '',   //input双向绑定的值
            list:[]   //list数组
        },
        methods: {
            handleSubmit: function(){    //按钮绑定的方法
                this.list.push(this.inputVal);
                this.inputVal = ''
            }
        }
    })
</script>

自定义指令

<div id="app">
    <p>页面载入,input 元素自动获取焦点:</p>
    <input v-focus>
</div>

<script>
// 注册一个全局自定义指令 v-focus
Vue.directive('focus', {
  // 当绑定元素插入到 DOM 中。
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})
// 创建根实例
new Vue({
  el: '#app'
})
</script>

组件

组件其实也是一个实例,注册一个全局组件语法格式如下:

Vue.component(tagName, options)

组件基础

<div id="app">
    <!-- title属性是为了向子组件传参,@clicknow事件是为了被子组件触发执行clicknow函数接收子组件传来的参数 -->
    <button-counter title="title1 : " @clicknow="clicknow">
        <h2>hi...h2</h2>
    </button-counter>
    <!-- 没有绑定子组件的@clicknow事件,并不会接收子组件传来的数据 -->
    <button-counter title="title2 : "></button-counter>
</div>
<script type="text/javascript">
Vue.component('button-counter', {
    props: ['title'],   /* props是父组件向子组件传值 */
    data: function () {
        return {
          count: 0
        }
    },
    /* <slot>标签为原有数据 */
    template: '<div><h1>hi...</h1><button v-on:click="clickfun">{{title}} You clicked me {{ count }} times.</button><slot></slot></div>',
    methods:{
        clickfun : function () {  //1.模板内容点击绑定的事件
            this.count ++;
            this.$emit('clicknow', this.count);   //2.$emit将触发当前实例上的事件clicknow
        }
    }
})
var vm = new Vue({
    el : "#app",
    data : {
        
    },
    methods:{
        clicknow : function (data) {  //3.clicknow为被子组件触发的事件,并接收子组件传来的参数
            console.log(data);
        }
    }
});
</script>

组件注册

<div id="app">
    <button-counter></button-counter>
    <test></test>
</div>
<script type="text/javascript">
/* 全局注册 */
Vue.component('button-counter', {
    props: ['title'],
    data: function () {
        return {}
    },
    template: '<div><h1>hi...</h1></div>',
    methods:{
        
    }
})
/* 局部注册 */
var vm = new Vue({
    el : "#app",
    data : {
        
    },
    methods:{
        clicknow : function (e) {
            console.log(e);
        }
    },
    components:{/* 局部注册,只能在挂载点使用组件 */
        test : {
            template:"<h2>h2...</h2>"
        }
    }
});
</script>

 

简单组件

        <ol id="app">
          <!-- 使用组件,创建一个todo-item组件的实例 -->
          <todo-item></todo-item>
        </ol>
        <!-- 这里的script一定要写在最后写在前面不行 -->
        <script>
            // 定义名为 todo-item 的新组件,tagName为todo-item(html中直接使用)
            Vue.component('todo-item', { 
              template: '<li>这是个待办项</li>'
            });
            
            //声明式渲染不能少
            new Vue({
              el: '#app'
            })
        </script>

父组件传值子组件props

v-for遍历多次调用全局组件,动态添加数据。

父组件(vue实例)向子组件传值,通过属性绑定的方式传值,子组件通过props接收属性的值。

父组件 -> 将值绑定(v-bind:)在子组件的挂载点上 -> 子组件通过props获取挂载点上的属性值。

props是单向数据流: 避免了子组件意外修改父组件的状态;如需修改可以在data()中新定义一个局部数据属性;如果需要对props传过来的数值进行进一步的转换可以再computed中定义一个计算属性。

prop校验: type、required、default、validator

<div id="root">
    <div>
        <input v-model="inputVal"/>
        <button @click="handleSubmit">提交</button>  <!-- 通过提交事件的handleSubmit方法操作vue.$list数据,下面会自动显示list数据.(vue是数据驱动型,操作的是数据不是dom) -->
    </div>
    <ul>
        <!-- vue实例中的值每次改变dom也会跟着变动,这里把item作为参数传给组件了-->
        <todo-item
            v-for="(item,index) of list" :key="index" :param="item">
        <todo-item/>
    </ul>
</div>
<script>
    /*全局组件,相当于一个li标签,中间的内容由父级实例传入,props接收父级实例传过来的数据*/
    Vue.component('todo-item',{
        props: ['param'],   
        template:'<li @click="handleClick">{{param}}</li>',
        methods: {
            handleClick: function(){
                alert('cl');    
            }
        }
    });
    
    /*vue实例*/
    new Vue({
        el:"#root",   //挂载点(dom)
        data: {
            inputVal: '',   //input双向绑定的值
            list:[]   //list数组
        },
        methods: {
            handleSubmit: function(){    //按钮绑定的方法
                this.list.push(this.inputVal);
                this.inputVal = ''
            }
        }
    })
</script>

子组件向父组件传值

要通过发布订阅的方式实现。

子组件通过this.$emit(事件,参数)方法触发事件 -> 父组件在子组件上通过v-on:方式监听事件 -> 父组件找到事件绑定的方法(带参数)并执行.

<div id="root">
    <div>
        <input v-model="inputVal"/>
        <button @click="handleSubmit">提交</button>  <!-- 通过提交事件的handleSubmit方法操作vue.$list数据,下面会自动显示list数据.(vue是数据驱动型,操作的是数据不是dom) -->
    </div>
    <ul>
        <!-- vue实例中的值每次改变dom也会跟着变动,这里把item作为参数传给组件了;监听组件的delete事件,如果被触发执行vue实例的handleDelete-->
        <todo-item
            v-for="(item,index) of list" :key="index" :param="item" :index="index" @delete="handleDelete">
        <todo-item/>
    </ul>
</div>
<script>
    /*全局组件,相当于一个li标签,中间的内容由参数(遍历的item)传入并展示*/
    Vue.component('todo-item',{
        props: ['param','index'],   
        template:'<li @click="handleClick">{{param}},下标{{index}}</li>',
        methods: {
            handleClick: function(vlue){
                this.$emit('delete',this.index);  //方法触发delete事件并传值
            }
        }
    });
    
    /*vue实例*/
    new Vue({
        el:"#root",   //挂载点(dom)
        data: {
            inputVal: '',   //input双向绑定的值
            list:[]   //list数组
        },
        methods: {
            handleSubmit: function(){    //按钮绑定的方法
                this.list.push(this.inputVal);
                this.inputVal = ''
            },
          handleDelete: function(index){
                  this.list.splice(index,1);
          }
        }
    })
</script>

1、父组件可以使用 props 把数据传给子组件。
2、子组件可以使用 $emit 触发父组件的自定义事件。

vm.$emit( event, arg ) //触发当前实例上的事件
vm.$on( event, fn );//监听event事件后运行fn;

vue单文件组件

安装单文件环境

安装 `npm`
`npm` 全称为 `Node Package Manager`,是一个基于`Node.js`的包管理器,也是整个`Node.js`社区最流行、支持的第三方模块最多的包管理器。
npm -v

由于网络原因 安装 `cnpm`
npm install -g cnpm --registry=https://registry.npm.taobao.org

安装 `vue-cli`
cnpm install -g @vue/cli

安装 `webpack`
`webpack` 是 `JavaScript` 打包器(module bundler)
cnpm install -g webpack

 

文件以.vue结尾的是的 single-file components (单文件组件),用webstorm新建一个vue文件格式如下。

练习: 点击列表高亮显示,点击添加按钮把元素移动到另外一个列表

新建Info.vue文件

<template>
  <ul>
    <!--@click点击选中样式-->
    <!--:class选中样式,仅在current等于某个索引时且current不为空时生效-->
    <li v-for="(item,index) in lists"
        @click="choose(index)"
        :class="{active: index == current && current !== ''}"
        :key="index">
      {{item}}
    </li>
  </ul>
  <button type="button" @click="add()">添加</button>
  <!--输出target-->
  <ul>
    <li v-for="(item,index) in target" :key="index">{{item}}</li>
  </ul>
</template>

<script>
  export default {
    name: 'Info',
    data () {
      return {
        current: '',
        lists: [1,2,3,4,5,6,7,8,9],
        target: []
      }
    },
    methods:{
      //选中时改变current的值
      choose (index){
        this.current = index;
        console.info(index);
      },
      //点击添加按钮时把当前选中值加到目标数组
      add(){
        if(this.current === ''){  //为空时不添加
          return;
        }
        this.target.push(this.lists[this.current]);
        /*添加后清空*/
        this.current = '';
      }
    }
  }
</script>

<style scoped>
    /*选中的li加背景色*/
    li.active{
      background:green;
    }
</style>

 

官方示例

<html>
    <head>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script>
            window.onload=function (){
                //声明式渲染
                app = new Vue({
                  el: '#app',
                  data: {
                    message: 'Hello Vue!'
                  }
                })
                
                //v-bind:title给标签动态绑定提示
                app2 = new Vue({
                  el: '#app-2',
                  data: {
                    message: '页面加载于 ' + new Date().toLocaleString()
                  }
                })
                
                //v-if条件
                app3 = new Vue({
                  el: '#app-3',
                  data: {
                    seen: true
                  }
                })
                
                //v-for循环
                app4 = new Vue({
                  el: '#app-4',
                  data: {
                    todos: [
                      { text: '学习 JavaScript' },
                      { text: '学习 Vue' },
                      { text: '整个牛项目' }
                    ]
                  }
                })
                
                //v-on:click点击事件
                app5 = new Vue({
                  el: '#app-5',
                  data: {
                    message: 'Hello Vue.js!'
                  },
                  methods: {
                    reverseMessage: function () {
                      this.message = this.message.split('').reverse().join('')
                    }
                  }
                })
                
                //v-model双向绑定
                app6 = new Vue({
                  el: '#app-6',
                  data: {
                    message: 'Hello Vue!'
                  }
                })
                
            }
        </script>
    </head>
    
    <body>
        <!--显示文本-->
        <div id="app">{{ message }}</div>
        
        <!--显示悬浮框-->
        <div id="app-2">
          <span v-bind:title="message">
            鼠标悬停几秒钟查看此处动态绑定的提示信息!
          </span>
        </div>
        
        <!--条件-->
        <div id="app-3">
          <p v-if="seen">现在你看到我了</p>
        </div>
        
        <!--循环-->
        <div id="app-4">
          <ol>
            <li v-for="todo in todos">
              {{ todo.text }}
            </li>
          </ol>
        </div>
        
        <!--点击事件-->
        <div id="app-5">
          <p>{{ message }}</p>
          <button v-on:click="reverseMessage">逆转消息</button>
        </div>
        
        <!--表单输入和文本状态之间的双向绑定-->
        <div id="app-6">
          <p>{{ message }}</p>
          <input v-model="message">
        </div>
        
    </body>
</html>

Vue-Router

https://router.vuejs.org/zh/

vue-cli的项目创建后添加Vue Router,但是会覆盖你的App.vue

vue add router

注册路由

用 Vue.js + Vue Router 创建单页应用

javascript

// 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)

// 1. 定义(路由)组件。
// 可以.vue文件import进来
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }

// 2. 定义路由
// 每个路由应该映射一个组件。 其中"component" 可以是
// 通过 Vue.extend() 创建的组件构造器,
// 或者,只是一个组件配置对象。
// 我们晚点再讨论嵌套路由。
const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]

// 3. 创建 router 实例,然后传 `routes` 配置
// 你还可以传别的配置参数, 不过先这么简单着吧。
const router = new VueRouter({
  routes // (缩写) 相当于 routes: routes
})

// 4. 创建和挂载根实例。
// 记得要通过 router 配置参数注入路由,
// 从而让整个应用都有路由功能
const app = new Vue({
  router
}).$mount('#app')

// 现在,应用已经启动了!

HTML

<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>

<div id="app">
  <h1>Hello App!</h1>
  <p>
    <!-- 使用 router-link 组件来导航. -->
    <!-- 通过传入 `to` 属性指定链接. -->
    <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>
</div>

或者在全局router.js里面注册好路由,然后在vue文件中使用<router-link to="/info">Info</router-link>的方式调用路由,<router-view/>展示组件内容。

模块中使用Vue Router

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

编程式导航

// 字符串
router.push('home')

// 对象
router.push({ path: 'home' })

// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})

// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

Vue Router路由元信息

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      children: [
        {
          path: 'bar',
          component: Bar,
          // a meta field
          meta: { requiresAuth: true }
        }
      ]
    }
  ]
})

 

Vuex

state

就是Vue应用中需要使用的所有公共数据,在Vue通常放在应用的顶层组件上,通过父子组件通信的方式进行传递和修改。

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

//实例化一个vuex
const store = new Vuex.Store({
    state: {
        count: 0
    }
});

//通过this.$store.state.属性 访问vuex
new Vue({ 
    el: '#app',
    store,
    computed: {
        count () {
            return this.$store.state.count
        }
    }
});

getters

getters可以认为,是store的计算属性。

mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性

const store = createStore({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: (state) => {
      return state.todos.filter(todo => todo.done)
    },
    //通过属性访问
    doneTodosCount (state, getters) {
      return getters.doneTodos.length
    },
    //通过方法访问
    getTodoById: (state) => (id) => {
      return state.todos.find(todo => todo.id === id)
    }
  }
})
//调用
this.$store.getters.doneTodosCount

mutation

const store = createStore({
  state: {
    count: 1
  },
  mutations: {
    //Payload传对象参数
    increment (state, payload) {
      state.count += payload.amount
    }
  }
})

//调用
store.commit('increment', {
  amount: 10
})

action

Action与mutation基本相同,区别在以下两个方面:

  • Action是通过提交mutation来改变state,而不是直接改变state
  • Action可以执行异步操作,而mutation只能为同步操作

vue-cli

npm安装及配置

https://www.cnblogs.com/aeolian/p/12457284.html

安装

官网

#安装vue-cli
npm install --global vue-cli
#或者
npm install -g @vue/cli

构建项目

命令构建

#cli方式(vue-cli3才有的命令),vuecli集成webpack
vue create hello-world
#基于webpack
vue init webpack hello-world

UI构建

vue ui    #vue-cli3才有

启动后浏览器自动打开。

运行

cd hello-world
npm run serve

npm run XXX,XXX是package.json中的scripts的内容。

 

webstorm可以右击package.json -》 show Package Scripts调出来命令窗口。

 

结构

 

index.html为首页,main.js为index中挂载点的实例,main.js中导入组件并使用组件。

main.js

import Vue from 'vue'
import TodoList from './TodoList'

/* index.html中挂载点的实例 */
new Vue({
  el: '#app', /* index.html中的根结点 */
  components: { App: TodoList }, /* 以APP标签使用引入的TodoList组件 */
  template: '<App/>'
})

TodoList.vue

<!--父组件-->
<template>
  <div id="app">
    <div>
      <input v-model="inputVal"/>
      <button @click="handleSubmit">提交</button>  <!-- 通过提交事件的handleSubmit方法操作vue.$list数据,下面会自动显示list数据.(vue是数据驱动型,操作的是数据不是dom) -->
      <ul>
        <!--使用子组件,通过:绑定属性传值给子组件,通过@监听事件接收子组件传值-->
        <todo-item v-for="(item,index) of list"
                   :content="item"
                   :index="index"
                   :key="index"
                   @delete="handleDelete">
        </todo-item>
      </ul>
    </div>
  </div>
</template>

<script>
/* 引入子组件TodoItem组件 */
import TodoItem from './components/TodoItem'

export default {
  components: { 'todo-item': TodoItem }, /* 引用导入的组件,声明通过todo-item标签的方式使用TodoItem */
  name: 'App',
  data: function () {
    return {
      inputVal: '',
      list: []
    }
  },
  methods: {
    handleSubmit () {
      this.list.push(this.inputVal)
      this.inputVal = ''
    },
    handleDelete (index) { /* 监听子组件触发的事件方法,并接收参数 */
      this.list.splice(index, 1) /* 从index位置删除1个数据 */
    }
  }
}
</script>

<!--不加scope会变成全局-->
<style scoped>
#app {
  color: #2c3e50;
}
</style>

TodoItem.vue

<!--子组件-->
<template>
  <!--监听li标签的单击事件,执行handleDelete方法-->
  <li @click="handleDelete">{{content}}</li>
</template>

<script>
export default {
  props: ['content', 'index'], /* 通过属性接收父组件的数据 */
  methods: {
    handleDelete () {
      this.$emit('delete', this.index) /* 触发父组件的delete监听事件,并传递参数index */
      // alert(this.index)
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

浏览器调试工具vue-devtools

下载地址: https://github.com/vuejs/devtools/releases,下载发布版本

manifest.json并把json文件里的"persistent":false改成true

打开chrome浏览器,打开更多工具>扩展程序,添加解压文件夹;

重启浏览器

posted @ 2018-06-26 07:46  秋夜雨巷  阅读(220)  评论(0编辑  收藏  举报