Vue基础学习

1.vue基础

1.1 Vue下载安装

1.1.1js文件安装

下载:学习--教程--左侧的安装---下载开发版,点击进入,复制---到项目中创建vue.js文件,将内容复制即可,用script引入 
<script type="text/javascript" src="Vue/vue.js" ></script>
3.或者可以直接引入
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>

1.1.2 win下安装node.js

  • 下载安装:
  • 测试:
    • 打开cmd,输入node进入,然后就可以测试了
    • 退出:两次Ctrl+c
  • 查看版本号: npm -v
若是没有版本号,需要修改环境变量:
在用户变量的path中加上:C:\Users\jsy\AppData\Roaming\npm


1.1.3安装命令行工具MobaXterm 

打开即可使用;
配置:打开Settings 

  • 安装cnpm
    • 方法1:
npm install -g cnpm --registry=https://registry.npm.taobao.org
//但是这样版本可能会不一致
    • 方法2:
或者你直接通过添加 npm 参数 alias 一个新命令:
alias cnpm="npm --registry=https://registry.npm.taobao.org \
--cache=$HOME/.npm/.cache/cnpm \
--disturl=https://npm.taobao.org/dist \
--userconfig=$HOME/.cnpmrc"



1.1.3vue-cli下载和安装

使用node.js(MobaXterm )安装vue-cli

  • 安装vue-cli:     cnpm install vue-cli -g
  • 初始化项目:        vue init webpack my-project
  • 安装项目依赖         cnpm install
  • 在locallot启动测试服务器 :       npm run dev
  • 生成上线日录(部署) :        npm run build

  • 具体使用
vue版本2.9.6,输入  vue --help    有一下内容

  • 查看版本
  • vue -V

  • 查看官方提供的模板
  • vue list    //速度回有点慢

  • 使用webpack搭建项目
vue init webpack my-project    //搭建项目
    接下来是配置:
        项目名
        描述
        作者
        安装vue-router   y
        代码校验ESLint   n
        测试工具tests  看个人需要 n
        e2s tests 测试工具    n
  生成项目;
启动项目:
    1.安装依赖:
        进入项目文件夹my-project
        cnpm install    //安装依赖  node_modules
        npm run dev    //启动项目
生成部署用的文件:
    npm run build     //运行之后,会有一个dist目录

1.1.4 sublime text 添加vue高亮

1.准备语法高亮插件vue-syntax-highlight。
下载zip并解压;
2.进入sublime,首选项--浏览插件目录,在打开的文件夹中创建“Vue”文件夹。
3.在Vue文件夹中,将vue-syntax-highlight-master压缩包解压后的所有文件考入
4.按下快捷键“ctrl+shift+p”,在打开的packages输入框中输入vue,选择“Set Syntax:Vue Component”进行加载。
加载后重启sublime,重新打开.vue文件,即能看到语法高亮

1.1.5 安装vuex

在项目中安装
cnpm install vuex --save
//若是重启了工具,要重新把上面的npm转cnpm的代码运行一下,
安装完之后,重新运行项目
    npm run dev

1.1.6 安装vue-resource

cnpm install vue-resource

1.1.7 json-server 虚拟的后端(只能get)

cnpm install json-server --save
打开项目,进入build 打开dev-server.js文件,
在第四行express下:
    var jsonServer=require('json-server')
在第16行var app = express()之下写
    var jsonServer=new jsonServer()
在最底下module.exports之前设置:


var jsonServer=require('json-server')
var apiserver=jsonServer.create()
var apirouter=jsonServer.router('db.json')//此目录是项目的目录,放置此文件到项目文件夹中
var middlewares=jsonServer.defaults()
apiserver.use(middlewares)
apiserver.use('/api',apirouter)
apiserver.listen(3000,function () {//监听的接口,
  console.log('JSON Server is running')
})

配置后端接口路径

打开config中的index.js文件,其中配置的就是后端

1.1.8虚拟后端接口

var apiServer = express()
var bodyParser = require('body-parser')
apiServer.use(bodyParser.urlencoded({ extended: true }))
apiServer.use(bodyParser.json())
var apiRouter = express.Router()
var fs = require('fs')
apiRouter.route('/:apiName')//动态设置路由接口
.all(function (req, res) {
  fs.readFile('./db.json', 'utf8', function (err, data) {
    if (err) throw err
    var data = JSON.parse(data)
    if (data[req.params.apiName]) {//判断是否有这个接口
      res.json(data[req.params.apiName])//设置返回值
    }
    else {
      res.send('no such api name')
    }

  })
})


apiServer.use('/api', apiRouter);
apiServer.listen(port + 1, function (err) {
  if (err) {
    console.log(err)
    return
  }
  console.log('Listening at http://localhost:' + (port + 1) + '\n')
})







1.2 vue概述

生命周期


1.2.1 挂载点、模板、实例的关系

挂载点:就是页面的标签,vue只会处理挂载点下面的内容
<div id="root"></div>
模板:挂载点内部的内容,都是模板内容,可以写在挂载点(标签中),也可以写在template中.
显示的时候,显示的是template中定义的内容,页面本身的内容会去掉
    <body>
        <div id="root">{{msg}}</div><!--显示msg中内容-->
    </body>
    <script>
    /*创建一个vue实例,让这个实例接管页面上的id为root的标签*/
        new Vue({
            el:"#root", /*绑定:id为root的*/
            template:'<h1>你好,{{msg}}</h1>',/*在root内部设置内容*/
            data:{
                msg:"hello world"
            }
        })
    </script>
实例在vue实例中的data中,可以设置任意的名字,只要用{{ }}就可以显示

1.2.1 vue实例显示方法(html,text)

1.用{{ }}显示
{{msg}}
2.在标签上使用v-text显示:(若是HTML格式的内容,会直接将标签显示)
<h1 v-text='msg'></h1>
3.在标签上使用v-html显示:(会将标签转义,显示处理后的页面样式)
<h1 v-html='msg'></h1>

1.2.2 vue点击事件

点击标题,将标题的内容改为123
  • 点击标题时,调用root的vue中的handleClick方法,将vue的data中的msg改为123;

绑定点击事件的方法: 

1.使用 v-on:click='handleClick' 
2.使用 @click='handleClick'
注意:写方法的时候,方法要写在vue的methods中
<body>
    <div id="root">
        <h1 v-on:click='handleClick'>{{msg}}</h1>
        <!--设置点击方法-->
    </div>
    <!--显示msg中内容-->
</body>
<script>
    new Vue({
        el : "#root"/*绑定:id为root的*/
        data : {
            msg "hello world"
        },
        methods : {
            handleClick : function() {
                his.msg "123"
            }
        }
    })
</script>

1.2.3 Vue中的属性绑定

(1)属性绑定

使用:
(1)v-bind:
(2):
<!--使用v-bind对title中的内容绑定,绑定为data中title中的内容-->
<div v-bind:title="title">hello world</div><!--v-bind可以省略-->
-------------
new Vue({
    el:"#root", /*绑定:id为root的*/
    data:{
        title:"this is hello world",
    }
})


<div v-bind:title="'123 '+title">hello world</div>
则页面上提示内容为:123 this is hello world 
简化:
<div :title="title">hello world</div>

(2):绑定class

这种class绑定不会冲突,页面上回自动整合未一个class的两个样式
<div :class="link" class="aaa"></div>
在data中:
    link:'class1'

  • 绑定多个class(class对象)
        link:{
            'class1':true,
            'class2':false
        }//true的class会在页面显示
  • 数组形式class
link:['class1','class2']
或者:
<div :class="[classA,classB]" class="aaa"></div>
----------------------
classA:'cla1',
classB:'cla2',
  • 混合使用:
<div :class="[classA,{'classB':iferror}]" class="aaa"></div>
******************
classA:'cla1',
classB:'cla2',
iferror:true

1.2.4 双向数据绑定 v-model

v-model双向绑定,当INPUT中的内容变的时候,下面div中的内容也会变
<input v-model="content"/>    
<!--v-model双向绑定,当INPUT中的内容变的时候,下面div中的内容也会变-->        
<div>{{content}}</div>    



(1)绑定表达式

  • 支持三元表达式
{{content?content:"你好"}}
当content有值的时候显示值,没有的时候显示"你好"

(2)lazy修改器:延迟修改

只有当修改完之后,点击了enter或者失去焦点的时候,才会修改,input必须定义type为text
<input type="text" v-model.lazy="myVlaue" /><!--延迟-->
{{myVlaue}}

(3)number数字转为number格式

<input type="text" v-model.number="myVlaue" /><!--延迟-->
{{typeof myVlaue}}     输出的是类型

注意:是数字格式的会转化为number,但是字符串的不会影响

(4)trim去掉前后空格

<input type="text" v-model.trim="myVlaue" /><!--延迟-->
{{myVlaue}}

1.2.5 Vue中的计算属性(多个属性)

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


整合之后:
姓:<input v-model="firstName"/>
名:<input v-model="lastName"/>
<div>{{fullName}}</div>    
--------------
new Vue({
    el:"#root", /*绑定:id为root的*/
    data:{
        firstName:"",
        lastName:""
    },
    computed:{/*计算属性,表示一个属性通过另一个属性计算而来*/
        fullName:function(){
            return this.firstName+' '+this.lastName;
        }
    }
})



(1)案例:获取输入中的数据,将数字清掉,只显示其他部分

  • 方法1:使用计算属性
<input type="text" v-model.trim="myVlaue" /><!--延迟-->
{{myVlaueNoNumber}}
    computed:{
        myVlaueNoNumber:function (){
            return this.myVlaue.replace(/\d/g,'')
        }
  • 方法2:添加事件:
定义方法:
getValue:function(){
    return this.myVlaue.replace(/\d/g,'')
}
调用:
{{getValue()}}
显示:

  • 区别:
    • 计算属性只会根据其中调用的值改变(只有这个值改变的时候,他才会变);
    • 方法只要调用就会进行数据处理

1.2.6 Vue中的侦听器,监听: watch

watch监听的属性的方法可以有两个值,一个新值,一个旧值
	watch:{
		myVlaue:function(val,oldVal){}
	}
()
当姓或名做了改变的时候,count+1,使用watch监听器

姓:<input v-model="firstName"/>    
<!--v-model双向绑定,当INPUT中的内容变的时候,下面div中的内容也会变-->        
名:<input v-model="lastName"/>
<div>{{fullName}}</div>            
<div>{{count}}</div>
-------------
new Vue({
    el:"#root", /*绑定:id为root的*/
    data:{
        firstName:"",
        lastName:"",
        count:0
    },
    computed:{/*计算属性*/
        fullName:function(){
            return this.firstName+' '+this.lastName;
        }
    },
    watch:{
        /*监听firstName*/
        firstName:function () {
            this.count++;
        },
        lastName:function () {
            this.count++;
        }
    }
})

此处监听的是firstName和lastName,也可以监听fullName,只要fullName改变,就count++

1.2.7 v-if, v-show与v-for指令

(1)案例:点击按钮,标签显示、隐藏

  • v-if
<div id="root">
    <!--只有show是true的时候,标签才会存在-->
    <div v-if='show'>hello world</div>
    <button @click='handleClick'>toggle</button>
</div>
--------------
new Vue({
    el:"#root",
    data:{
        show:true,
    },
    methods:{
        handleClick:function(){
            this.show=!this.show;//将show的值取反
        }
    }
})

  • v-show
上述代码,直接将v-if换为v-show即可,使用时,结果相同 
  • v-else
<v-if="isshow">456</a>
<v-else>123</a>

(2)v-for 案例:将list中的内容,循环展示出来

遍历的时候,item of list ,用in或of都可以
    <ul>
        <!--遍历list中的内容,定义Wieitem,将他显示-->
        <li v-for="item of list":key="item">{{item}}</li>
    </ul>
-------------
data:{
        show:true,
        list:[1,2,3]
},


注意:,使用了key,要求item中的内容不能相同,(list中的内容不能相同)
若是list中有相同的内容,使用index:
<!--item放的是内容,index放的是下标,用index作为key值,就不会重复了-->
<li v-for="(item,index) of list":key="index">{{item}}</li>

  • 对象列表

      
        list:[
        {
            name:'apple',
            price:323
        },{
            name:'aaa',
            price:1123
        }
        ]
<div v-for="(item,index) in list":key="index">{{item.name}}---{{item.price}}--{{index}}</div>
也可以直接在标签中引用:
<div v-for="(item,index) in list":key="index"
   v-text="item.name+'---'+item.price+'---'+index"></div>

  • 遍历对象
<div v-for="(value,key) in objlist" >{{value}}---{{key}}</div>
	objlist:{
			name:'app',
			price:123,
			color:'red'
		}

(3)v-if, v-show区别

v-if:当为false的时候,会之间将代码移除; 
v-show:当为false的时候,会display为隐藏none;
当需要频繁的显示隐藏的时候,v-show更好,它不需要重新创建,性能更高; 
只需要一次的话,v-if更好;

(4)v-for 操作class

<div v-for="(item,index) in list" :class="{odd:index%2}">{{index}}</div>
当index%2有余数的时候odd显示

(5)案例:当点击提交的时候,input的内容显示在list中,在页面显示(同步更新)

<!--当点击提交的时候,input的内容显示在list中,在页面显示-->        
<div id="root">
    <div>
        <input v-model="inputValue"/>
        <button @click="handleSubmit">提交</button>
    </div>
    <ul>
        <li v-for="(item,index) of list":key="index">{{item}}</li>
    </ul>
</div>
    </body>
    <script>
new Vue({
    el:"#root",
    data:{
          inputValue:'',
        list:[]
    },
    methods:{
        handleSubmit:function(){
            //点击提交的时候,将input的值放到list中
            this.list.push(this.inputValue)
            this.inputValue=''//将inputValue设置W为空,这样输入框就会自动为空了
        }
    }
})
    </script>

(5)数据列表修改数据

为列表中某一项修改数据
  • 直接修改----不会自动更新
  • 使用vue的setfnagfa
<button @click="changelist">changelist</button>
-----------------
methods:{
		changelist:function (){
			Vue.set(this.list,1,123)
		}
	}

1.2.8 组件

组件:指页面的某些部分

(1)全局组件

//将页面显示的ul部分作为一个组件,
//Vue.component创建的是全局组件
Vue.component('todo-item',{
    template:'<li>item</li>'  //模板(其中的HTML代码)
})
-----------调用:
<ul>
    <!--使用组件-->
    <todo-item></todo-item>
</ul>

(2)局部组件

  • 局部组件声明
var TodoIrem={
    template:'<li>item</li>' 
}
由于是局部的,需要在要使用的实例哪里声明
new Vue({
    el:"#root",
    components:{        //做组件声明
        'todo-item':TodoItem
//若是左右相同,可以只写一边的  TodoItem  
    },
  • 组件使用:
    • 方法1:
<todo-item></todo-item> <!--一样-->
    • 方法2:使用is引入
<p is='todo-irem'></p>
方法2优势,可以动态的使用组件,使用:is 的时候,可以引用变量
动态引入:
<p :is='getTodo'></p>
data中:   getTodo:'todo-irem'

(3)子组件多级调用

var my2={
    template:'<div>123456</div>',
}
//创建一个子组件
var my1={
    template:'<div><my2></my2></div>',//多级调用,要在这里
    components:{
        //my1
        'my2':my2
    }
}
new Vue({//根组件
    el: '#app',
    data: {
        content: 'Hello'
    },
    components:{
        'my':my1
    }
})

(4)子组件data赋值

子组件要避免引用赋值,
//创建一个子组件
var my1={
    template:'<div>{{f}}<my2></my2></div>',
    components:{
        //my1
        'my2':my2
    },
    data :function(){//也可以使用    data (){
        return{
            f:2
        }
    }
}


(3)组件与实例的关系

每一个组件,就是一个实例,每一个组件上都可以定制方法等内容

(4)父组件向子组件传递数据组件通信

  • 父组件向子组件传递数据,属性:
    • 父组件调用的时候,设置:key=value,(key是父组件的数据的key)
    • 子组件接收参数:使用props接收参数,就可以正常调用了
    • 子组件方法中可以用this.xxx调用数据
    • 注意,key值设置的时候大小写不敏感,要使用-,props中也是,当时子组件调用的时候,使用的是驼峰的样式.

  • 使用全局组件完成input提交显示,
 <!--使用组件-->
<todo-item v-for="(item,index) of list" 
    :key="index" 
    :content="item"
>  <!--设置key值,1.传参-->
</todo-item>
设置全局组件,接收参数,显示内容
Vue.component('todo-item',{
    props:['content'],//2.接收参数content
    template:'<li>{{content}}</li>'  //3.设置显示模板(其中的HTML代码)也可以在页面中调用
})

(5)props接收参数

接收参数可以是list格式,也可以是对象格式:
 props:['aaa','bbb']
对象格式:
    props:{
        'aaa':[Number,String,Object]//指定参数运行的格式
    }

(6)子组件向父组件传递事件

1.子组件的模板中添加时间(vue事件);
2.在事件中,通过  this.$emit('delete-a',this.index)  创建自定义的事件,并传递参数,自定义的事件不支持驼峰形式.
3.在父组件中调用子组件的时候,在标签中用@...调用这个事件,@...='父组件中的方法名',
4.在父组件中编写方法,
5.调用子组件的事件的时候,调用的就会是父组件的方法了.
  • 案例:下方的删除功能

(7)插槽:子组件显示父组件定义的标签

在父组件中调用子组件,再向子组件的标签中添加内容的时候,不会显示,只会显示子组件本身的内容
<todo-irem><!--调用子组件,子组件中有内容<li>i123131132tem</li>-->
	<p>123</p>
</todo-irem>
只会显示:子组件本身定义的内容
想要这部分内容显示,可以在子组件的模板中使用标签
template:'<div><li>i123131132tem</li><slot></slot></div>' 
在子组件中加上这个标签,就会把父组件调用的时候添加的内容显示
注意:子组件必须在一个大标签之下,

  • 插槽设置默认内容
当插槽没有设置的时候,默认显示内容
template:'<div><li>i123131132tem</li><slot>没有内容</slot></div>' ,

  • 插槽设置名字
<todo-irem><!--调用子组件,子组件中有内容<li>i123131132tem</li>-->
<slot='header'>header插的内容 </p>
<!--<p slot='footer'> footer插的内容</p>-->
</todo-irem>
template:'<div><li>i123131132tem</li><slot name="header">header没有内容</slot><slot name="footer">footer没有内容</slot></div>',

(8)动态组件is

在父组件中声明子组件之后,在页面中:
<:is='getTodo'></p>
这样就可以动态设置了,getTodo是data中的属性,通过改变它的值改变绑定的子组件
getTodo:'todo-irem'

(9)组件缓存:<keep-alive>

<keep-alive>
    <:is='getTodo'></p>
</keep-alive>
当组件从a切换到b,的时候,a就会缓存起来,从b切换回a的时候,直接读缓存

1.2.9案例: 删除功能(子组件向父组件传递事件)

  • 已有功能:
点击提交,会将input中的内容保存到list,子组件会遍历list,设置为item,以content传递到props,在template中显示.
  • 需要实现:
要想删除子组件,在每一条上加上click方法,删除的时候,要删除的是父组件list中的内容. 
调用的是子组件的方法,删除父组件的数据,需要两个组件之间进行通信(此时需要子组件中,这一条的下标,来和父组件中对应).

  • 传递顺序:
1.点击子组件(显示的内容中)的方法handleClick(click方法),调用方法, this.$emit创建在父组件中显示的名(@...自定义事件)和参数,在父组件中调用@...(<xxx调用子组件)之后的方法
注意,自定义事件不支持驼峰形式

    <body>
<!--当点击提交的时候,input的内容显示在list中,在页面显示-->        
<div id="root">
    <div>
        <input v-model="inputValue"/>
        <button @click="handleSubmit">提交</button>
    </div>
    <ul>
        <!--在父组件中调用子组件----使用组件-->
        <todo-item v-for="(item,index) of list" 
            :key="index" 
            :content="item"
            :index="index"
            @delete-a="handleDelete"
            >  <!--设置key值,1.传参,下标,-->
            <!--监听子组件的delete事件,当子组件触发了delete事件的时候,调用方法handleDelete(父组件的方法)-->
        </todo-item>
    </ul>
</div>
    </body>
    <script>
//将页面显示的ul部分作为一个组件,
//Vue.component创建的是全局组件
Vue.component('todo-item',{
    props:['content',"index"],//2.接收参数content
    template:'<li @click="handleClick">{{content}}</li>'//3.设置显示模板(其中的HTML代码)
    methods:{
        handleClick:function(){
            //调用$emit,调用自定义的事件,传入接收的下标值
            this.$emit('delete-a',this.index)
        }
    }
})
//局部组件
//var TodoItem={
//    template:'<li>item</li>' 
//}
new Vue({
    el:"#root",
//    components:{//做组件声明
//        'todo-item':TodoItem
//    },
    data:{
          inputValue:'',
        list:[]
    },
    methods:{
        handleSubmit:function(){
            //点击提交的时候,将input的值放到list中
            this.list.push(this.inputValue)
            this.inputValue=''//将inputValue设置W为空,这样输入框就会自动为空了
        },
        handleDelete:function (index) {
            //删除list中对应下标的内容,即可删除页面中的数据
            //从下标位置,删除一项
            this.list.splice(index,1)
        }
    }
})
    </script>
</html>

1.3vue事件和表单

1.3.1全局api

实例对象创建完之后,还可以进行操作
实例对象有一个对象名root
var root=new Vue({
	el: '#app',
	data: {
		content: 'Hello'
	}
})
root.$data 
可以获取data数据
root.$on('emit',function () {})  
可以绑定方法

1.3.1事件绑定

除了click之外,还常用的方法是keydown方法,一般监听的键盘是enter
当按键为回车的时候,进行的操作:
<input @keydown.enter="tokeydown" />
也可以指定其他的按键,比如:
@keydown.13

1.3.2多选框/单选框,数据绑定

将多选框中的数据绑定到数组中

(1)单选框数据绑定

<input v-model="myBox" type="radio" value="111" />
<input v-model="myBox" type="radio" value="222" />
<input v-model="myBox" type="radio" value="333" />
{{myBox}}
--------------
myBox:[]

(2)多选框数据绑定

<input v-model="myBox" type="checkbox" value="111" />
<input v-model="myBox" type="checkbox" value="222" />
<input v-model="myBox" type="checkbox" value="333" />

(3)select下拉框绑定

<select v-model="sel">
	<option value="1">11</option>
	<option value="2">22</option>
	<option value="3">33</option>
</select>
{{sel}}
------------
sel:null

(4)v-for 遍历下拉绑定

<select v-model="sel">
	<option v-for="item in seloption" :value="item.value">{{item.text}}</option>
</select>
{{sel}}
------------
sel:null,
seloption:[
    {text:'app1',value:1},
    {text:'app2',value:2},
    {text:'app3',value:3},
]
一般情况,这种下拉会创建一个组件,直接调用组件:
<vSelect @onSelect='' :list="seloption"></vSelect>

1.4 vue高级功能

1.4.1过渡(动画效果)

要与v-show,v-if 动态组件结合
1.给需要过渡的元素外层加transition ,并用name命名
show:true,
---------------------
<button @click="show=!show">button</button>
<transition name='fade'>
    <v-show="show">456</p>
</transition>

(1)css过渡


  • 淡入淡出 
show:true,
---------------------
<button @click="show=!show">button</button>
<transition name='fade'>
    <v-show="show">456</p>
</transition>
--------------------
在style中定义样式
<style>
.fade-enter-active,.fade-leave-active{
    transition:/*opacity*/ all .5;/*属性,时长,还可以加上ease-out,代表变化的曲线*/
    /*指定当前样式有过渡效果,opacity代表透明度*/
}
.fade-enter,.fade-leave-active{
    opacity:0;
    /*进入和出去的时候透明度是0*/
}
</style>

  • 上下左右滑入滑出
/*激活阶段,动画控制,*/
.my-trans-enter-active,.my-trans-leave-active{
    transition: all .5s ease-out;/*属性,时长,还可以加上,代表变化的曲线*/
    
}
/*控制动画具体怎么变*/
/*进入动画控制*/
.my-trans-enter{
    /*进入从上方滑入*/
    transform: translateY(-500px);
    opacity: 0;
}
.my-trans-leave-active{
    /*出去,向下滑出*/
    transform: translateY(500px);
    opacity:0;
    /*进入和出去的时候透明度是0*/
    /*指定当前样式有过渡效果,opacity代表透明度*/
}

组件设置过渡

<transition name='my-trans'>
	<div :is='getTodo'></div>
</transition>
<button @click="getTodoFun">button</button>
---------------
getTodo:'todo-irem'
------------
getTodoFun:function(){
    if(this.getTodo==='todo-irem'){
        this.getTodo='todo-irem2'
    }else{
        this.getTodo='todo-irem'
    }
}

多元素过渡

多个元素切换,是将新的在下方显示,在将旧的隐藏,有同时出现的机会,默认是in-out
使用out-in,会先将就的去掉,再显示新的
<transition name='my-trans' mode='out-in'>  
    <v-show="show">456</p>
</transition>

注意,多个元素的时候,过渡动画会消失,需要定义key区分每一个元素
<button @click="show=!show">button</button>
<transition name='fade' mode='out-in'>
    <v-if="show" key='1'>456</p>
    <v-else key='2'>11178911</p>
</transition>

(2)JS过渡

  • js控制动画,是通过v-on事件控制的.
  • 使用js过渡的时候,要在transition中绑定  v-bind:css='false' 防止css样式的影响

 <!--进入前,进入过程中,离开-->
 <transition 
    @before-enter='beforeEnter'
    @enter='enter'  
    @leave='leave'   
    :css='false'>
    <class='js-class' v-show="show" >456</p>
</transition>
.js-class{
    position: absolute;
    top: 50px;
    left: 50px;
    color: red;
}

使用js操作动画:
        beforeEnter:function(el){
            $(el).css({
                left:'-500px',
                opacity:0
            })
        },
        enter:function(el,done){
            $(el).animate({
                left:'50px',/*进入的时候,跑到left到50位置*/
                opacity:1
            },{
                duration:1500,/*执行的ms数*/
                complete:done /*完成的之后*/
            });
        },
        leave:function(el,done){
            $(el).animate({
                left:'500px',/*离开的时候,向右移动500px后消失*/
                opacity:0
            },{
                duration:1500,/*离开时间*/
                complete:done
            })
        }
动画会在左右动作,没有定义的top不会有影响


1.4.2 自定义指令

使用的v-if等是内置的指令,

(1)局部自定义指令

在一个组件中定义的,只能在这一个组件中使用
定义自定义指令,使用
    directives:{
        //自定义指令color,binding是传入的值
        color:function(el,binding){
            el.style.color=binding.value
        }
    }
使用自定义指令:
<v-color="'red'">hello123</p>
传入的值使用"' '"包裹着

(2)全局自定义指令

只需要把自定义的指令放到根节点的组件中定义即可

(3)更细致定义

一个自定义对象可以定义几个钩子函数,
没有声明的时候,默认是bind和update
bind:
只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted
被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update
所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
componentUpdated
指令所在组件的 VNode 及其子 VNode 全部更新后调用
unbind
只调用一次,指令与元素解绑时调用。

        //自定义指令color
        color:{
            bind:function(el,binding){
                el.style.color=binding.value
            },
            inserted:function(el){
                
            }
        }

(4)案例:input获取光标

focus:{
    inserted:function(el,binding){
        el.focus()
    }
}
<input type="text" v-focus />

1.4.3插件

在vue项目的package.json文件中,就可以看到项目的依赖
  • 安装插件
    • 使用node.js,进入项目包,输入:  cnpm install vue-router --save
    • 再次打开package.json可以看到这插件
  • 引用插件
    • 在要调用的vue文件中进行引用,若是所有的页面都会用到的,可以在main.js中引用
    • import VueRouter from 'VueRouter '        
    • 也可以 import VueRouter from ' vue-router'   
    • 也可以 var VueRouter =require( ' vue-router' )

  • 注册使用
    • Vue.use(VueRouter )
  • 正式引入
    • 方法1:    
      • 定义:   let router=new VueRouter ()
      • 在组建中引入router,
    • 方法2:  若是已经引入了vueresource,可以直接在组建中定义
      • this.$http.get('')






2.vue-cli

2.1vue-cli概述

Vue-cli-vue 官方提供的脚手架工具
  • 作用:初始化一个Vue项目
  • 优势:
    • 成熟的vue项目架构设计
    • 本地测试服务器
    • 集成打包上线方案
  • 要求:
    • Node.js(>=4.x)
    • Git
    • 一个能使用node的命令行终端



启动项目:
npm run start
一个template中只能有一个根元素, 
定义参数data要用function 

style可以加上scoped使样式局部

2.1.1es6语法


  • 导出:
    • Hello.vue导出
    • 方法1:
    • 方法2:

  • 导入:

  • 声明变量
    • 在当前作用域下:let
    •  本文件都可以取到var
    • 常量:const router=new VueRouter

  • 引入数据
在组建中使用data,要使用return的方式
<script>
export default {
  name'HelloWorld',
  data () {
    return {
      msg'Welcome to Your Vue.js App'
    }
  }
}
</script>

2.1.2 vue-rouer 路由

(1)安装/配置:

进入项目目录:(在搭建项目的时候安装了)
  cnpm install vue-router --save

项目中载入,一般在main.js中载入:
    import VueRouter from 'vue-router'
    Vue.use(VueRouter)
    let router = new VueRouter({})    //其中配置路径和地址
在Vue中引入:
    new Vue({
      el: '#app',
      router,
      template: '<APP/>',
      components: { APP }
    })

(2)基础案例:路径访问(映射表)

路径:http://localhost:8080/apple/    ,访问一个页面
  • 定义一个vue页面Apple:
<template>
    <div class="apple">213124</div>
</template>
<script>
export default {
  name'Apple'
}
</script>
<style scoped>
</style>

  • new VueRouter({})所在页面引入:
import Apple from '@/components/Apple'

  • 在new VueRouter({}) 中引入:
  routes: [
       mode:'history',
    {
        path:'/apple',
        component:Apple
    },
     {
        path:'/apple2',
        component:Apple2
    }
    
  ]

  • APP.vue中引入(会在这里显示)
<router-view></router-view>

(3)页面内跳转

要在   mode:'history',    之下
    <router-link :to="{path:'apple'}">to apple</router-link>
     <router-link :to="{path:'apple2'}">to apple2</router-link>

(4)路由参数

路由参数在映射表中进行
设置参数:
    path:'/apple/:color',
页面:
    http://localhost:8080/apple/red
获取参数:
    在Apple.vue获取:
        <div >{{$route.params}}</div>    { "color": "red" }
		<div >{{$route.params.color}}</div>    red
    在Apple.vue方法中获取:this.$route.params
点击按钮,显示参数:{ "color": "red" }
这种情况下,路径上若是没有参数,将会不能进入这个页面

多个参数:
  path:'/apple/:color/deee/:aa',
其中:color和:aa是用户可以自定义的参数,可以是任何内容;
deee是路径,不能修改
可以的访问路径为:http://localhost:8080/apple/red/deee/asas
只有带:  的参数才会在$route.params中

(5)路由嵌套(子路由)

    {
        path:'/apple',
        component:Apple,
        childdren:[
            {
                path:'/childapple/',
                component:ChildApple
            }
        ]
    },
在这个页面import引入

内容要在Apple.vue中添加
<router-view></router-view>
页面跳转:

(6)router-link,页面内跳转,声明试导航

普通页面跳转
<router-link :to="{path:'apple'}">to apple</router-link>
基于当前路径跳转
    <router-link :to="'apple'">to apple</router-link>
根目录:
    <router-link :to="'/apple'">to apple</router-link>
动态设置:
    <router-link :to="apple">to apple</router-link>
    在data中:
      data(){
      	reurn{
      		apple:'apple'
      	}
      }
传递参数:
    <router-link :to="{path:'apple',param:{color:'red'}}">to apple</router-link>
    可以访问 apple/red(参数)
改变router-link显示样式:
    <router-link :to="'apple'" tag="li">to apple</router-link>

(7)js中定义导航,跳转

router.push('apple') //或 {path:'apple'}
或
this.$router.push('/login');

(8)路由命名

    {
    	path:'/apple',
    	component:Apple,
    	name:'applePage'
    	
    }
访问:
    <router-link :to="{name:'applePage'}">to apple</router-link>

  • 命名路由视图
在router-view 上添加name
<router-view name='viewA  '></router-view>
路由表中可以根据name定义页面
    {
    	path:'/apple',
    	component:{
    		viewA:Apple,
    		viewB:OtherApple,
    	},
    	name:'applePage'
    }

(9)路由重定向

比如默认页面是具体的某一个页面,比如访问根目录,会自动跳转到Apple.vue目录
  {
      path:"/",
      redirect:'/apple'
  },

(10)页面跳转--过渡

    <transition name='fff'>
    	<keep-alive><!--缓存-->
    		<router-view></router-view>
    	</keep-alive>
    </transition>

2.2vuex 状态管理

2.2.1引入

import  Vuex from  'vuex' /*引入*/
Vue.use(Vuex) /*使用*/
let store=new Vuex.Store({ /*调用*/
state:{/*数据中心的数据*/
totalPrice:0
},
mutations: {/*动作*/
increment(state, price) {/*增加*/
state.totalPrice += price
},
decrement(state, price) {/**/
state.totalPrice -= price
}
}
})
在全局中引用:(在main.js中的vue中引用)
new Vue({
el: '#app',
router,
store ,
components: { App },
template: '<App/>'
})
其他文件调用:
在上面引用之后,每个组件都可以使用:
this.$store.state.totalPrice

(1)案例:全局加减

创建Apple和Banana两个vue文件,在APP.vue中引入
方法1:
<template>
<div id="app">
<img src="./assets/1ogo.png">
{{ totalprice }}
<apple></apple>
<banana></banana>
</div>
</template>
<script>
import Apple from'./components/apple'
import Banana from './components/banana'
export default {
components: {Apple, Banana},
computed:{/*计算属性*/
totalPrice(){
return this.$store.state.totalPrice
}
}
}
</script>
每一个vue组件都有一个+1和-1的按钮
<template>
<div>
<h1>{{msg}}</h1>
<button @click="addOne">addOne</button>
<button @click="minusOne">minusOne</button>
</div>
</template>

<script>
export default {
name: "Apple",
data(){
return{
msg:'i am apple',
price:5 /*香蕉是15*/
}
},
methods:{
addOne(){
this.$store.commit('increment',this.price)
},
minusOne(){
this.$store.commit('decrement',this.price)
}
}
}
</script>

方法2:
let store=new Vuex.Store({  /*调用*/
state:{/*数据中心的数据*/
totalPrice:0
},
mutations: {/*动作,只能同步操作*/
increment(state, price) {/*增加*/
state.totalPrice += price
},
decrement(state, price) {/**/
state.totalPrice -= price
}
},
actions:{/*mutations之前的动作,可以先异步操作,再调用mutations中的方法*/
increase(context,price){
context.commit('increment',price)
}
}
})
addOne(){
this.$store.dispatch('increase',this.price)
},



  • 在Store中还可以设置getters获取数据
getters:{/*获取数据*/
getTotal(){
return state.totalPrice
//APP.vue中方法获取totalPrice,可以直接用
// this.$store.getters.getTotal获取
}
},

可以定义多个状态集,最后汇总

2.3 vue-resource:整合ajax

在main.js中
import VueResource from 'vue-resource'
Vue.use(VueResource)
每一个页面都可以使用this.$http  

2.3.1 ajax案例

  • get:
    /*ajax请求 */
    this.$http.get('api/getNewsList')
    .then((res) => {/*成功回调*/
      this.newsList = res.data //赋值
    }, (err) => {/*失败回调*/
      console.log(err)
    })
  • post
this.$http.post(this.GLOBAL.urlHead+'manager/login',{managerUserName:this.ruleForm.username,managerPass:this.ruleForm.password},{emulateJSON:true})
                .then((res) => {/*成功回调*/
                  if (res.data.state==1) {
                    alert(res.data.msg)
 localStorage.setItem('managerName',res.data.data.managerName);//ms_username
 localStorage.setItem('managerId',res.data.data.managerId);//ms_username
                    this.$router.push('/index');
                  }else {
                    alert(res.data.msg)
                  }
                }, (err) => {/*失败回调*/
                  console.log(err)
                  alert("登录失败!")
                });

2.3.2 页面加载

  /*在组建创建完之后加载:页面加载*/
  created: function () {
    /*ajax请求 */
    this.$http.get('api/getNewsList')
    //post参数:.post('api/getNewsList',{userId:123,aa:44})
    .then((res) => {/*成功回调*/
      this.newsList = res.data //赋值
    }, (err) => {/*失败回调*/
      console.log(err)
    })
  },

2.3.3页面初次加载判断

使用一个没有定义的参数进行判断,默认为false,只需要判断完设置为true即可
      if (!this.userFlag) {
        errorText = ''
        this.userFlag = true
      }


2.4 vue的UI组件

2.3.3 轮播图组件


2.3.4显示项目图片

使用js设置的图片
数据:src: require('../assets/slideShow/pic1.jpg')

3.vue具体组件

使用vue搭建项目的时候,一般的目结构为:

3.1 侧边栏

<template>
  <div class="left-nav">
    <ul>
        <li>
            <i class="icon iconfont icon-wodezichan"></i>
            <div>收银</div>
        </li>

        <li>
            <i class="icon iconfont icon-dianpu"></i>
            <div>店铺</div>
        </li>

        <li>
            <i class="icon iconfont icon-hanbao"></i>
            <div>商品</div>
        </li>

         <li>
            <i class="icon iconfont icon-huiyuanqia"></i>
            <div>会员</div>
        </li>

         <li>
            <i class="icon iconfont icon-shijian"></i>
            <div>抢购</div>
        </li>

        <li>
            <i class="icon iconfont icon-tongji"></i>
            <div>统计</div>
        </li>

·
    </ul>
  </div>
</template>

<script>
export default {
  name: 'Main',
  data () {
    return {
      
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
    .left-nav{
       color:#fff;
       font-size:10px;
       height:100%;
       background-color: #1D8ce0;
       float:left;
       width:5%;
    }
    .iconfont{/*设置图标大小*/
       font-size:24px;
    }
    .left-nav ul{
        padding:0px;
        margin: 0px;
    }
    .left-nav li{
        list-style: none;
        text-align: center;
        border-bottom:1px solid #20a0ff;
        padding:10px;
    }
</style>
  • APP.vue中引用:
 <leftNav></leftNav>
import leftNav from '@/components/common/leftNav'
components:{
    leftNav
  }
同时要调整APP的样式(比如#APP的margin-top)

复制,赋值不绑定



vue表单校验

vue.js校验

给定一个表单,包含三个字段,其中两个是必填项
<form
  id="app"
  @submit="checkForm"
  action="https://vuejs.org/"
  method="post"
>
解释:
    id 确认vue的
    submit 处理函数
    action 跳转路径

<form
  id="app"
  @submit="checkForm"
  action="https://vuejs.org/"
  method="post"
>

  <p v-if="errors.length">
    <b>Please correct the following error(s):</b>
    <ul>
      <li v-for="error in errors">{{ error }}</li>
    </ul>
  </p>

  <p>
    <label for="name">Name</label>
    <input
      id="name"
      v-model="name"
      type="text"
      name="name"
    >
  </p>

  <p>
    <label for="age">Age</label>
    <input
      id="age"
      v-model="age"
      type="number"
      name="age"
      min="0">
  </p>

  <p>
    <label for="movie">Favorite Movie</label>
    <select
      id="movie"
      v-model="movie"
      name="movie"
    >
      <option>Star Wars</option>
      <option>Vanilla Sky</option>
      <option>Atomic Blonde</option>
    </select>
  </p>

  <p>
    <input type="submit" value="Submit">
  </p>

</form>

const app = new Vue({
  el: '#app',
  data: {
    errors: [],
    name: null,
    age: null,
    movie: null
  },
  methods:{
    checkForm: function (e) {
      if (this.name && this.age) {
        return true;
      }

      this.errors = [];

      if (!this.name) {
        this.errors.push('Name required.');
      }
      if (!this.age) {
        this.errors.push('Age required.');
      }

      e.preventDefault();
    }
  }
})

vue.js自定义校验

<form
  id="app"
  @submit="checkForm"
  action="https://vuejs.org/"
  method="post"
  novalidate="true"
>
      
 <p>
    <label for="email">Email</label>
    <input
      id="email"
      v-model="email"
      type="email"
      name="email"
    >
  </p>     
      
      
注意顶端的 novalidate="true"
浏览器会尝试在 type="email" 的字端校验邮件地址
const app = new Vue({
  el: '#app',
  data: {
    errors: [],
    name: null,
    email: null,
    movie: null
  },
  methods: {
    checkForm: function (e) {
      this.errors = [];

      if (!this.name) {
        this.errors.push("Name required.");
      }
      if (!this.email) {
        this.errors.push('Email required.');
      } else if (!this.validEmail(this.email)) {
        this.errors.push('Valid email required.');
      }

      if (!this.errors.length) {
        return true;
      }

      e.preventDefault();
    },
    validEmail: function (email) {//自定义校验规则
      var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
      return re.test(email);
    }
  }
})

其他校验方法
















posted @ 2018-08-15 09:25  紫月java  阅读(338)  评论(0编辑  收藏  举报