Vue.js学习(一)

一.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的详细学习:

V-bind详细使用_CaseyWei的博客-CSDN博客

<!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">
  &lt;!&ndash; checkbox单选框应用 &ndash;&gt;
  <label><input type="checkbox" v-model="isAgree">同意协议</label>
  <h2>您选择的是:{{isAgree}}</h2>
  &lt;!&ndash; disabled 关闭 &ndash;&gt;
  <button :disabled="!isAgree">下一步</button>
</div>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好',
      isAgree: false
    }
  })
</script>
-->
<!--<div id="app">
  &lt;!&ndash; checkbox多选框应用 &ndash;&gt;
  <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">
  &lt;!&ndash; 1.单选 &ndash;&gt;
  <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">
  &lt;!&ndash; 2.多选 &ndash;&gt;
  <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>
&lt;!&ndash; 1.监听对象内部属性变化:当只改变a的时候,只监听a的变化 &ndash;&gt;

<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>
&lt;!&ndash;
结论:无论是否开启deep:true,只要改变了a值,都会触发监听动作。但是改变了b之后,是不会触发监听动作的
&ndash;&gt;-->

<!-- 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>
&lt;!&ndash; 1.监听对象内部属性变化:当只改变a的时候,只监听a的变化 &ndash;&gt;

<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>
&lt;!&ndash;
结论:无论是否开启deep:true,只要改变了a值,都会触发监听动作。但是改变了b之后,是不会触发监听动作的
&ndash;&gt;-->

<!-- 监听整个 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博客

钩子函数(生命周期函数)

常用的钩子函数

初始化beforeCreatecreated
挂载beforeMountmounted
更新beforeUpdateupdated
销毁beforeDestroydestroyed

钩子函数声明的位置:

四类函数都是需要与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用的不多

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值