1.vue基础
1.1 Vue下载安装
1.1.1js文件安装
进入网站:https://cn.vuejs.org
下载:学习--教程--左侧的安装---下载开发版,点击进入,复制---到项目中创建vue.js文件,将内容复制即可,用script引入
<script type="text/javascript" src="Vue/vue.js" ></script>
1
<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
1
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
1.1.2 win下安装node.js
- 下载安装:
- http://nodejs.cn/
- 下载msi的版本,安装即可
- 测试:
- 打开cmd,输入node进入,然后就可以测试了
- 退出:两次Ctrl+c
- 查看版本号: npm -v
若是没有版本号,需要修改环境变量:在用户变量的path中加上:C:UsersjsyAppDataRoaming pm
1.1.3安装命令行工具MobaXterm
打开即可使用;
配置:打开Settings
- 安装cnpm
- 方法1:
npm install -g cnpm --registry=https://registry.npm.taobao.org
//但是这样版本可能会不一致
x
1
npm install -g cnpm --registry=https://registry.npm.taobao.org
2
//但是这样版本可能会不一致
- 方法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"
5
5
1
或者你直接通过添加 npm 参数 alias 一个新命令:
2
alias cnpm="npm --registry=https://registry.npm.taobao.org
3
--cache=$HOME/.npm/.cache/cnpm
4
--disturl=https://npm.taobao.org/dist
5
--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
111vue -V
- 查看官方提供的模板
vue list //速度回有点慢
111vue 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目录
17
17
1
vue init webpack my-project //搭建项目
2
接下来是配置:
3
项目名
4
描述
5
作者
6
安装vue-router y
7
代码校验ESLint n
8
测试工具tests 看个人需要 n
9
e2s tests 测试工具 n
10
生成项目;
11
启动项目:
12
1.安装依赖:
13
进入项目文件夹my-project
14
cnpm install //安装依赖 node_modules
15
npm run dev //启动项目
16
生成部署用的文件:
17
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
5
5
1
在项目中安装
2
cnpm install vuex --save
3
//若是重启了工具,要重新把上面的npm转cnpm的代码运行一下,
4
安装完之后,重新运行项目
5
npm run dev
1.1.6 安装vue-resource
cnpm install vue-resource
1
1
1
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')
})
19
19
1
cnpm install json-server --save
2
打开项目,进入build 打开dev-server.js文件,
3
在第四行express下:
4
var jsonServer=require('json-server')
5
在第16行var app = express()之下写
6
var jsonServer=new jsonServer()
7
在最底下module.exports之前设置:
8
9
10
var jsonServer=require('json-server')
11
var apiserver=jsonServer.create()
12
var apirouter=jsonServer.router('db.json')//此目录是项目的目录,放置此文件到项目文件夹中
13
var middlewares=jsonServer.defaults()
14
apiserver.use(middlewares)
15
apiserver.use('/api',apirouter)
16
apiserver.listen(3000,function () {//监听的接口,
17
console.log('JSON Server is running')
18
})
19
配置后端接口路径
打开config中的index.js文件,其中配置的就是后端
1
1
1
打开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) + '
')
})
30
30
1
var apiServer = express()
2
var bodyParser = require('body-parser')
3
apiServer.use(bodyParser.urlencoded({ extended: true }))
4
apiServer.use(bodyParser.json())
5
var apiRouter = express.Router()
6
var fs = require('fs')
7
apiRouter.route('/:apiName')//动态设置路由接口
8
.all(function (req, res) {
9
fs.readFile('./db.json', 'utf8', function (err, data) {
10
if (err) throw err
11
var data = JSON.parse(data)
12
if (data[req.params.apiName]) {//判断是否有这个接口
13
res.json(data[req.params.apiName])//设置返回值
14
}
15
else {
16
res.send('no such api name')
17
}
18
19
})
20
})
21
22
23
apiServer.use('/api', apiRouter);
24
apiServer.listen(port + 1, function (err) {
25
if (err) {
26
console.log(err)
27
return
28
}
29
console.log('Listening at http://localhost:' + (port + 1) + '
')
30
})
1.2 vue概述
生命周期
1.2.1 挂载点、模板、实例的关系
挂载点:就是页面的标签,vue只会处理挂载点下面的内容
<div id="root"></div>
1
1
1
<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>
13
13
1
<body>
2
<div id="root">{{msg}}</div><!--显示msg中内容-->
3
</body>
4
<script>
5
/*创建一个vue实例,让这个实例接管页面上的id为root的标签*/
6
new Vue({
7
el:"#root", /*绑定:id为root的*/
8
template:'<h1>你好,{{msg}}</h1>',/*在root内部设置内容*/
9
data:{
10
msg:"hello world"
11
}
12
})
13
</script>
实例: 在vue实例中的data中,可以设置任意的名字,只要用{{ }}就可以显示
1.2.1 vue实例显示方法(html,text)
1.用{{ }}显示
{{msg}}
1
1
1
{{msg}}
2.在标签上使用v-text显示:(若是HTML格式的内容,会直接将标签显示)
<h1 v-text='msg'></h1>
1
1
1
<h1 v-text='msg'></h1>
3.在标签上使用v-html显示:(会将标签转义,显示处理后的页面样式)
<h1 v-html='msg'></h1>
1
1
1
<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):
3
3
1
使用:
2
(1)v-bind:
3
(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
2
1
{{content?content:"你好"}}
2
当content有值的时候显示值,没有的时候显示"你好"
(2)lazy修改器:延迟修改
只有当修改完之后,点击了enter或者失去焦点的时候,才会修改,input必须定义type为text
<input type="text" v-model.lazy="myVlaue" /><!--延迟-->
{{myVlaue}}
2
2
1
<input type="text" v-model.lazy="myVlaue" /><!--延迟-->
2
{{myVlaue}}
(3)number数字转为number格式
<input type="text" v-model.number="myVlaue" /><!--延迟-->
{{typeof myVlaue}} 输出的是类型
2
2
1
<input type="text" v-model.number="myVlaue" /><!--延迟-->
2
{{typeof myVlaue}} 输出的是类型
注意:是数字格式的会转化为number,但是字符串的不会影响
(4)trim去掉前后空格
<input type="text" v-model.trim="myVlaue" /><!--延迟-->
{{myVlaue}}
2
2
1
<input type="text" v-model.trim="myVlaue" /><!--延迟-->
2
{{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){}
}
3
3
1
watch:{
2
myVlaue:function(val,oldVal){}
3
}
()
当姓或名做了改变的时候,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
<a v-if="isshow">456</a> <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'
}
6
6
1
<div v-for="(value,key) in objlist" >{{value}}---{{key}}</div>
2
objlist:{
3
name:'app',
4
price:123,
5
color:'red'
6
}
(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>
1
1
1
<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)
}
}
7
7
1
<button @click="changelist">changelist</button>
2
-----------------
3
methods:{
4
changelist:function (){
5
Vue.set(this.list,1,123)
6
}
7
}
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>'
}
3
3
1
var TodoIrem={
2
template:'<li>item</li>'
3
}
由于是局部的,需要在要使用的实例哪里声明
new Vue({
el:"#root",
components:{ //做组件声明
'todo-item':TodoItem
//若是左右相同,可以只写一边的 TodoItem
},
6
6
1
new Vue({
2
el:"#root",
3
components:{ //做组件声明
4
'todo-item':TodoItem
5
//若是左右相同,可以只写一边的 TodoItem
6
},
- 组件使用:
- 方法1:
<todo-item></todo-item> <!--一样-->
1
1
1
<todo-item></todo-item> <!--一样-->
- 方法2:使用is引入
<p is='todo-irem'></p>
1
1
1
<p is='todo-irem'></p>
方法2优势,可以动态的使用组件,使用:is 的时候,可以引用变量
动态引入:
<p :is='getTodo'></p>
data中: getTodo:'todo-irem'
3
3
1
动态引入:
2
<p :is='getTodo'></p>
3
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>
3
3
1
<todo-irem><!--调用子组件,子组件中有内容<li>i123131132tem</li>-->
2
<p>123</p>
3
</todo-irem>
只会显示:子组件本身定义的内容
想要这部分内容显示,可以在子组件的模板中使用标签
template:'<div><li>i123131132tem</li><slot></slot></div>' 在子组件中加上这个标签,就会把父组件调用的时候添加的内容显示 注意:子组件必须在一个大标签之下, |
- 插槽设置默认内容
当插槽没有设置的时候,默认显示内容
template:'<div><li>i123131132tem</li><slot>没有内容</slot></div>' , |
- 插槽设置名字
<todo-irem><!--调用子组件,子组件中有内容<li>i123131132tem</li>--> <p 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
在父组件中声明子组件之后,在页面中:
<p :is='getTodo'></p> |
这样就可以动态设置了,getTodo是data中的属性,通过改变它的值改变绑定的子组件
getTodo:'todo-irem' |
(9)组件缓存:<keep-alive>
<keep-alive> <p :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'
}
})
7
7
1
实例对象有一个对象名root
2
var root=new Vue({
3
el: '#app',
4
data: {
5
content: 'Hello'
6
}
7
})
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:[]
6
6
1
<input v-model="myBox" type="radio" value="111" />
2
<input v-model="myBox" type="radio" value="222" />
3
<input v-model="myBox" type="radio" value="333" />
4
{{myBox}}
5
--------------
6
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
3
1
<input v-model="myBox" type="checkbox" value="111" />
2
<input v-model="myBox" type="checkbox" value="222" />
3
<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
8
8
1
<select v-model="sel">
2
<option value="1">11</option>
3
<option value="2">22</option>
4
<option value="3">33</option>
5
</select>
6
{{sel}}
7
------------
8
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},
]
11
11
1
<select v-model="sel">
2
<option v-for="item in seloption" :value="item.value">{{item.text}}</option>
3
</select>
4
{{sel}}
5
------------
6
sel:null,
7
seloption:[
8
{text:'app1',value:1},
9
{text:'app2',value:2},
10
{text:'app3',value:3},
11
]
一般情况,这种下拉会创建一个组件,直接调用组件:
<vSelect @onSelect='' :list="seloption"></vSelect>
1
1
1
<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'> <p v-show="show">456</p> </transition> |
(1)css过渡
- 淡入淡出
show:true, --------------------- <button @click="show=!show">button</button> <transition name='fade'> <p v-show="show">456</p> </transition> -------------------- 在style中定义样式 <style> .fade-enter-active,.fade-leave-active{ transition:/*opacity*/ all .5s ;/*属性,时长,还可以加上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'
}
}
14
14
1
<transition name='my-trans'>
2
<div :is='getTodo'></div>
3
</transition>
4
<button @click="getTodoFun">button</button>
5
---------------
6
getTodo:'todo-irem'
7
------------
8
getTodoFun:function(){
9
if(this.getTodo==='todo-irem'){
10
this.getTodo='todo-irem2'
11
}else{
12
this.getTodo='todo-irem'
13
}
14
}
多元素过渡
多个元素切换,是将新的在下方显示,在将旧的隐藏,有同时出现的机会,默认是in-out
使用out-in,会先将就的去掉,再显示新的 <transition name='my-trans' mode='out-in'> <p v-show="show">456</p> </transition> |
注意,多个元素的时候,过渡动画会消失,需要定义key区分每一个元素
<button @click="show=!show">button</button> <transition name='fade' mode='out-in'> <p v-if="show" key='1'>456</p> <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'> <p 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 } } |
使用自定义指令:
<p 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
1
1
1
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 }
})
14
14
1
进入项目目录:(在搭建项目的时候安装了)
2
cnpm install vue-router --save
3
4
项目中载入,一般在main.js中载入:
5
import VueRouter from 'vue-router'
6
Vue.use(VueRouter)
7
let router = new VueRouter({}) //其中配置路径和地址
8
在Vue中引入:
9
new Vue({
10
el: '#app',
11
router,
12
template: '<APP/>',
13
components: { APP }
14
})
(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
9
9
1
设置参数:
2
path:'/apple/:color',
3
页面:
4
http://localhost:8080/apple/red
5
获取参数:
6
在Apple.vue获取:
7
<div >{{$route.params}}</div> { "color": "red" }
8
<div >{{$route.params.color}}</div> red
9
在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
5
1
path:'/apple/:color/deee/:aa',
2
其中:color和:aa是用户可以自定义的参数,可以是任何内容;
3
deee是路径,不能修改
4
可以的访问路径为:http://localhost:8080/apple/red/deee/asas
5
只有带: 的参数才会在$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>
18
18
1
<router-link :to="{path:'apple'}">to apple</router-link>
2
基于当前路径跳转
3
<router-link :to="'apple'">to apple</router-link>
4
根目录:
5
<router-link :to="'/apple'">to apple</router-link>
6
动态设置:
7
<router-link :to="apple">to apple</router-link>
8
在data中:
9
data(){
10
reurn{
11
apple:'apple'
12
}
13
}
14
传递参数:
15
<router-link :to="{path:'apple',param:{color:'red'}}">to apple</router-link>
16
可以访问 apple/red(参数)
17
改变router-link显示样式:
18
<router-link :to="'apple'" tag="li">to apple</router-link>
(7)js中定义导航,跳转
router.push('apple') //或 {path:'apple'}
或
this.$router.push('/login');
3
3
1
router.push('apple') //或 {path:'apple'}
2
或
3
this.$router.push('/login');
(8)路由命名
{
path:'/apple',
component:Apple,
name:'applePage'
}
访问:
<router-link :to="{name:'applePage'}">to apple</router-link>
8
8
1
{
2
path:'/apple',
3
component:Apple,
4
name:'applePage'
5
6
}
7
访问:
8
<router-link :to="{name:'applePage'}">to apple</router-link>
- 命名路由视图
在router-view 上添加name
<router-view name='viewA '></router-view>
1
1
1
<router-view name='viewA '></router-view>
路由表中可以根据name定义页面
{
path:'/apple',
component:{
viewA:Apple,
viewB:OtherApple,
},
name:'applePage'
}
8
8
1
{
2
path:'/apple',
3
component:{
4
viewA:Apple,
5
viewB:OtherApple,
6
},
7
name:'applePage'
8
}
(9)路由重定向
比如默认页面是具体的某一个页面,比如访问根目录,会自动跳转到Apple.vue目录
{ path:"/", redirect:'/apple' }, |
(10)页面跳转--过渡
<transition name='fff'>
<keep-alive><!--缓存-->
<router-view></router-view>
</keep-alive>
</transition>
5
5
1
<transition name='fff'>
2
<keep-alive><!--缓存-->
3
<router-view></router-view>
4
</keep-alive>
5
</transition>
2.2vuex 状态管理
2.2.1引入
在全局中引用:(在main.js中的vue中引用)
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
}
}
})
new Vue({ |
其他文件调用:
在上面引用之后,每个组件都可以使用:
this.$store.state.totalPrice |
(1)案例:全局加减
创建Apple和Banana两个vue文件,在APP.vue中引入
方法1:
<template> |
每一个vue组件都有一个+1和-1的按钮
<template> |
方法2:
let store=new Vuex.Store({ /*调用*/ |
addOne(){ |
- 在Store中还可以设置getters获取数据
getters:{/*获取数据*/ |
可以定义多个状态集,最后汇总
2.3 vue-resource:整合ajax
在main.js中
import VueResource from 'vue-resource'
Vue.use(VueResource)
每一个页面都可以使用this.$http
4
4
1
在main.js中
2
import VueResource from 'vue-resource'
3
Vue.use(VueResource)
4
每一个页面都可以使用this.$http
2.3.1 ajax案例
- get:
/*ajax请求 */
this.$http.get('api/getNewsList')
.then((res) => {/*成功回调*/
this.newsList = res.data //赋值
}, (err) => {/*失败回调*/
console.log(err)
})
7
7
1
/*ajax请求 */
2
this.$http.get('api/getNewsList')
3
.then((res) => {/*成功回调*/
4
this.newsList = res.data //赋值
5
}, (err) => {/*失败回调*/
6
console.log(err)
7
})
- 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("登录失败!")
});
14
14
1
this.$http.post(this.GLOBAL.urlHead+'manager/login',{managerUserName:this.ruleForm.username,managerPass:this.ruleForm.password},{emulateJSON:true})
2
.then((res) => {/*成功回调*/
3
if (res.data.state==1) {
4
alert(res.data.msg)
5
localStorage.setItem('managerName',res.data.data.managerName);//ms_username
6
localStorage.setItem('managerId',res.data.data.managerId);//ms_username
7
this.$router.push('/index');
8
}else {
9
alert(res.data.msg)
10
}
11
}, (err) => {/*失败回调*/
12
console.log(err)
13
alert("登录失败!")
14
});
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)
})
},
11
11
1
/*在组建创建完之后加载:页面加载*/
2
created: function () {
3
/*ajax请求 */
4
this.$http.get('api/getNewsList')
5
//post参数:.post('api/getNewsList',{userId:123,aa:44})
6
.then((res) => {/*成功回调*/
7
this.newsList = res.data //赋值
8
}, (err) => {/*失败回调*/
9
console.log(err)
10
})
11
},
2.3.3页面初次加载判断
使用一个没有定义的参数进行判断,默认为false,只需要判断完设置为true即可
if (!this.userFlag) {
errorText = ''
this.userFlag = true
}
4
4
1
if (!this.userFlag) {
2
errorText = ''
3
this.userFlag = true
4
}
2.4 vue的UI组件
- GitHub地址:https://github.com/vuejs/awesome-vue
2.3.3 轮播图组件
2.3.4显示项目图片
使用js设置的图片
数据:src: require('../assets/slideShow/pic1.jpg')
3
3
1
使用js设置的图片
2
数据:src: require('../assets/slideShow/pic1.jpg')
3
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;
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>
73
73
1
<template>
2
<div class="left-nav">
3
<ul>
4
<li>
5
<i class="icon iconfont icon-wodezichan"></i>
6
<div>收银</div>
7
</li>
8
9
<li>
10
<i class="icon iconfont icon-dianpu"></i>
11
<div>店铺</div>
12
</li>
13
14
<li>
15
<i class="icon iconfont icon-hanbao"></i>
16
<div>商品</div>
17
</li>
18
19
<li>
20
<i class="icon iconfont icon-huiyuanqia"></i>
21
<div>会员</div>
22
</li>
23
24
<li>
25
<i class="icon iconfont icon-shijian"></i>
26
<div>抢购</div>
27
</li>
28
29
<li>
30
<i class="icon iconfont icon-tongji"></i>
31
<div>统计</div>
32
</li>
33
34
·
35
</ul>
36
</div>
37
</template>
38
39
<script>
40
export default {
41
name: 'Main',
42
data () {
43
return {
44
45
}
46
}
47
}
48
</script>
49
50
<!-- Add "scoped" attribute to limit CSS to this component only -->
51
<style>
52
.left-nav{
53
color:#fff;
54
font-size:10px;
55
height:100%;
56
background-color: #1D8ce0;
57
float:left;
58
width:5%;
59
}
60
.iconfont{/*设置图标大小*/
61
font-size:24px;
62
}
63
.left-nav ul{
64
padding:0px;
65
margin: 0px;
66
}
67
.left-nav li{
68
list-style: none;
69
text-align: center;
70
border-bottom:1px solid #20a0ff;
71
padding:10px;
72
}
73
</style>
- APP.vue中引用:
<leftNav></leftNav>
import leftNav from '@/components/common/leftNav'
components:{
leftNav
}
同时要调整APP的样式(比如#APP的margin-top)
6
6
1
<leftNav></leftNav>
2
import leftNav from '@/components/common/leftNav'
3
components:{
4
leftNav
5
}
6
同时要调整APP的样式(比如#APP的margin-top)
复制,赋值不绑定
vue表单校验
vue.js校验
给定一个表单,包含三个字段,其中两个是必填项
<form
id="app"
@submit="checkForm"
action="https://vuejs.org/"
method="post"
>
解释:
id 确认vue的
submit 处理函数
action 跳转路径
10
10
1
<form
2
id="app"
3
@submit="checkForm"
4
action="https://vuejs.org/"
5
method="post"
6
>
7
解释:
8
id 确认vue的
9
submit 处理函数
10
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>
52
52
1
<form
2
id="app"
3
@submit="checkForm"
4
action="https://vuejs.org/"
5
method="post"
6
>
7
8
<p v-if="errors.length">
9
<b>Please correct the following error(s):</b>
10
<ul>
11
<li v-for="error in errors">{{ error }}</li>
12
</ul>
13
</p>
14
15
<p>
16
<label for="name">Name</label>
17
<input
18
id="name"
19
v-model="name"
20
type="text"
21
name="name"
22
>
23
</p>
24
25
<p>
26
<label for="age">Age</label>
27
<input
28
id="age"
29
v-model="age"
30
type="number"
31
name="age"
32
min="0">
33
</p>
34
35
<p>
36
<label for="movie">Favorite Movie</label>
37
<select
38
id="movie"
39
v-model="movie"
40
name="movie"
41
>
42
<option>Star Wars</option>
43
<option>Vanilla Sky</option>
44
<option>Atomic Blonde</option>
45
</select>
46
</p>
47
48
<p>
49
<input type="submit" value="Submit">
50
</p>
51
52
</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();
}
}
})
27
27
1
const app = new Vue({
2
el: '#app',
3
data: {
4
errors: [],
5
name: null,
6
age: null,
7
movie: null
8
},
9
methods:{
10
checkForm: function (e) {
11
if (this.name && this.age) {
12
return true;
13
}
14
15
this.errors = [];
16
17
if (!this.name) {
18
this.errors.push('Name required.');
19
}
20
if (!this.age) {
21
this.errors.push('Age required.');
22
}
23
24
e.preventDefault();
25
}
26
}
27
})
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>
19
19
1
<form
2
id="app"
3
@submit="checkForm"
4
action="https://vuejs.org/"
5
method="post"
6
novalidate="true"
7
>
8
9
<p>
10
<label for="email">Email</label>
11
<input
12
id="email"
13
v-model="email"
14
type="email"
15
name="email"
16
>
17
</p>
18
19
注意顶端的 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);
}
}
})
x
33
1
const app = new Vue({
2
el: '#app',
3
data: {
4
errors: [],
5
name: null,
6
email: null,
7
movie: null
8
},
9
methods: {
10
checkForm: function (e) {
11
this.errors = [];
12
13
if (!this.name) {
14
this.errors.push("Name required.");
15
}
16
if (!this.email) {
17
this.errors.push('Email required.');
18
} else if (!this.validEmail(this.email)) {
19
this.errors.push('Valid email required.');
20
}
21
22
if (!this.errors.length) {
23
return true;
24
}
25
26
e.preventDefault();
27
},
28
validEmail: function (email) {//自定义校验规则
29
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,}))$/;
30
return re.test(email);
31
}
32
}
33
})