一、收集表单数据
爱好:
学习<input type="checkbox" value="study" v-model="hobby">
打游戏<input type="checkbox" value="games" v-model="hobby">
吃饭<input type="checkbox" value="eat" v-model="hobby">
这种写法为啥一勾三个全勾呢?
(1)不配置value的话,默认收集的是checkbox,然后hobby被选为true,其他两个一看hobby是true也就选上了,但是我写了value还是不对
(2)hobby默认值不能是' '
多选框要设置type、value、v-model对应的设置为数组
<body>
<div id="root">
<form @submit.prevent="demo">
<!-- 填完信息把信息提交整个表单,而且防止button提交之后跳转页面 -->
<label for="demo" >账号:</label>
<!-- 这样写一个label,点击账号两个字就能在input框里获取焦点了 -->
<input type="text" id="demo" v-model.trim="userInfo.account">
<!-- .trim可以忽略 ab c (获得ab c) -->
<br><br/>
密码:<input type="password" v-model="userInfo.password">
<br><br/>
<!-- 账号和密码输入什么值value就是啥,但是单/多选框没法输入 -->
年龄:<input type="number" v-model.number="userInfo.age">
<!-- 设成type:number可以忽略用户输入的文字 v-model.number是vue提供的,输入到后台就是数字18不是字符串18-->
<br><br/>
性别:
男<input type="radio" name="sex" value="man" v-model="userInfo.sex">
女<input type="radio" name="sex" value="woman" v-model="userInfo.sex">
<br><br/>
爱好:
学习<input type="checkbox" value="study" v-model="userInfo.hobby">
打游戏<input type="checkbox" value="games" 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="shenzhen">深圳</option>
<option value="shanghai">上海</option>
<option value="guangdong">广东</option>
</select>
<br><br/>
其他信息:<textarea v-model.lazy="userInfo.other"></textarea>
<!-- 加上.lazy就会失去焦点的时候再去读入写的啥,不会实时获取 -->
<br><br/>
<input type="checkbox" v-model="userInfo.agree">
阅读并接受<a href="#">《用户协议》</a>
<button>提交</button>
</form>
</div>
<script type="text/javascript">
const vm=new Vue({
el:'#root',
data:{
userInfo:{
password:'',
account:'',
age:'',
sex:'woman',//默认选择女
hobby:[],
city:'beijing',//默认值
agree:'',
//这样单选框就不用设置value,就一个点了就是true否则几句诗false
}
},
methods: {
demo(){
console.log(JSON.stringify(this.userInfo))
//交给后端的方法,但是直接提交data不太好
}
},
})
v-model.lazy
:实现不用实时收集,输入框失去焦点再收集
v-model.number
:输入的字符串收集为数字(Vue内部做了数据转换),经常和type="number"
一起用
v-model.trim
:收集时去掉输入的首尾空格
二、过滤器
1.过滤器定义
定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理比如价格1999改成1,999等需求,复杂的用计算属性或方法)。
语法:
1、注册过滤器:Vue.filter(name,callback) 或 new Vue{filters:{}}
2、使用过滤器:{{ xxx | 过滤器名}} 或 v-bind:属性 = "xxx | 过滤器名"(用的少)
备注:
1、过滤器也可以接收额外参数、多个过滤器也可以串联
2、并没有改变原本的数据, 是产生新的对应的数据
过滤器两种用法:插值语法、v-bind
2.案例:过滤器格式化时间戳:
<body>
<div id="root">
<h2>显示格式化之后的时间</h2>
<!-- 计算属性实现 -->
<h3>现在是:{{fmtTime}}</h3>
<!-- methods实现 -->
<h3>现在是:{{getFmtTime()}}</h3>
<!-- 是方法就得加()调用 -->
<!-- 过滤器实现 要改谁就直接写它名儿-->
<h3>现在是:{{time | timeFormaters}}</h3>
<h3>现在是:{{time | timeFormaters('YYYY-MM-DD')}}</h3>
<!-- 拿着time传给timeFormaters返回值直接到{{}}里面,也就是time是个参数 -->
<!-- 过滤器可以不加(),会给你把|左边的传进去,如果加了(),第一个还是time,第二个参数是格式 -->
<h3>现在是:{{time | timeFormaters('YYYY-MM-DD') | mySlice}}</h3>
<!-- 拿着time传给timeFormaters,timeFormaters拿着传入的结果继续往下 -->
<h3 :x="msg | mySlice">hhh</h3>
<!-- 过滤器不仅可以用在插值里面 -->
</div>
<div id="root2">
<h2>{{mes | mySlice}}</h2>
</div>
<script type="text/javascript">
Vue.filter('mySlice',function(value){
return value.slice(0,4)
})
// 全局过滤器得写在new Vue之前,而且是filter不加s
const vm=new Vue({
el:'#root',
data:{
time:1710744301627,
msg:"你好哇哇哇哇"
},
computed:{
fmtTime(){
return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
// 如果dayjs后面不加参数就默认是当前时间
}
},
methods:{
getFmtTime(){
return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
}
},
filters:{
timeFormaters(value,str='YYYY-MM-DD HH:mm:ss'){
// 过滤器本质是函数
return dayjs(value).format(str)
// 没有格式就默认是'YYYY-MM-DD HH:mm:ss',有的话用传入的格式
},
}
})
// 我写的这些过滤器只能在root vue中可以用
new Vue({
el:'#root2',
data:{
mes:'hello',
}
})
</script>
</body>
三、自定义指令
1.内置指令
v-bind : 单向绑定解析表达式, 可简写为 :xxx
v-model : 双向数据绑定
v-for : 遍历数组/对象/字符串
v-on : 绑定事件监听, 可简写为@
v-if : 条件渲染(动态控制节点是否存存在)
v-else : 条件渲染(动态控制节点是否存存在)
v-show : 条件渲染 (动态控制节点是否展示)
**v-text:**向其所在的节点中渲染文本内容。
<div>{{name}}</div>
<div v-text="name"></div>
当data中name='尚硅谷'的时候,这两段显示出来没有什么区别
但是插值用的更多,因为可以这样写:
<div>你好哇{{name}}</div>
而v-text把所有内容当文本会替换掉整个div 的内容,div里面写东西没用,''内容里的写标签它也不识别
v-html :向指定节点中渲染包含html结构的内容。
data:{
name:'尚硅谷',
str:'<h3>hhh</h3>'
},
与插值语法的区别:
(1)v-html会替换掉节点中所有的内容,{{xx}}则不会,这点和v-text一样。
(2)v-html可以识别html结构,这点和v-text区别,v-text不能渲染标签。
严重注意:v-html有安全性问题!!!!
(1)在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
(2)一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!
v-cloak
(没有值):不让未经解析的模版跑到页面上去
script链接的js如果延迟五秒的话,body内的内容就不会展示在界面上,vue也不会工作
如果script链接的js写在body里面的最下方,那么body上面的内容会出现在页面上但是不被解析
(1)本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
(2)使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题,先隐藏标签,然后Vue渲染完了之后删除v-cloak,那么就能显示渲染完之后的页面了。
<style>
[v-colak]{
/* 选中所有标签属性里面有v-colak的 */
display: none;
}
</style>
<body>
<div id="root">
<div v-cloak>{{name}}</div>
</div>
<script type="text/javascript">
const vm=new Vue({
el:'#root',
data:{
name:'尚硅谷',
},
})
v-once
指令:(没有值)
(1)v-once所在节点在初次动态渲染后,就视为静态内容了,也就是只读一次。
(2)以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
<div id="root">
<div v-once>{{n}}</div>
<button @click="n++">点我n+1</button>
<div>{{n}}</div>
</div>
v-pre
指令:(没有值)
(1)跳过其所在节点的编译过程。
(2)可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。
也就是程序员写的什么样它就呈现出来什么样,vue不去解析了
2.自定义指令
(1)函数式
big函数何时调用?
1、指令与元素成功绑定时(一上来,没放入页面之前)
2、指令所在的模板被重新解析时
点击按钮使n++,输出n*10
<div id="root">
<h2>当前的n值是:
<span v-text="n"></span>
</h2>
<h2>放大10倍的n值是:
<span v-big="n"></span>
</h2>
<button @click="n++">点我n++</button>
</div>
<script type="text/javascript">
const vm=new Vue({
el:'#root',
data:{
n:1,
},
directives:{
big(element,binding){//这里就不加v-了
// 这里的binding是说v-big和span的绑定关系,不是v-bind
// return this.n*10这么写不对!!
// 不是靠返回值,是靠big这个函数返回的参数
console.log(element,binding)
// 第一个参数是说跟什么标签绑定的span(真实dom)
// 第二个参数是一个存着指令值的对象
element.innerText=binding.value*10
}
}
(2)对象式
配置对象中常用的3个回调:
bind
:指令与元素成功绑定时(一上来,没放入页面之前)
inserted
:指令所在元素被插入页面时调用(放入页面后)
update
:指令所在模板结构被重新解析时调用(有任意data中的东西被改了)。
案例:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。
<div id="root">
<h2>当前的n值是:
<span v-text="n"></span>
</h2>
<h2>放大10倍的n值是:
<span v-big="n"></span>
</h2>
<button @click="n++">点我n++</button>
</br>
<input type="text" v-fbind:value="n">
</div>
const vm=new Vue({
el:'#root',
data:{
n:1,
},
directives:{
// 函数调用的时候:一上来;指令所在模版被重新解析
big(element,binding){//这里就不加v-了
// 这里的binding是说v-big和span的绑定关系,不是v-bind
// return this.n*10这么写不对!!
// 不是靠返回值,是靠big这个函数返回的参数
console.log(element,binding)
// 第一个参数是说跟什么标签绑定的span(真实dom)
// 第二个参数是一个存着指令值的对象
element.innerText=binding.value*10
},
// fbind(element,binding){
// element.value=binding.value
// element.focus()
//这个放在这里刷新之后并没有自动获取焦点,所以不能写成函数得弄成对象,因为:
//fbind第一次调用就在他俩成功绑定也就是一上来的时候,那会input还没被解析到页面上,所以出不来焦点
//如果这时候点了button发现input自动获取焦点了,因为n值改变fbind再次被调用了,这时候input框已经出来了
// }
fbind:{
//指令与元素成功绑定时(一上来)
bind(element,binding){
element.value=binding.value
},
//指令所在元素被插入到页面时调用
inserted(element,binding){
element.focus()
},
//指令所在的模版被重新调用时
update(element,binding){
element.value=binding.value
}
// bind和updata往往都一样,所以人家设置了函数
}
}
})
</script>
(3)注意点
1.多个单词用-分割,v-big-number,而且在vue中写函数的时候不能简写了,得:
'big-number'(element,binding){}
2.指令里面相关的this都是window
(4)写全局指令:
Vue.directive(指令名,配置对象) 或 Vue.directive(指令名,回调函数)
Vue.directive('fbind',{
bind、、
update、、、
})
和filter一样不加s
写全局函数:
Vue.directive('big',function(element,binding){
element.innerText=binding.value*10
})
四、Vue的生命周期!!
1.什么是生命周期?
一个小笔记:{{}}如果返回值为undefined的话不显示在页面上
生命周期
1.又名:生命周期回调函数、生命周期函数、生命周期钩子。
2.是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
4.生命周期函数中的this指向是vm 或 组件实例对象。
mounted之前有一些函数,之后有一些函数,这三种加一块就组成生命周期
2.生命周期中的8个钩子
整个root div都是模版template
把内容写在template里和直接写在body里有区别:写在template里root的div就不被解析了,而且template里边只能有一个根元素,template标签不能作为根元素出现在vue中的template(它不显示在页面上)
重要的生命周期钩子
1.mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
2.beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。
关于销毁Vue实例
1.销毁后借助Vue开发者工具看不到任何信息。
2.销毁后自定义事件会失效,但原生DOM事件依然有效,销毁后所有的监视也没了
3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。
beforeCreate() {
console.log('beforeCreate');
console.log(this);
// debugger;
},
created() {
console.log('created');
// create的是数据代理和数据监测
},
beforeMount() {
console.log('beforeMount');
// 挂载之前对dom的操作最终都无效所以不要操作
},
mounted() {
console.log('mounted');
// 避免对dom操作,让vue来
},
beforeUpdate() {
console.log('beforeUpdate');
},
updated() {
console.log('updated');
},
beforeDestroy() {
console.log('beforeDestroy');
// 如果这个时候调函数让n++,这个操作不会让数据更新了
// 可以访问数据和调用函数,但是不更新
},
destryed() {
console.log('destryed');
// 销毁了但是它之前的成果还会留着
}
3.图解生命周期
4.案例:字体闪烁,点击停止(销毁vm)
<body>
<div id="root">
<h1 :style="{opacity}">欢迎学习Vue</h1>
<!-- opacity本来就是透明度,正好变量设置的也是opacity,可以简略写成opacity -->
<button @click="stop">停止变换</button>
<button @click="opacity=1">透明度设置为1</button>
<!-- destory很少用vm.$destory(紫砂)得v-if或v-for -->
</div>
<script type="text/javascript">
const vm=new Vue({
el:'#root',
data:{
opacity:1,
},
methods: {
stop(){
// clearInterval(this.timer)
// 我想拿到mounred里的东西不能直接给下面const为id,这儿是找不着id的
// 加上this,但是清理定时器以后还能打开,我想要销毁
this.$destory(timer)
// 这样是页面停了但是定时器还一直在变化
},
},
mounted() {
this.timer=setInterval(()=>{
this.opacity-=0.01
if(this.opacity<=0) this.opacity=1
},16)
},
beforeDestroy() {
clearInterval(this.timer)
// 这句话写在stop也行但是是紫砂的时候才调用,但是写在这里就是不管紫砂还是他砂都停止定时器
},
})
</script>
</body>