一.idea如何创建vue项目
1.官网下载node.js,尽量不要下载那么新的版本
2.cmd中查看node版本,输入node -v
3.cmd中输入npm install -g @vue/cli@5.0.8(我这里安装的是这个版本,可以自行选择)
4.输入vue -V查询脚手架版本,即安装成功。
5.在idea中安装vue.js插件:File->Setting->Plugins,在marketplace中下载Vue.js,然后可以在installed中可以查看到vue.js.
6.在idea中创建vue项目
推荐:创建一个文件夹,在文件夹打开cmd,在cmd中输入命令:vue create springboot-vue demo,选择最后一项回车
。。。。借鉴博客:
Idea创建vue项目_Z-LittleQ的博客-CSDN博客
vue创建的目录结构:
build 项目构建(webpack)相关代码
config 配置目录,包括端口号。
node_modules npm加载的项目依赖模块
src :
- assets: 放置一些图片,如logo等。
- components: 目录里面放了一个组件文件,可以不用。
- App.vue: 项目入口文件,我们也可以直接将组件写这里,而不使用 components 目录。
- main.js: 项目的核心文件。
-
static 静态资源目录,如图片、字体等。 test 初始测试目录,可删除 .xxxx文件 这些是一些配置文件,包括语法配置,git配置等。 index.html 首页入口文件,你可以添加一些 meta 信息或统计代码啥的。 package.json 项目配置文件。 README.md 项目的说明文档,markdown 格式
菜鸟教程:Vue.js 目录结构 | 菜鸟教程
v-bind的详细学习:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>v-bind使用</title> <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script> <style> .box{ border: 1px dashed #c42bc4; } .textColor{ color: #f00; background-color: #eef; } .textSize{ font-size: 30px; font-weight: bold; } </style> </head> <body> <!-- 1.v-bind:class 一个对象,以动态地切换class --> <!--<ul class="box" v-bind:class="{'textColor':isColor, 'textSize':isSize}"> <li>学习Vue</li> <li>学习Node</li> <li>学习React</li> </ul> <script> var vm= new Vue({ el:'.box', data:{ isColor:true, isSize:true } }) </script>--> <!-- 2.直接绑定数据里的一个对象 <li></li>无序标签 --> <!--<ul class="box" :class="classObject"> <li>学习Vue</li> <li>学习Node</li> <li>学习React</li> </ul> <script> var vm = new Vue({ el: '.box', data:{ classObject:{ 'textColor':true, 'textSize':false //不进行渲染 } } }) </script>--> <!-- 3.v-bind中的数组语法,将数组传递给一个class列表 --> <!--<ul class="box" :class="[classA, classB]"> <li>学习Vue</li> <li>学习Node</li> <li>学习React</li> </ul> <script> var vm= new Vue({ el:'.box', data:{ classA:'textColor', classB:'textSize' } }) </script>--> <!-- 3.1 v-bind中的数组语法,根据条件切换列表中的class,可以用三目运算 --> <ul class="box" :class="[isA?classA:'', classB]"> <li>学习Vue</li> <li>学习Node</li> <li>学习React</li> </ul> <script> var vm= new Vue({ el:'.box', data:{ classA:'textColor', classB:'textSize', isA:false } }) </script> </body> </html>
v-model详细学习:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script> </head> <body> <!-- v-model指令实现表单元素和数据的双向绑定 <input type="text" v-model="message"> v-model实现双向绑定的原理 <input type="text" :value="message" @input="message=$event.target.value"> 1.v-bind绑定一个value属性 2.v-on指令给当前元素绑定input事件 除了input,也可将v-model用于textarea元素 --> <!-- 1.v-model 结合radio --> <!--<div id="app"> <label><input type="radio" value="男" v-model="sex">男</label> <label><input type="radio" value="女" v-model="sex">女</label> <h2>您选择的性别是:{{sex}}</h2> </div> <script> const app = new Vue({ el: '#app', data: { message: '你好', sex: '男' } }) </script>--> <!-- 2.v-model结合checkbox checkbox 单选框应用(同意协议),单选框时对应布尔类型,绑定checked --> <!-- <div id="app"> <!– checkbox单选框应用 –> <label><input type="checkbox" v-model="isAgree">同意协议</label> <h2>您选择的是:{{isAgree}}</h2> <!– disabled 关闭 –> <button :disabled="!isAgree">下一步</button> </div> <script> const app = new Vue({ el: '#app', data: { message: '你好', isAgree: false } }) </script> --> <!--<div id="app"> <!– checkbox多选框应用 –> <label><input type="checkbox" value="篮球" v-model="hobbies">篮球</label> <label><input type="checkbox" value="足球" v-model="hobbies">足球</label> <label><input type="checkbox" value="羽毛球" v-model="hobbies">羽毛球</label> <label><input type="checkbox" value="乒乓球" v-model="hobbies">乒乓球</label> <h2>您的爱好有:{{hobbies}}</h2> </div> <script> const app = new Vue({ el: '#app', data: { hobbies: [] } }) </script>--> <!-- 3.v-model结合select 单选,对应字符串类型 单选:只能选中其中一个 ·v-model绑定一个值 ·当我们选中option中的一个时,会将它对应的value赋值到mySelect中 --> <!--<div id="app"> <!– 1.单选 –> <select name="abc" v-model="fruit"> <option value="苹果">苹果</option> <option value="西瓜">西瓜</option> <option value="香蕉">香蕉</option> <option value="葡萄">葡萄</option> </select> <h2>您选择的水果是:{{fruit}}</h2> </div> <script> const app = new Vue({ el: '#app', data: { fruit: '葡萄' } }) </script>--> <!--多选,对应数组类型 多选:可以选中多个值 ·v-model绑定的是一个数组 ·当选中多个值时,就会将选中的option对应的value添加到数组mySelect中 --> <!--<div id="app"> <!– 2.多选 –> <select name="abc" v-model="fruits" multiple> <option value="苹果">苹果</option> <option value="香蕉">香蕉</option> <option value="西瓜">西瓜</option> <option value="葡萄">葡萄</option> </select> <h2>您选择的水果是:{{fruits}}</h2> </div> <script> const app = new Vue({ el: '#app', data: { fruits: [] } }) </script>--> <!-- 4.v-model 给值绑定 即动态地给value赋值(实际就是v-bind) --> <div id="app"> <!-- 值绑定 --> <label v-for="item in originHobbies" :for="item"> <input type="checkbox" :value="item" :id="item" v-model="hobbies">{{item}} </label> <h2>您的爱好有:{{hobbies}}</h2> </div> <script> const app = new Vue({ el: '#app', data: { originHobbies: ['篮球', '足球', '羽毛球', '乒乓球', '高尔夫球'], hobbies: [] } }) </script> <!--5、v-model 修饰符 (1).lazy v-model默认是在input事件中同步输入框的数据的。.lazy 可以让数据在失去焦点或者回车时才会更新 <input type="text" v-model.lazy="message"> (2).number 默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当作字符串类型进行处理。.number 可以让在输入框中输入的内容自动转化成数字类型 <input type="number" v-model.number="age"> (3).trim 如果输入的内容首尾有很多空格,通常我们希望将其去除。.trim 可以过滤内容左右两边的空格 <input type="text" v-model.trim="name"> (4).native 监听组件根元素的原生事件 组件不能直接监听点击,如果监听需要加.native <back-top @click.native="backClick" /> --> </body> </html>
计算属性computed
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>computed计算属性</title> <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script> </head> <body> <!-- 计算属性: computed与methods的区别: 计算属性有依赖缓存 如果值没有发生变化是不会重新调用计算属性 methods没有缓存 每一个调用都会重新执行/渲染 发送异步请求 计算属性不处理异步请求 我们可以使用 methods 来替代 computed,效果上两个都是一样的, 但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。 而使用 methods ,在重新渲染的时候,函数总会重新调用执行。 使用computed性能会更好,如果不希望缓存,可以使用methods属性 --> <!-- 反转字符串 --> <!--<div id="app"> {{message.split('').reverse().join('')}} </div> <script> var vm = new Vue({ el: '#app', data: { message: "hello world!!" } }) </script>--> <!--<div id="app"> <p>原始字符串: {{ message }}</p> <p>计算后反转字符串: {{ reversedMessage }}</p> </div> <script> var vm = new Vue({ el: '#app', data: { message: 'Runoob!' }, /* 声明的计算属性reverseMessage,提供的函数将用作属性vm.reverseMessage * 的getter * */ computed: { // 计算属性的 getter reversedMessage: function () { // `this` 指向 vm 实例 return this.message.split('').reverse().join('') } } }) </script>--> <!-- <div id="app"> <input type="number" v-model="a"> <input type="number" v-model="b"> <br> {{total}} </div> <script> new Vue({ el: "#app", data() { return { a: 1, b: 4 }; }, computed: { total(){ return this.a + this.b; } }, methods: {} }) </script> --> <!-- computed属性默认只有getter,不过需要时可以提供一个setter --> <div id="app"> <p>{{site}}</p> </div> <script> var vm = new Vue({ el: '#app', data: { name: 'Google', url: 'http://www.google.com' }, computed: { site: { //getter get: function (){ return this.name + ' ' + this.url }, //setter set: function (newValue){ var names = newValue.split(' ') this.name = names[0] this.url = names[names.length - 1] } } } }) //调用setter,vm.name和vm.url也会被对应更新 vm.site = '菜鸟教程 http://www.runoob.com'; document.write('name: ' + vm.name); document.write('<br>'); document.write('url: ' + vm.url); </script> </body> </html>
监听属性watch
deep:true 开启深层属性监听,默认为 false 不监听
Vue 是可以监听到 多层级数据改变的,且可以在页面上做出对应展示。但是 Vue 提供的 watch 方法,默认是不提供 深度监听的( deep 默认为 false,也就是不开启深度监听)
<!-- Vue-Watch-deep深度监听 --> <!--<div id="root"> {{numbers.a}} <button @click='numbers.a++'>a++</button> <br><br><br> {{numbers.b}} <button @click='numbers.b++'>b++</button> </div> <!– 1.监听对象内部属性变化:当只改变a的时候,只监听a的变化 –> <script> const vm = new Vue({ el: '#root', data() { return { numbers: { a: 1, b: 1 } } }, watch: { a: { handler(newValue, oldValue) { console.log(newValue, oldValue) console.log('numbers正在被侦听') }, // deep: true, // immediate: true } } }) </script>--> <!-- 结论:由此得出:当存在多层属性嵌套时,直接监听内层属性时无法做到的。 因为此时vm上存在的只有data内的一级属性,外加计算属性,data内层属性是 observe 取的 --> <!-- 2.监听对象内部属性变化:只改变a值的时候,通过最外层的属性,监听到内部改变的属性--> <!--<script> const vm = new Vue({ el: '#root', data() { return { numbers: { a: 1, b: 1 } } }, // 监听对象内部属性变化:只改变a值的时候,通过最外层的属性,监听到内部改变的属性 watch: { 'numbers.a': { handler(newValue, oldValue) { console.log(newValue, oldValue) console.log('numbers正在被侦听') }, deep: true, // immediate: true } } }) </script> <!– 结论:无论是否开启deep:true,只要改变了a值,都会触发监听动作。但是改变了b之后,是不会触发监听动作的 –>--> <!-- 3.监听整个 numbers 中 每个属性的变化 --> <!--<script> const vm = new Vue({ el: '#root', data() { return { numbers: { a: 1, b: 1 } } }, // 监听整个numbers中的每个属性变化 watch: { 'numbers.a': { handler(newValue, oldValue) { console.log(newValue, oldValue) console.log('numbers.a正在被侦听') }, }, 'numbers.b': { handler(newValue, oldValue) { console.log(newValue, oldValue) console.log('numbers.b正在被侦听') }, } } }) </script>--> <!-- 结论:事实证明可行的,可以监听到内部属性,但是属性多的时候,太冗余 --> <!-- 4.直接监听整个numbers属性的变化 --> <!--<script> const vm = new Vue({ el: '#root', data() { return { numbers: { a: 1, b: 1 } } }, watch: { numbers: { handler(newValue, oldValue) { console.log(newValue, oldValue) console.log('numbers正在被侦听') }, }, } }) </script>--> <!-- 结果:即使 numbers 内部的 a、b 都已经改变了,但是并未监听到 numbers 的改变。 原因:vue 此时监视的是 numbers 对象属性的 内存地址,只要内存地址不改变,则不会监听 numbers 的改变 --> <!-- 5.配置deep:true后 --> <div id="root"> {{numbers.a}} <button @click='numbers.a++'>a++</button> <br><br><br> {{numbers.b}} <button @click='numbers.b++'>b++</button> </div> <script> Vue.config.productionTip = false const vm = new Vue({ el: '#root', data() { return { numbers: { a: 1, b: 1 } } }, watch: { numbers: { handler(newValue, oldValue) { console.log(newValue, oldValue) console.log('numbers正在被侦听') }, deep: true }, } }) </script> <!-- 结果:能看到两个属性都发生了改变,且控制台上输出了两次监听信息, 这就说明了,配置 deep:true 之后,在改变内部属性之后,vue 也是能监听到的 --> <!-- vue 确实是能自动监听到 多层级的内部属性的改变的。但是 watch 内部监听的函数没有执行 --> <!--vue还是是能监听到内部属性的改变的,且一旦开启了 deep:true 之后, 在 watch 中 监听的多级属性在 内部属性 改变之后,也能被 watch 监听到了。-->
<!-- Vue-Watch-deep深度监听 --> <!--<div id="root"> {{numbers.a}} <button @click='numbers.a++'>a++</button> <br><br><br> {{numbers.b}} <button @click='numbers.b++'>b++</button> </div> <!– 1.监听对象内部属性变化:当只改变a的时候,只监听a的变化 –> <script> const vm = new Vue({ el: '#root', data() { return { numbers: { a: 1, b: 1 } } }, watch: { a: { handler(newValue, oldValue) { console.log(newValue, oldValue) console.log('numbers正在被侦听') }, // deep: true, // immediate: true } } }) </script>--> <!-- 结论:由此得出:当存在多层属性嵌套时,直接监听内层属性时无法做到的。 因为此时vm上存在的只有data内的一级属性,外加计算属性,data内层属性是 observe 取的 --> <!--<script> const vm = new Vue({ el: '#root', data() { return { numbers: { a: 1, b: 1 } } }, // 监听对象内部属性变化:只改变a值的时候,通过最外层的属性,监听到内部改变的属性 watch: { 'numbers.a': { handler(newValue, oldValue) { console.log(newValue, oldValue) console.log('numbers正在被侦听') }, deep: true, // immediate: true } } }) </script> <!– 结论:无论是否开启deep:true,只要改变了a值,都会触发监听动作。但是改变了b之后,是不会触发监听动作的 –>--> <!-- 监听整个 numbers 中 每个属性的变化 --> <!--<script> const vm = new Vue({ el: '#root', data() { return { numbers: { a: 1, b: 1 } } }, // 监听整个numbers中的每个属性变化 watch: { 'numbers.a': { handler(newValue, oldValue) { console.log(newValue, oldValue) console.log('numbers.a正在被侦听') }, }, 'numbers.b': { handler(newValue, oldValue) { console.log(newValue, oldValue) console.log('numbers.b正在被侦听') }, } } }) </script>--> <!-- 结论:事实证明可行的,可以监听到内部属性,但是属性多的时候,太冗余 --> <!-- 直接监听整个numbers属性的变化 --> <!--<script> const vm = new Vue({ el: '#root', data() { return { numbers: { a: 1, b: 1 } } }, watch: { numbers: { handler(newValue, oldValue) { console.log(newValue, oldValue) console.log('numbers正在被侦听') }, }, } }) </script>--> <!-- 结果:即使 numbers 内部的 a、b 都已经改变了,但是并未监听到 numbers 的改变。 原因:vue 此时监视的是 numbers 对象属性的 内存地址,只要内存地址不改变,则不会监听 numbers 的改变 --> <!-- 配置deep:true后 --> <div id="root"> {{numbers.a}} <button @click='numbers.a++'>a++</button> <br><br><br> {{numbers.b}} <button @click='numbers.b++'>b++</button> </div> <script> Vue.config.productionTip = false const vm = new Vue({ el: '#root', data() { return { numbers: { a: 1, b: 1 } } }, watch: { numbers: { handler(newValue, oldValue) { console.log(newValue, oldValue) console.log('numbers正在被侦听') }, deep: true }, } }) </script> <!-- 结果:能看到两个属性都发生了改变,且控制台上输出了两次监听信息, 这就说明了,配置 deep:true 之后,在改变内部属性之后,vue 也是能监听到的 --> <!-- vue 确实是能自动监听到 多层级的内部属性的改变的。但是 watch 内部监听的函数没有执行 --> <!--vue还是是能监听到内部属性的改变的,且一旦开启了 deep:true 之后, 在 watch 中 监听的多级属性在 内部属性 改变之后,也能被 watch 监听到了。--> </body> </html>
Vue-watch-deep 深度监听_vue watch deep_白桃味稠鱼烧的博客-CSDN博客
Vue组件
全局组件
注册一个简单的全局组件runoob,并使用它;
<!--<div id="app"> <Runoob></Runoob> </div> <script> //注册 Vue.component('runoob',{ template: '<h1>自定义组件!</h1>>' }) new Vue({ el: '#app' }) </script>
局部组件
<div id="app"> <runoob></runoob> </div> <script> var Child = { template: '<h1>自定义组件!</h1>>' } //创建根实例 new Vue({ el: '#app', components: { // <runoob>将只在父模板可用 'runoob': Child } }) </script>
Prop
<div id="app"> <child message="hello!"></child> </div> <script> Vue.component('child',{ // 声明 props props: ['message'], // 同样也可以在 vm 实例中像 "this.message" 这样使用 template: '<span>{{ message }}</span>' }) //创建根实例 new Vue({ el: '#app' }) </script>
prop是子组件用来接受父组件传递过来的数据的一个自定义属性
父组件的数据需要通过该props把数据传给子组件子组件需要显式地用 props 选项声明 "prop";
动态Props
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。 每当父组件的数据变化时,该变化也会传导给子组件:
<div id="app"> <div> <input v-model="parentMsg"> <br> <child v-bind:message="parentMsg"></child> </div> </div> <script> // 注册 Vue.component('child', { // 声明 props props: ['message'], // 同样也可以在 vm 实例中像 "this.message" 这样使用 template: '<span>{{ message }}</span>' }) // 创建根实例 new Vue({ el: '#app', data: { parentMsg: '父组件内容' } }) </script>
<!-- 实例需求:使用v-bind指令将todo传到每一个重复的组件中 注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。 --> <!--<div id="app"> <ol> <todo-item v-for="item in sites" v-bind:todo="item"></todo-item> </ol> </div> <script> Vue.component('todo-item', { props: ['todo'], template: '<li>{{ todo.text }}</li>' }) new Vue({ el: '#app', data: { sites: [ { text: 'Runoob' }, { text: 'Google' }, { text: 'Taobao' } ] } }) </script>-->
Prop验证
Vue.component('my-component', { props: { // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证) propA: Number, // 多个可能的类型 propB: [String, Number], // 必填的字符串 propC: { type: String, required: true }, // 带有默认值的数字 propD: { type: Number, default: 100 }, // 带有默认值的对象 propE: { type: Object, // 对象或数组默认值必须从一个工厂函数获取 default: function () { return { message: 'hello' } } }, // 自定义验证函数 propF: { validator: function (value) { // 这个值必须匹配下列字符串中的一个 return ['success', 'warning', 'danger'].indexOf(value) !== -1 } } } })
自定义事件
<!-- 自定义事件产生原因:父组件是使用props传递数据给子组件,但如果子组件要把数据传递回去,则需要使用自定义事件 以下实例:使用v-on绑定自定义事件,每个Vue实例都实现了事件接口,即: · 使用$on(eventName)监听事件 父组件监听 · 使用$emit(eventName)触发事件 子组件触发 父组件可以在使用子组件的地方直接用v-on来监听子组件的事件 --> <div id="app"> <div id="counter-event-example"> <p>{{ total }}</p> <button-counter v-on:increment="incrementTotal"></button-counter> <button-counter v-on:increment="incrementTotal"></button-counter> </div> </div> <script> Vue.component('button-counter', { template: '<button v-on:click="incrementHandler">{{ counter }}</button>', data: function () { return { counter: 0 } }, methods: { incrementHandler: function () { this.counter += 1 this.$emit('increment') //绑定的是触发事件,对组件的触发事件进行绑定 } }, }) new Vue({ el: '#counter-event-example', data: { total: 0 }, methods: { incrementTotal: function () { this.total += 1 } } }) </script>
data必须是一个函数
<!-- data必须是一个函数 观察下面代码发现:data是一个函数的话组件相互不影响,而是对象的话,会影响 这样的好处就是每个实例可以维护一份被返回对象的独立的拷贝,如果 data 是一个对象则会影响到其他实例 --> <div id="components-demo3" class="demo"> <button-counter2></button-counter2> <button-counter2></button-counter2> <button-counter2></button-counter2> </div> <script> var buttonCounter2Data = { count: 0 } Vue.component('button-counter2', { data: function () { // data 选项是一个函数,组件不相互影响 return { count: 0 } }, /* data: function () { // data 选项是一个对象,会影响到其他实例 return buttonCounter2Data },*/ template: '<button v-on:click="count++">点击了 {{ count }} 次。</button>' }) new Vue({ el: '#components-demo3' }) </script>
Vue7:组件_menglong0329的博客-CSDN博客
钩子函数(生命周期函数)
常用的钩子函数
初始化 | beforeCreate | created |
挂载 | beforeMount | mounted |
更新 | beforeUpdate | updated |
销毁 | beforeDestroy | destroyed |
钩子函数声明的位置:
四类函数都是需要与methods同级声明,并且不可被methods调用,以updated举例:
export default { data () { }, methods: { }, // 钩子函数和 methods 同级声明 updated () { console.log('看到了吗 声明到这个位置'); } }
1.初始化beforeCreate和created
此阶段就是在浏览器初始化data和methods中数据前和后的时间点
beforeCreate 代表的就是 Vue 中 data 和 methods 中定义的数据函数 添加到浏览器之前 这个时间点会触发的函数;
created 代表的就是 Vue 中 data 和 methods 中定义的数据函数 添加到浏览器初始化完毕之后 触发的函数;
这个函数 created 和 mounted 经常用来发初始化ajax请求渲染页面,但是根据每个人的习惯不同,用哪个的都有,我本人而言一般用 created ,除非涉及到获取DOM元素否则很少用 mounted 这是因为 created 的请求更早,打开页面不会出现闪的情况,网页加载更快
new Vue({ data () { return { bl: true } }, methods: { change () { this.bl = !this.bl } }, <!-- Vue内部添加data和method数据前 --> beforeCreate(){ // 在这里 打印的结果是 undefined console.log(this.bl) }, <!-- Vue内部添加data和method数据后 --> created(){ // 在这里 打印的结果是 true console.log(this.bl) } })
2.挂载beforeMount和mounted
这个阶段就是将Vue的数据在内存中渲染为虚拟dom模板, 将这个虚拟DOM模板渲染为真实的页面DOM元素前和后
beforeMount 简单来说,就是内存里的虚拟DOM已经运算完毕,但是还没有渲染到浏览器中,此时还无法看到页面内容,也无法访问DOM元素,用处也不大,如果硬是要访问,会返回 undefined
mounted 这个钩子函数就是 虚拟DOM已经成功渲染到浏览器中了 此时调用mounted 中的内容,这个函数和 created 一样可以用来发送初始化ajax请求
beforeMount 不可以打印 DOM节点 ,mounted 可以,如下实例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script> </head> <body> <div id="app"> <div ref="biaoqian">这是个DOM节点</div> </div> <script> new Vue({ el: '#app', // dom节点 渲染浏览器之前 beforeMount () { console.log('beforeMount 打印结果:',this.$refs.biaoqian); }, // dom节点 渲染浏览器完成 mounted(){ console.log('mounted 打印结果:',this.$refs.biaoqian); } }) </script> </body> </html>
3.beforeUpdate和updated
这个阶段是 页面DOM元素相关的数据更新 时,虚拟DOM更新完毕 和 真实DOM更新完毕后两个时间点 触发 beforeUpdate 和 updated,非DOM相关数据更新不会触发
beforeUpdate 是页面元素相关联的数据在 虚拟DOM层面已经更新完毕 , 但是还 未渲染成真实DOM 这个状态,发生在 虚拟DOM打补丁之前 ,具体就是内存中的更新过程这个时间点会触发这个钩子函数,此时还未渲染到浏览器中DOM
updated 是数据改动完成并且成功重新打补丁渲染完成后调用的钩子函数,发生在改动数据的函数全部执行完毕并渲染到DOM之后,此时获取的数据一定是经过改动 和 beforeUpdate 的最新数据,通过 el 和 ref 获取的DOM层面和数据层面的数据都是最新的,但是最好不要在updated 中改动数据,这样可能会再次触发 beforeUpdate
实例如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script> </head> <body> <div id="app"> <input v-model="text" v-on="text"> <p>{{text}}</p> </div> <script> new Vue({ el: '#app', data () { return { text: '我是还没被改的文字' } }, methods: { // 改动数据事件 change () { this.text = '我被改了' console.log('change事件', this.text); } }, // beforeUpdate 钩子函数 beforeUpdate () { this.text = '我又被改了,我不干净了' console.log('改变时', this.text); }, // updated 钩子函数 updated () { console.log('改变之后', this.text); } }) </script> </body> </html>
4.beforeDestroy和destroyed
beforeDestroy 和 destroyed用法如上一样,只不过他的触发时机是 Vue实例销毁的前后,destroyed用处多用于 清除定时器和 清空localstorage中的数据,beforeDestroy用的不多