vue教程

v

  • 创建一个vue实例
  • 插值表达式{{}}
  • vue响应式特性
  • vue指令
    • v-if vs. v-show 指令
    • v-else-if 指令
    • v-on指令 注册监听
      • 内联语句
      • methods中的函数名![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/8b9d81539ba74e6691b27694813e0f65.png)
      • v-on 调用传参
    • v-bind 动态的设置html标签
    • v-for指令 基于数据循环
      • v-for中的key
      • v-model 表单绑定
  • 指令修饰符
  • v-bind对于样式控制的增强
  • v-model应用于其他表单元素
  • 计算属性
  • computed 计算属性 VS methods方法
  • 计算属性的完整写法
  • watch 监听器
  • watch完整写法
  • VUE的生命周期和生命周期的四个阶段
    • created应用新闻迭代
    • 输入框获取焦点
  • 工程化开发&脚手架vue CLI
    • 组件化开发&根组件
  • 局部注册
  • 全局注册组件
  • 组件样式冲突scoped
  • data是一个函数
  • 组件通信
    • 父传子用props方式
    • 子传父
  • prop校验
    • 类型校验
  • 非父子通信-事件总线
  • 非父子通宵扩展-provide-inject
  • v-model原理
  • 表单类组件封装&v-model简化代码
  • sync修饰符
  • ref和refs获取dom和组件
  • vue异步更新 nextTick
  • Vue 自定义指令-基础语法
  • 自定义指令-封装v-loading
  • 插槽-默认插槽
  • 插槽-后备内容
  • 具名插槽
  • 作用域插槽
  • 组件标签封装-my-tag
  • 单页应用&路由
  • 路由的使用
  • 组件存放
  • 路由封装抽离

创建一个vue实例

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue 实例</title>
    <!-- 引入 Vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <!--
        创建vue容器初始化渲染
        1.准备容器
        2.引包(vue的js包) 
        3.创建实例
        4.添加配置项 完成渲染
    -->
    <div id="app">
        <!--这将来会编写一些用于渲染的代码逻辑-->
        {{msg}}
    </div>
    <!-- 创建实例 -->
    <script>
        //引入了vuejs的核心包,在全局环境下,就有了vue构造函数
        const app =new Vue(
            //通过el配置选择器指定了vue管理的是那个盒子
            //#app就指定管理了上面app的那个盒子
            {
                el:'#app',
                //通过data提供数据进行渲染
                data:{
                    msg:"hello vue"
                }

            }
        )
    </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>Vue 实例</title>
    <!-- 引入 Vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <!--
        创建vue容器初始化渲染
        1.准备容器
        2.引包(vue的js包) 
        3.创建实例
        4.添加配置项 完成渲染
    -->
    <div id="app">
        <!--这将来会编写一些用于渲染的代码逻辑-->
        {{msg.toUpperCase()}}
        {{msg.toUpperCase()+"你好啊"}}
        <h1>{{msg}}</h1>
    </div>
    <!-- 创建实例 -->
    <script>
        //引入了vuejs的核心包,在全局环境下,就有了vue构造函数
        const app =new Vue(
            //通过el配置选择器指定了vue管理的是那个盒子
            //#app就指定管理了上面app的那个盒子
            {
                el:'#app',
                //通过data提供数据进行渲染
                data:{
                    msg:"hello word"
                }

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

vue响应式特性

在这里插入图片描述

        //引入了vuejs的核心包,在全局环境下,就有了vue构造函数
        const app =new Vue(
            //通过el配置选择器指定了vue管理的是那个盒子
            //#app就指定管理了上面app的那个盒子
            {
                el:'#app',
                //通过data提供数据进行渲染
                data:{
                    //响应式数据》数据变化后视图会自动更新
                    msg:"你好,响应式"
                }
                //data中的数据是会被添加到实例上。
                //1.实例.属性名
                //2.实例.属性名=新值
            }
        )

一旦数据变化数据也会变化。

vue指令

在这里插入图片描述
具体指令查看:https://cn.vuejs.org/api/built-in-directives.html#built-in-directives
例如v-html这个指令。
v-html 的内容直接作为普通 HTML 插入
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue 实例</title>
    <!-- 引入 Vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <!--
        创建vue容器初始化渲染
        1.准备容器
        2.引包(vue的js包) 
        3.创建实例
        4.添加配置项 完成渲染
    -->
    <div id="app">
        <div v-html="msg"></div>
    </div>
    <!-- 创建实例 -->
    <script>
        //引入了vuejs的核心包,在全局环境下,就有了vue构造函数
        const app =new Vue(
            //通过el配置选择器指定了vue管理的是那个盒子
            //#app就指定管理了上面app的那个盒子
            {
                el:'#app',
                //通过data提供数据进行渲染
                data:{
                    //响应式数据》数据变化后视图会自动更新
                    msg:"<a href='http://ww.baidu.com'>百度</a>"
                }
                //data中的数据是会被添加到实例上。
                //1.实例.属性名
                //2.实例.属性名=新值
            }
        )
    </script>
</body>
</html>

v-if vs. v-show 指令

v-if 是“真实的”按条件渲染,因为它确保了在切换时,条件区块内的事件监听器和子组件都会被销毁与重建。

v-if 也是惰性的:如果在初次渲染时条件值为 false,则不会做任何事。条件区块只有当条件首次变为 true 时才被渲染。

相比之下,v-show 简单许多,元素无论初始条件如何,始终会被渲染,只有 CSS display 属性会被切换。

总的来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要频繁切换,则使用 v-show
较好;如果在运行时绑定条件很少改变,则 v-if 会更合适。

在这里插入图片描述

show是通过css来控制隐藏,if是通过判断条件控制元素的创建和移除

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue 实例</title>
    <!-- 引入 Vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <h1 v-show="msg">Hello!</h1>
        <h1 v-if="msg">v-if</h1>
    </div>
    <!-- 创建实例 -->
    <script>
        const app =new Vue(
            {
                el:'#app',
  
                data:{
                  
                    msg: true
                }
            }
        )
    </script>
</body>
</html>

v-else-if 指令

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue 实例</title>
    <!-- 引入 Vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <p v-if="gender===1">男</p>
        <p v-else>女</p>
        <hr>
        <p v-if="score>=90">A</p>
        <p v-else-if="score>=70">B</p>
        <p v-else>C</p>
    </div>
    <!-- 创建实例 -->
    <script>
        const app =new Vue(
            {
                el:'#app',
  
                data:{
                    gender: 2,
                    score:80
                }
            }
        )
    </script>
</body>
</html>

v-on指令 注册监听

在这里插入图片描述

内联语句

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue 实例</title>
    <!-- 引入 Vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <button v-on:click="count--">-</button>
        <span>{{count}}</span>
        <!-- 给+号注册点击事件 -->
        <button v-on:click="count++">+</button>
    </div>
    <!-- 创建实例 -->
    <script>
        const app =new Vue(
            {
                el:'#app',
  
                data:{
                    count:100
                }
            }
        )
    </script>
</body>
</html>

或者用@click注册

        <button @click="count++">+</button>

methods中的函数名在这里插入图片描述

methods中用来提供方法。
实现隐藏方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue 实例</title>
    <!-- 引入 Vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <button @click="fun">显示隐藏</button>
        <h1 v-show="isshow">测试</h1>
    </div>
    <!-- 创建实例 -->
    <script>
        const app =new Vue(
            {
                el:'#app',
  
                data:{
                    isshow:true
                },
                methods:{
                    fun(){
                        app.isshow=!app.isshow;      
                    }
                }
            }
        )
    </script>
</body>
</html>

v-on 调用传参

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue 实例</title>
    <!-- 引入 Vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <button @click="fun(5)">减5 </button>
        <button @click="fun(10)">减10 </button>
        <p>当前数值:{{number}}</p>
    </div>
    <!-- 创建实例 -->
    <script>
        const app =new Vue(
            {
                el:'#app',
                data:{
                    number: 100
                },
                methods:{
                    fun(number){
                        this.number-=number;
                    }
                }
            }
        )
    </script>
</body>
</html>

v-bind 动态的设置html标签

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue 实例</title>
    <!-- 引入 Vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
       <img v-bind:src="imgUrl">
    </div>
    <!-- 创建实例 -->
    <script>
        const app =new Vue(
            {
                el:'#app',
                data:{
                    imgUrl: "./omg/10.png "
                }
            }
        )
    </script>
</body>
</html>

简写

<div id="app">
   <img :src="imgUrl">
</div>

v-for指令 基于数据循环

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue 实例</title>
    <!-- 引入 Vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <ul>
            <li v-for="(item,index) in list">
                {{item}} - {{index}}
            </li>
        </ul>
    </div>
    <!-- 创建实例 -->
    <script>
        const app =new Vue(
            {
                el:'#app',
                data:{
                    list: ['1','2','3']
                }
            }
        )
    </script>
</body>
</html>

v-for中的key

在这里插入图片描述
在这里插入图片描述

v-model 表单绑定

在这里插入图片描述

数据变化:视图自动你更新 视图变化:数据自动更新

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue 实例</title>
    <!-- 引入 Vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        账户:<input v-model="username"><br>
        密码:<input v-model="password"><br>
        <button @click="login">登陆</button>
    </div>
    <!-- 创建实例 -->
    <script>
        const app =new Vue(
            {
                el:'#app',
                data:{
                    username:'',
                    password:''
                },
                methods:{
                    login(){
                        console.log(this.username,this.password)
                    }
                }
            }
        )
    </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>Vue 实例</title>
    <!-- 引入 Vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <!-- 绑定键盘回车事件 -->
    <input @keyup.enter="fn" v-model="username" type="text">
    </div>
    <!-- 创建实例 -->
    <script>
        const app =new Vue(
            {
                el:'#app',
                data:{
                    username:''
                },
                methods:{
                    fn(){
                        console.log(this.username)
                    }
                }
            }
        )
    </script>
</body>
</html>

v-bind对于样式控制的增强

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue 实例</title>
    <!-- 引入 Vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
    <style>
        .active{
            color: red;
        }
    </style>
</head>

<body>
    <div id="app">
        <ul>
            <li v-for="(item,index) in list" :key="item.id" @click="activeIndex = index">
            //通过{active: index === activeIndex}"实现动态控制
                <a :class="{active: index === activeIndex}" href="#">{{item.name}}</a>

            </li>
        </ul>
    </div>
    <!-- 创建实例 -->
    <script>
        const app =new Vue(
            {
                el:'#app',
                data:{
                    activeIndex:0,//记录高亮
                    list:[
                        {id:1,name:'京东秒杀'},
                        {id:2,name:'每日特价'},
                        {id:3,name:'品类秒杀'},
                    ]
                }
            }
        )
    </script>
</body>
</html>

:STYLE单独控制某个属性变化
在这里插入图片描述

v-model应用于其他表单元素

在这里插入图片描述

<!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>
  <style>
    textarea {
      display: block;
      width: 240px;
      height: 100px;
      margin: 10px 0;
    }
  </style>
</head>
<body>

  <div id="app">
    <h3>小黑学习网</h3>

    姓名:
      <input type="text" v-model="username"> 
      <br><br>

    是否单身:
      <input type="checkbox" v-model="isSingle"> 
      <br><br>

    <!-- 
      前置理解:
        1. name:  给单选框加上 name 属性 可以分组 → 同一组互相会互斥
        2. value: 给单选框加上 value 属性,用于提交给后台的数据
      结合 Vue 使用 → v-model
    -->
    性别: 
      <input v-model="gender" type="radio" name="gender" value="1">男
      <input v-model="gender" type="radio" name="gender" value="2">女
      <br><br>

    <!-- 
      前置理解:
        1. option 需要设置 value 值,提交给后台
        2. select 的 value 值,关联了选中的 option 的 value 值
      结合 Vue 使用 → v-model
    -->
    所在城市:
      <select v-model="cityId">
        <option value="101">北京</option>
        <option value="102">上海</option>
        <option value="103">成都</option>
        <option value="104">南京</option>
      </select>
      <br><br>

    自我描述:
      <textarea v-model="desc"></textarea> 

    <button>立即注册</button>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        username: '',
        isSingle: false,
        gender: "2",
        cityId: '102',
        desc: ""
      }
    })
  </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>
  <style>
    table {
      border: 1px solid #000;
      text-align: center;
      width: 240px;
    }
    th,td {
      border: 1px solid #000;
    }
    h3 {
      position: relative;
    }
  </style>
</head>
<body>

  <div id="app">
    <h3>小黑的礼物清单</h3>
    <table>
      <tr>
        <th>名字</th>
        <th>数量</th>
      </tr>
      <tr v-for="(item, index) in list" :key="item.id">
        <td>{{ item.name }}</td>
        <td>{{ item.num }}个</td>
      </tr>
    </table>

    <!-- 目标:统计求和,求得礼物总数 -->
    <p>礼物总数:{{ totalCount }} 个</p>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        // 现有的数据
        list: [
          { id: 1, name: '篮球', num: 1 },
          { id: 2, name: '玩具', num: 2 },
          { id: 3, name: '铅笔', num: 5 },
        ]
      },
      computed: {
        totalCount () {
          // 基于现有的数据,编写求值逻辑
          // 计算属性函数内部,可以直接通过 this 访问到 app 实例
          // console.log(this.list)

          // 需求:对 this.list 数组里面的 num 进行求和 → reduce
          let total = this.list.reduce((sum, item) => sum + item.num, 0)
          return total
        }
      }
    })
  </script>
</body>
</html>

computed 计算属性 VS methods方法

计算属性是有缓存的,一旦算出来结果就会立刻缓存
下一次读取》直接读缓存就行》性能特别高

在这里插入图片描述

计算属性的完整写法

在这里插入图片描述

<!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="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>

  <div id="app">
    姓:<input type="text"><br>
    名:<input type="text"><br>
    <p>姓名:{{ fullName }}</p>
    <button>修改姓名</button>
  </div>

  <script>
    const app = new Vue({
      el: '#app',
      data: {
            firsName:"刘",
            lastName:"备",
      },
      computed: {
  fullName: {
    get() {
      return this.firstName + this.lastName;
    }
  }
},
      methods: {
          changeName(){

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

watch 监听器

作用:监视数据变化,执行一些逻辑或异步操作
在这里插入图片描述

<!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>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
        font-size: 18px;
      }
      #app {
        padding: 10px 20px;
      }
      .query {
        margin: 10px 0;
      }
      .box {
        display: flex;
      }
      textarea {
        width: 300px;
        height: 160px;
        font-size: 18px;
        border: 1px solid #dedede;
        outline: none;
        resize: none;
        padding: 10px;
      }
      textarea:hover {
        border: 1px solid #1589f5;
      }
      .transbox {
        width: 300px;
        height: 160px;
        background-color: #f0f0f0;
        padding: 10px;
        border: none;
      }
      .tip-box {
        width: 300px;
        height: 25px;
        line-height: 25px;
        display: flex;
      }
      .tip-box span {
        flex: 1;
        text-align: center;
      }
      .query span {
        font-size: 18px;
      }

      .input-wrap {
        position: relative;
      }
      .input-wrap span {
        position: absolute;
        right: 15px;
        bottom: 15px;
        font-size: 12px;
      }
      .input-wrap i {
        font-size: 20px;
        font-style: normal;
      }
    </style>
        <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>

  </head>
  <body>
    <div id="app">
      <!-- 条件选择框 -->
      <div class="query">
        <span>翻译成的语言:</span>
        <select>
          <option value="italy">意大利</option>
          <option value="english">英语</option>
          <option value="german">德语</option>
        </select>
      </div>

      <!-- 翻译框 -->
      <div class="box">
        <div class="input-wrap">
          <textarea v-model="obj.words"></textarea>
          <span><i>⌨️</i>文档翻译</span>
        </div>
        <div class="output-wrap">
          <div class="transbox">mela</div>
        </div>
      </div>
    </div>

    <script>
      // 接口地址:https://applet-base-api-t.itheima.net/api/translate
      // 请求方式:get
      // 请求参数:
      // (1)words:需要被翻译的文本(必传)
      // (2)lang: 需要被翻译成的语言(可选)默认值-意大利
      // -----------------------------------------------
      
      const app = new Vue({
        el: '#app',
        data: {
          words: '',
        },
        // 具体讲解:(1) watch语法 (2) 具体业务实现
       watch:{
        //该方法会在数据变化的时候执行
        'obj.words'(newValue,oldValue){
          console.log("变化了",newValue,oldValue)
        }
       }
       
      })
    </script>
  </body>
</html>

watch完整写法

在这里插入图片描述
在这里插入图片描述

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="app">
    <h3>{{ title }}</h3>
    <div>
      <button @click="count--">-</button>
      <span>{{ count }}</span>
      <button @click="count++">+</button>
    </div>
  </div>
  <script src="./vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        count: 100,
        title: '计数器'
      },
      //1.创建阶段
      beforeCreate(){
        console.log("响应数据准备好之前")
      },
      created(){
        console.log("响应数据准备好之后")
      },
       //2.挂载阶段
       beforeMount(){
        console.log("模板渲染之前")
       },
       mounted(){
        console.log("模板渲染之后")
       },
       //3.更新阶段(修改数据》更新视图
       beforeUpdatre(){
        console.log("数据修改了视图还没有更新");
       },
       updated(){
        console.log('update数据修改,视图已经更新了')
       },
       //4.卸载阶段
       beforeDestroy(){
        console.log('卸载前')
       },
       destroyed(){
        console.log("卸载后")
       }
    })
  </script>
</body>

</html>

created应用新闻迭代

<!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>
  <style>
    * {
      margin: 0;
      padding: 0;
      list-style: none;
    }
    .news {
      display: flex;
      height: 120px;
      width: 600px;
      margin: 0 auto;
      padding: 20px 0;
      cursor: pointer;
    }
    .news .left {
      flex: 1;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      padding-right: 10px;
    }
    .news .left .title {
      font-size: 20px;
    }
    .news .left .info {
      color: #999999;
    }
    .news .left .info span {
      margin-right: 20px;
    }
    .news .right {
      width: 160px;
      height: 120px;
    }
    .news .right img {
      width: 100%;
      height: 100%;
      object-fit: cover;
    }
  </style>
</head>
<body>

  <div id="app">
    <ul>
      <li  v-for="(item,index) in list" :key="item.id" class="news">
        <div class="left">
          <div class="title">{{item.title}}</div>
          <div class="info">
            <span>{{item.source}}</span>
            <span>{{item.time}}</span>
          </div>
        </div>
        <div class="right">
          <img :src="item.img" alt="">
        </div>
      </li>
    </ul>
  </div>
  <script src="./vue.js"></script>
  <script src="./axios.js"></script>
  <script>
    // 接口地址:http://hmajax.itheima.net/api/news
    // 请求方式:get
    const app = new Vue({
      el: '#app',
      data: {
        list:[]
      },
      async created(){
        //进入页面立即发送请求
        const res = await axios.get('http://hmajax.itheima.net/api/news');
        console.log(res)
        //将数据更新到data中的list
        this.list=res.data.data
      }
    })
  </script>
</body>
</html>

输入框获取焦点


<!DOCTYPE html>
<html lang="zh-CN">

<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>示例-获取焦点</title>
  <!-- 初始化样式 -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reset.css@2.0.2/reset.min.css">
  <!-- 核心样式 -->
  <style>
    html,
    body {
      height: 100%;
    }
    .search-container {
      position: absolute;
      top: 30%;
      left: 50%;
      transform: translate(-50%, -50%);
      text-align: center;
    }
    .search-container .search-box {
      display: flex;
    }
    .search-container img {
      margin-bottom: 30px;
    }
    .search-container .search-box input {
      width: 512px;
      height: 16px;
      padding: 12px 16px;
      font-size: 16px;
      margin: 0;
      vertical-align: top;
      outline: 0;
      box-shadow: none;
      border-radius: 10px 0 0 10px;
      border: 2px solid #c4c7ce;
      background: #fff;
      color: #222;
      overflow: hidden;
      box-sizing: content-box;
      -webkit-tap-highlight-color: transparent;
    }
    .search-container .search-box button {
      cursor: pointer;
      width: 112px;
      height: 44px;
      line-height: 41px;
      line-height: 42px;
      background-color: #ad2a27;
      border-radius: 0 10px 10px 0;
      font-size: 17px;
      box-shadow: none;
      font-weight: 400;
      border: 0;
      outline: 0;
      letter-spacing: normal;
      color: white;
    }
    body {
      background: no-repeat center /cover;
      background-color: #edf0f5;
    }
  </style>
</head>

<body>
<div class="container" id="app">
  <div class="search-container">
    <img src="https://www.itheima.com/images/logo.png" alt="">
    <div class="search-box">
      <input type="text" v-model="words" id="inp">
      <button>搜索一下</button>
    </div>
  </div>
</div>

<script src="./vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      words: ''
    },
    //等输入框渲染完成,输入框获取焦点
    mounted(){
      document.querySelector("#inp").focus()
    }
  })
</script>

</body>

</html>

工程化开发&脚手架vue CLI

在这里插入图片描述
在这里插入图片描述

组件化开发&根组件

在这里插入图片描述

局部注册

在这里插入图片描述
在这里插入图片描述
新建components局部文件夹,在里面编写局部组件
在这里插入图片描述
编写一个头部局部组件

<template>
  <div class="hm-header">
    我是header
  </div>
</template>

<script>
export default {

}
</script>

<style>
    .hm-header{
        height: 100px;
        line-height: 100px;
        text-align:center;
        font-size: 30px;
    }
</style>

然后引入局部组件使用

<template>
  <div class="App">
    <!-- 头部组件 -->
    <HmHeader></HmHeader>
    <!-- 主体组件 -->
    <!-- 底部组件 -->
  </div>
</template>

<script>
import HmHeader from './components/HmHeader.vue';
export default {
  // 使用变量
  components:{
    // 组件名:组件对象
    HmHeader:HmHeader
  }
}
</script>

<style>
  .App{
    width: 600px;
    height: 700px;
    background-color: aqua;
    margin:0 auto;
    padding:1 ;
  }
</style>

全局注册组件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在main.JS进行全局注册

// 导入全局组件
import HmButton from './components/HmButton.vue';
Vue.config.productionTip = false
// 进行全局注册
Vue.component('HmButton',HmButton)

直接引入

<template>
    <div class="hm-header">
      我是header
      <HmButton></HmButton>
    </div>
  </template>

组件样式冲突scoped

在这里插入图片描述
在这里插入图片描述
默认的style样式会作用到全局,如果不想影响全局加上scoped属性,这样只会作用于当前组件。

data是一个函数

在这里插入图片描述

组件通信

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

父传子用props方式

<template>
  <div class="app" style="border: 3px solid #000; margin: 10px">
    我是APP组件
    <!-- 1.给组件标签,添加属性方式 赋值 -->
    <Son :title="myTitle"></Son>
  </div>
</template>

<script>
import Son from "./components/Son.vue"
export default {
  name: "App",
  components: {
    Son,
  },
  data() {
    return {
      myTitle: "学前端,就来黑马程序员",
    }
  },
}
</script>

<style>
</style>
<template>
  <div class="son" style="border:3px solid #000;margin:10px">
    <!-- 3.直接使用props的值 -->
    我是Son组件 
  </div>
</template>

<script>
export default {
  name: 'Son-Child',
  // 2.通过props来接受
  props:['title']
  
}
</script>

<style>

</style>

子传父

在这里插入图片描述

<template>
  <div class="app" style="border: 3px solid #000; margin: 10px">
    我是APP组件
    <!-- 1.给组件标签,添加属性方式 赋值 -->
    <Son :title="myTitle" @changeTitle="handleChange"></Son>
  </div>
</template>

<script>
import Son from "./components/Son.vue"
export default {
  name: "App",
  components: {
    Son,
  },
  data() {
    return {
      myTitle: "学前端,就来黑马程序员",
    }
  },
  methods:{
    //3.提供处理函数
    handleChange(newTitle){
      console.log(newTitle)
    }
  }
}
</script>

<style>
</style>
<template>
  <div class="son" style="border:3px solid #000;margin:10px">
    <!-- 3.直接使用props的值 -->
    我是Son组件 
  </div>
</template>

<script>
export default {
  name: 'Son-Child',
  // 2.通过props来接受
  props:['title'],
  methods:{
      changeFn(){
        //1.通过$emit像父组件传递消息
        this.$emit('changeTitle',"船只教育")
      }
  }
  
}
</script>

<style>

</style>

prop校验

在这里插入图片描述

在这里插入图片描述

<template>
  <div class="base-progress">
    <div class="inner" :style="{ width: w + '%' }">
      <span>{{ w }}%</span>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    //设置校验类型
    w:Number
  }


  // 1.基础写法(类型校验)
  // 2.完整写法(类型、是否必填、默认值、自定义校验)
}
</script>

<style scoped>
.base-progress {
  height: 26px;
  width: 400px;
  border-radius: 15px;
  background-color: #272425;
  border: 3px solid #272425;
  box-sizing: border-box;
  margin-bottom: 30px;
}
.inner {
  position: relative;
  background: #379bff;
  border-radius: 15px;
  height: 25px;
  box-sizing: border-box;
  left: -3px;
  top: -2px;
}
.inner span {
  position: absolute;
  right: 0;
  top: 26px;
}
</style>
<template>
  <div class="app">
    <BaseProgress :w="width"></BaseProgress>
  </div>
</template>

<script>
import BaseProgress from './components/BaseProgress.vue'
export default {
  data() {
    return {
      width: 30,
    }
  },
  components: {
    BaseProgress,
  },
}
</script>

<style>
</style>

类型校验

在这里插入图片描述

非父子通信-事件总线

在这里插入图片描述

创建一个空的总线在这里插入图片描述

A组件监听事件
在这里插入图片描述
B组件监听事件
在这里插入图片描述

非父子通宵扩展-provide-inject

在这里插入图片描述
在这里插入图片描述

v-model原理

在这里插入图片描述
在这里插入图片描述

表单类组件封装&v-model简化代码

在这里插入图片描述

sync修饰符

在这里插入图片描述

ref和refs获取dom和组件

在这里插入图片描述

<template>
  <div class="app">
    <div class="base-chart-box">
      这是一个捣乱的盒子
    </div>
    <BaseChart></BaseChart>
  </div>
</template>

<script>
import BaseChart from './components/BaseChart.vue'
export default {
  components:{
    BaseChart
  }
}
</script>

<style>
.base-chart-box {
  width: 300px;
  height: 200px;
}
</style>
<template>
  <div ref="mychart" class="base-chart-box">子组件</div>
</template>

<script>
import * as echarts from 'echarts'

export default {
  mounted() {
    // 基于准备好的dom,初始化echarts实例
    // document.querySelector 会查找项目中所有的元素
    // $refs只会在当前组件查找盒子
    // var myChart = echarts.init(document.querySelector('.base-chart-box'))
    var myChart = echarts.init(this.$refs.mychart)
    // 绘制图表
    myChart.setOption({
      title: {
        text: 'ECharts 入门示例',
      },
      tooltip: {},
      xAxis: {
        data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
      },
      yAxis: {},
      series: [
        {
          name: '销量',
          type: 'bar',
          data: [5, 20, 36, 10, 10, 20],
        },
      ],
    })
  },
}
</script>

<style scoped>
.base-chart-box {
  width: 400px;
  height: 300px;
  border: 3px solid #000;
  border-radius: 6px;
}
</style>

在这里插入图片描述

vue异步更新 nextTick

在这里插入图片描述
在这里插入图片描述

<template>
  <div class="app">
    <div v-if="isShowEdit">
      <input type="text" v-model="editValue" ref="inp" />
      <button>确认</button>
    </div>
    <div v-else>
      <span>{{ title }}</span>
      <button>编辑</button>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      title: '大标题',
      isShowEdit: false,
      editValue: '',
    }
  },
  methods: {
   handleEdit(){
    //1.显示输入框
    this.isShowEdit =true
    //2.让输入框获取焦点
    this.$nextTick(()=>{
      this.$refs.inp.focus()
    })
   }
  },
}
</script>

<style>
</style>

Vue 自定义指令-基础语法

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

自定义指令-封装v-loading

在这里插入图片描述

插槽-默认插槽

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

插槽-后备内容

在这里插入图片描述
在这里插入图片描述

具名插槽

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一旦起了名字就是具名插槽,需要添加template包裹起来
在这里插入图片描述

作用域插槽

在这里插入图片描述
在这里插入图片描述

<template>
  <div>
    <MyTable :data="list">
      <template #default="obj">
        <button @click="del(obj.row.id)">删除</button>
       </template>
    </MyTable>
    <MyTable :data="list2">
    </MyTable>
  </div>
</template>

<script>
import MyTable from './components/MyTable.vue'
export default {
  data () {
    return {
      list: [
        { id: 1, name: '张小花', age: 18 },
        { id: 2, name: '孙大明', age: 19 },
        { id: 3, name: '刘德忠', age: 17 },
      ],
      list2: [
        { id: 1, name: '赵小云', age: 18 },
        { id: 2, name: '刘蓓蓓', age: 19 },
        { id: 3, name: '姜肖泰', age: 17 },
      ]
    }
  },
  components: {
    MyTable
  }
}
</script>

<template>
  <table class="my-table">
    <thead>
      <tr>
        <th>序号</th>
        <th>姓名</th>
        <th>年纪</th>
        <th>操作</th>
      </tr>
    </thead>
    <tbody v-for="(item,index) in data" :key="item.id">
      <tr>
        <td>1</td>
        <td>小张</td>
        <td>8</td>
        <td>
          <!-- 给slot标签传值 -->
          <slot :row="item"> </slot>
        </td>
      </tr>
    </tbody>
  </table>
</template>

<script>
export default {
  props: {
    data: Array,
  },
}
</script>

<style scoped>
.my-table {
  width: 450px;
  text-align: center;
  border: 1px solid #ccc;
  font-size: 24px;
  margin: 30px auto;
}
.my-table thead {
  background-color: #1f74ff;
  color: #fff;
}
.my-table thead th {
  font-weight: normal;
}
.my-table thead tr {
  line-height: 40px;
}
.my-table th,
.my-table td {
  border-bottom: 1px solid #ccc;
  border-right: 1px solid #ccc;
}
.my-table td:last-child {
  border-right: none;
}
.my-table tr:last-child td {
  border-bottom: none;
}
.my-table button {
  width: 65px;
  height: 35px;
  font-size: 18px;
  border: 1px solid #ccc;
  outline: none;
  border-radius: 3px;
  cursor: pointer;
  background-color: #ffffff;
  margin-left: 5px;
}
</style>

组件标签封装-my-tag

在这里插入图片描述

单页应用&路由

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

路由的使用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

组件存放

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

路由封装抽离

在这里插入图片描述
wwwwwwwwwww

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/407075.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(十一)【Jmeter】线程(Threads(Users))之jp@gc-Ultimate Thread Group

简述 操作路径如下: 作用:提供了高级的线程组控制选项,支持更复杂的场景模拟。配置:设置多种线程控制参数,如启动延迟、启动线程数、并发压测持续时间、关闭线程时间等。使用场景:针对特定需求进行高级的并发访问模拟,如流量控制、延迟启动等。优点:提供了丰富的控制…

HarmonyOS Stage模型 应用配置文件讲解

好&#xff0c;上文 HarmonyOS Stage模型基本概念讲解 中&#xff0c;我们简单讲解了HarmonyOS 中 Stage模型的基本概念 那么 我们继续学习Stage模型的相关知识 上文之后 我们肯定对它的概念和基本结构 有了一个了解 那么 我们就来看一下 基于Stage模型 它里面一些基本的配置文…

算法沉淀——动态规划之斐波那契数列模型(leetcode真题剖析)

算法沉淀——动态规划之斐波那契数列模型 01.第 N 个泰波那契数02.三步问题03.使用最小花费爬楼梯04.解码方法 动态规划&#xff08;Dynamic Programming&#xff0c;简称DP&#xff09;是一种通过将原问题分解为相互重叠的子问题并仅仅解决每个子问题一次&#xff0c;将其解存…

CSRF攻击和防御

CSRF:Cross Site Request Forgery 跨站请求伪造 攻击&#xff1a; 攻击者盗用你的身份&#xff0c;以你的名义发送恶意请求&#xff08;邮件&#xff0c;消息&#xff0c;盗取账号&#xff0c;购买物品&#xff09; GET请求的伪造方式 POST请求的伪造方式 防御&#xff1a…

[c++] 工厂模式 + cyberrt 组件加载器分析

使用对象的时候&#xff0c;可以直接 new 一个&#xff0c;为什么还需要工厂模式 &#xff1f; 工厂模式属于创建型设计模式&#xff0c;将对象的创建和使用进行解耦&#xff0c;对用户隐藏了创建逻辑。 个人感觉上边的表述并没有说清楚为什么需要使用工厂模式。因为使用 new 创…

[面试] 如何保证Redis和MySQL数据一致性?

为什么要在Redis存数据 Redis 用来实现应用和数据库之间读操作的缓存层&#xff0c;主要目的是减少数据 库 IO&#xff0c;还可以提升数据的 IO 性能。 因为Redis基于内存, 查询效率比MySQL快很多, 所以有限查询Redis中的数据,如果Redis没有就查询数据库然后同步到Redis 出…

Vue+SpringBoot打造快递管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 数据中心模块2.2 快递类型模块2.3 快递区域模块2.4 快递货架模块2.5 快递档案模块 三、界面展示3.1 登录注册3.2 快递类型3.3 快递区域3.4 快递货架3.5 快递档案3.6 系统基础模块 四、免责说明 一、摘要 1.1 项目介绍 …

Flink ML 的新特性解析与应用

摘要&#xff1a;本文整理自阿里巴巴算法专家赵伟波&#xff0c;在 Flink Forward Asia 2023 AI特征工程专场的分享。本篇内容主要分为以下四部分&#xff1a; Flink ML 概况在线学习的设计与应用在线推理的设计与应用特征工程算法与应用 一、Flink ML 概况 Flink ML 是 Apache…

MySQL运维实战(7.2) MySQL复制server_id相关问题

作者&#xff1a;俊达 主库server_id没有设置 主库没有设置server_id Got fatal error 1236 from master when reading data from binary log: Misconfigured master - server_id was not set主库查看server_id mysql> show variables like server_id; ----------------…

Spring Boot 笔记 029 用户模块

1.1 用户信息需要在多个链接使用&#xff0c;所以需要用pinia持久化 1.1.1 定义store import {defineStore} from pinia import {ref} from vue const useUserInfoStore defineStore(userInfo,()>{//定义状态相关的内容const info ref({})const setInfo (newInfo)>{i…

基于ElementUI封装省市区四级联动下拉选择

基于ElementUI封装的省市区下拉级联选择 效果 数据 最新省市区JSON数据获取&#xff1a;https://xiangyuecn.github.io/AreaCity-JsSpider-StatsGov/ 参数说明 参数说明inputNumShow下拉框的数量&#xff0c;最多4个defaultAddress默认显示省市区 例&#xff1a;[‘安徽’, …

C语言:指针的进阶讲解

目录 1. 二级指针 1.1 二级指针是什么&#xff1f; 1.2 二级指针的作用 2. 一维数组和二维数组的本质 3. 指针数组 4. 数组指针 5. 函数指针 6. typedef的使用 7. 函数指针数组 7.1 转移表 1. 二级指针 如果了解了一级指针&#xff0c;那二级指针也是可以很好的理解…

Redis(十六)缓存预热+缓存雪崩+缓存击穿+缓存穿透

文章目录 面试题缓存预热缓存雪崩解决方案 缓存穿透解决方案 缓存击穿解决方案案例&#xff1a;高并发聚划算业务 总结表格 面试题 缓存预热、雪崩、穿透、击穿分别是什么?你遇到过那几个情况?缓存预热你是怎么做的?如何避免或者减少缓存雪崩?穿透和击穿有什么区别?他两是…

JDK下载安装

资源展示 安装说明 傻瓜式安装&#xff0c;下一步即可。建议&#xff1a;安装路径不要有中文或者空格等特殊符号。本套课程会同时安装JDK8 和 JDK17&#xff0c;并以JDK17为默认版本进行讲解。 安装步骤 &#xff08;1&#xff09;双击jdk-17_windows-x64_bin.exe文件&#…

免费多域名证书,最多支持保护250个域名

随着企业规模扩大和多元化发展&#xff0c;拥有多个域名的需求变得普遍&#xff0c;此时&#xff0c;多域名SSL证书应运而生&#xff0c;并且这一类型的证书已经发展到能够安全地支持多达250个不同域名的加密需求。 多域名SSL证书&#xff0c;也称为SAN&#xff08;Subject Alt…

RocketMQ生产环境常见问题分析与总结

RocketMQ生产环境常见问题分析与总结 如何保证消息不丢失 消息丢失场景 对于跨网络的节点可能会丢消息&#xff0c;因为MQ存盘都会先写入OS的PageCache中&#xff0c;然后再让OS进行异步刷盘&#xff0c;如果缓存中的数据未及时写入硬盘就会导致消息丢失 生产端到Broker端Brok…

Mybatis总结--传参二

#叫做占位符 Mybatis是封装的JDBC 增强版 内部还是用的jdbc 每遇到一个#号 这里就会变为&#xff1f;占位符 一个#{}就是对应一个问号 一个占位符 用这个对象执行sql语句没有sql注入的风险 八、多个参数-使用Param 当 Dao 接口方法有多个参数&#xff0c;需要通过名称使…

获取图片的颜色的RGB

shiftwins获取截图 然后打开画图软件&#xff0c;ctrlv 然后用吸管工具&#xff0c;吸取 然后编辑颜色&#xff0c;就有

【群智能算法转让】一种新的群智能算法||一种超越隐喻的元启发算法||一种基于数学的群智能算法

1、简介 本次全新出推出一个新的基于种群的元启发算法&#xff0c;基于数学中求解非线性方程组的基本思想而开发的&#xff0c;性能不错 新算法转让Q1 top级&#xff08;一种基于数学的超越隐喻的元启发式算法&#xff09; 新的群智能算法转让&#xff0c;新的元启发式算法转…

NATS学习笔记(一)

NATS是什么&#xff1f; NATS是一个开源的、轻量级、高性能的消息传递系统&#xff0c;它基于发布/订阅模式&#xff0c;由Apcera公司开发和维护。 NATS的功能 发布/订阅&#xff1a;NATS的核心是一个发布/订阅消息传递系统&#xff0c;允许消息生产者发布消息到特定的主题…