vue2.0- vue-cli、vue组件

目录

1. 侦听器

1)watch侦听器

2)使用watch侦听器检测用户名是否可用

3)对象格式的侦听器:immediate选项

5)对象格式的侦听器:deep选项

2. 计算属性

2. Ajax的基础用法

1)axios的基础语法

1⃣️发起GET请求

2⃣️发起POST请求

2)组合async和await调用axios

3)使用解构赋值

4)基于axios.get和axios.post发起请求

4. vue-cli

1)单页面应用程序

2)vue-cli

3)vue项目下src目录的构成

4)vue项目的运行流程

1⃣️main.js

2⃣️App.vue

3⃣️index.html

​​​​​​​4. vue组件

1)组件化开发

2).vue组件的三个组成部分

3)在组件中定义methods方法

4)组件之间的父子关系

5)使用组件的三个步骤

1⃣️通过components注册的是私有子组件

2⃣️注册全局组件

6)组件的props

1⃣️结合v-bind使用自定义属性

2⃣️props是只读的

3⃣️props的default默认值

4⃣️props的type值类型

5⃣️props的required必填项

7) 组件之间的样式冲突问题

1⃣️解决样式冲突 -> scoped属性

2⃣️/deep/样式穿透


1. 侦听器

1)watch侦听器

watch侦听器允许开发者监视数据的变化,从而针对数据的变化做特定的操作

<body>
    <div id="app">
        <input type="text" v-model="username">
    </div>

    <script src="lib/vue-2.6.12.js"></script>
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                username: ''
            },
            watch: {
                //侦听器本质上是一个函数,要监视哪个数据的变化,就把哪个数据名作为方法名即可
                //监听username的变化
                //newVal:变化后的新值,oldVal:变化之前的旧值
                username(newVal, oldVal) {
                    console.log('监听到username发生了变化' + '\t'+ oldVal + '\t' + newVal);
                }
                
            }

        })
    </script>
</body>

结果为:

2)使用watch侦听器检测用户名是否可用

监听username值的变化,并使用axios发起Ajax请求,检测当前输入的用户名是否可用

<body>
    <div id="app">
        <input type="text" v-model="username">
    </div>

    <script src="lib/vue-2.6.12.js"></script>
    <script src="lib/jquery-v3.6.0.js"></script>
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                username: ''
            },
            watch: {
                username(newVal) {
                    if(newVal === '') return
                    //使用axios发起请求,判断用户名是否可用
                    $.get('https://www.escook.cn/api/finduser/' + newVal, function(result) {
                        console.log(result);
                    })
                }
            }

        })
    </script>
</body>

结果为:

3)对象格式的侦听器:immediate选项

方法格式的侦听器:无法在刚进入页面的时候自动触发

对象格式的侦听器:可以通过immediate选项让侦听器自动触发

<body>
    <div id="app">
        <input type="text" v-model="username">
    </div>

    <script src="lib/vue-2.6.12.js"></script>
    <script src="lib/jquery-v3.6.0.js"></script>
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                username: 'admin'
            },
            watch: {
               //对象格式的侦听器
               username: {
                handler(newVal, oldVal) {
                    console.log(newVal + '\t' + oldVal);
                },
                // 通过immediate选项让侦听器自动触发
                immediate: true
               }
            }

        })
    </script>
</body>

结果为:

5)对象格式的侦听器:deep选项

方法格式的侦听器:如果侦听的是一个对象,对象中的属性发生了变化时,不会触发侦听器

对象格式的侦听器:可以通过deep选项,让侦听器深度监听对象中每个属性的变化

<body>
    <div id="app">
        <input type="text" v-model="info.username">
    </div>

    <script src="lib/vue-2.6.12.js"></script>
    <script src="lib/jquery-v3.6.0.js"></script>
    <script>
        const vm = new Vue({
            el: '#app',
            data: {
                info: {
                    username: 'admin'
                }
            },
            watch: {
               //对象格式的侦听器
               info: {
                handler(newVal) {
                    console.log(newVal);
                },
                // 通过deep选项深度监听对象的每个属性
                deep: true
               }

            //如果要侦听的是对象的子属性,可以用单引号包裹
            // 'info.username'(newVal) {
            //     console.log(newVal);
            // }
            }

        })
    </script>
</body>

结果为:

2. 计算属性

计算属性指的是通过一系列运算之后,最终得到一个属性值,这个动态计算出来的属性值可以被模版结构或methods方法使用。

  • 被定义成方法的格式
  • 在使用计算属性的时候,但普通的属性使用即可
  • 实现了代码的复用
  • 只要计算属性中依赖的数据源变化了则计算属性会自动重新求值
  <script src="./lib/vue-2.6.12.js"></script>
  <style>
    .box {
      width: 200px;
      height: 200px;
      border: 1px solid #ccc;
    }
  </style>
</head>

<body>
  <div id="app">
    <div>
      <span>R:</span>
      <input type="text" v-model.number="r">
    </div>
    <div>
      <span>G:</span>
      <input type="text" v-model.number="g">
    </div>
    <div>
      <span>B:</span>
      <input type="text" v-model.number="b">
    </div>
    <hr>

    <!-- 专门用户呈现颜色的 div 盒子 -->
    <!-- 动态绑定一个样式对象,键值对的形式 -->
    <!-- <div class="box" :style="{ backgroundColor: `rgb(${r}, ${g}, ${b})` }">
      {{ `rgb(${r}, ${g}, ${b})` }}
    </div> -->
    <div class="box" :style="{ backgroundColor:rgb }">
      {{ rgb }}
    </div>
    <button @click="show">按钮</button>
  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        // 红色
        r: 0,
        // 绿色
        g: 0,
        // 蓝色
        b: 0
      },
      methods: {
        // 点击按钮,在终端显示最新的颜色
        show() {
          // console.log(`rgb(${this.r}, ${this.g}, ${this.b})`)
          console.log(this.rgb);
        }
      },
      // 计算属性都要放在computed节点下
      computed: {
        rgb() {
          return `rgb(${this.r}, ${this.g}, ${this.b})`
        }
      }
    });
  </script>
</body>

结果为:

2. Ajax的基础用法

1)axios的基础语法

axios是一个专注于网络请求的库。

<body>
    <script src="lib/axios.js"></script>
    <script>
        const result = axios({
            method: 'GET',
            url: 'http://www.liulongbin.top:3006/api/getbooks'
        })
        // 调用axios()方法得到的是Promise对象
        console.log(result);
        //then():请求成功后的回调函数
        // 形参books:请求之后的结果
        result.then(function(books) {
            console.log(books);
            console.log(books.data);
        })
    </script>
</body>

结果为:

1⃣️发起GET请求

<body>
    <script src="lib/axios.js"></script>
    <script>
        axios({
            method: 'GET',
            url: 'http://www.liulongbin.top:3006/api/getbooks',
            // 1.发起GET请求,URL中的查询参数
            params: {
                id: 1
            }
        }).then(function(books) {
            console.log(books.data);
        })
    </script>
</body>

2⃣️发起POST请求

<body>
    <script src="lib/axios.js"></script>
    <script>
        axios({
            method: 'POST',
            url: 'http://www.liulongbin.top:3006/api/getbooks',
            // 2.发起POST请求,请求体参数
            data: {
                name: 'zs',
                age: 20
            }
        }).then(function(books) {
            console.log(books.data);
        })
    </script>
</body>

2)组合async和await调用axios

<body>
    <button id="btnPost">发起post请求</button>
    <script src="lib/axios.js"></script>
        
    <script>
        document.querySelector("#btnPost").addEventListener("click", async function() {
            // axios()方法返回的事Promise对象
            //如果调用某个方法的返回值是await,则前面就可以添加await
            //await只能用在被 async 修饰的方法中
            const res = await axios({
                method: 'POST',
                url: 'http://www.liulongbin.top:3006/api/post',
                data: {
                    name: 'zs',
                    age: 20
                }
            })
            console.log(res);

            
        })
    </script>
</body>

结果为:

3)使用解构赋值

<body>
    <button id="btnPost">发起post请求</button>
    <button id="btnGet">发起get请求</button>
    <script src="lib/axios.js"></script>
        
    <script>
        document.querySelector("#btnPost").addEventListener("click", async function() {
            // axios()方法返回的事Promise对象
            //如果调用某个方法的返回值是await,则前面就可以添加await
            //await只能用在被 async 修饰的方法中
            const res = await axios({
                method: 'POST',
                url: 'http://www.liulongbin.top:3006/api/post',
                data: {
                    name: 'zs',
                    age: 20
                }
            })
            console.log(res);


        })

        document.querySelector("#btnGet").addEventListener("click", async function() {
            // 解构赋值,进行重命名
            //1.从axios封装的大对象中,把data属性解构出来
            //2.把解构出来的data属性,使用 : 进行重命名,一般都是{ data : res }
            const { data : res } = await axios({
                method: 'GET',
                url: 'http://www.liulongbin.top:3006/api/getbooks',
            })
            console.log(res);
            console.log(res.data);
        })
    </script>
</body>

结果为:

4)基于axios.get和axios.post发起请求

<body>
    <button id="btnGet">GET</button>
    <button id="btnPost">POST</button>

    <script src="lib/axios.js"></script>

    <script>
        document.querySelector("#btnGet").addEventListener("click", async function() {
            // axios.get('url', { params:{GET请求体参数} })
            const { data : res} = await axios.get('http://www.liulongbin.top:3006/api/getbooks', {
                params: {
                    id: 1
                }
            })
            console.log(res);
            console.log(res.data);
        })

        document.querySelector("#btnPost").addEventListener("click", async function() {
            // axios.post('url', { POST请求体参数 })
            const { data : res } = await axios.post('http://www.liulongbin.top:3006/api/post', {
                name: 'zs',
                age: 20
            })
            console.log(res);
        })

    </script>

结果为:

4. vue-cli

1)单页面应用程序

单页面应用程序(Single Page Application)简称SPA,指的是一个Web网站中只有唯一的一个HTML页面,所有的功能与交互都在这唯一的一个页面内完成。

2)vue-cli

vue-cli是Vue.js开发的标准工具。它简化了程序员基于webpack创建工程化的Vue项目的过程。

官网:Vue CLI

全局安装:

npm install -g @vue/cli

初始化一个项目:

vue create demo-first

是否使用更快的淘宝镜像,选择 No.

C:\Users\Administrator\Desktop>vue create my_project
?  Your connection to the default npm registry seems to be slow.
   Use https://registry.npm.taobao.org for faster installation? No

使用 Vue create 创建项目是使用默认配置(包含babel, eslint)还是手动选择。

​​​​​​​

手动配置:上下键控制上下,空格进行确定/取消,a 全选。i 反选。

3)vue项目下src目录的构成

  • assets文件夹:存放项目中用到的静态资源文件,例如css样式表、图片资源
  • components文件夹:程序员封装的、可复用的组件
  • main.js:是项目的入口文件,整个项目的运行要先执行main.js
  • App.vue:是项目的根组件

4)vue项目的运行流程

在工程化的项目中,vue要做的事很单纯:通过main.js把App.vue渲染到index.html的指定区域中。其中:

  1. App.vue用来编写待渲染的模版结构
  2. index.html中需要预留一个el区域
  3. main.js把App.vue渲染到了index.html所预留的区域中

1⃣️main.js

// 导入vue包,得到Vue构造函数
import Vue from 'vue'
// 导入App.vue根组件,能够把App.vue中的模版结构渲染到index.html页面中
import App from './App.vue'

// import Test from './Test.vue'

Vue.config.productionTip = false

// 创建Vue的实例对象
new Vue({
  // 把render函数指定的组件,渲染到HTML页面上
  render: h => h(App),
  // render: h => h(Test)
}).$mount('#app')
// $mount():和el属性一样

2⃣️App.vue

<template>
<!-- 会占领index.html中<div id="app"></div>的位置 -->
  <div>
    <h1>App.vue组件</h1>
    <p>aaa</p>
    <p>bbb</p>
  </div>
</template>

3⃣️index.html

<!DOCTYPE html>
<html lang="">
  <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">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

结果为:

​​​​​​​4. vue组件

1)组件化开发

根据封装的思想,把页面上可重用的UI结构封装为组件,从而方便项目的开发和维护。

vue是一个支持组件化开发的前端框架。

vue中规定:组件的后缀名是.vue。eg.App.vue文件本质上就是一个vue组件。

2).vue组件的三个组成部分

  1. template -> 组件的模版结构,只能有一个根节点
  2. script -> 组件的JavaScript行为
  3. style -> 组件的样式,嵌套则<style lang="less"></style>
<template>
<!-- 会占领index.html中<div id="app"></div>的位置 -->
  <div>
    <h1>App.vue组件-- {{ username }}</h1>
    <p>aaa</p>
    <p>bbb</p>
  </div>
</template>

<script>
export default {
  // .vue中的data不能像之前一样指向对象
  // setup() {
  //   data: {
  //   username: 'zs'
  // }
  // },
  //组件中的data必须是一个函数
  data() {
    // return{}:可以定义数据
   return {
     username: 'zs'
   }
  }
}
</script>


<style>
  div {
    background-color: pink;
  }
</style>

结果为:

3)在组件中定义methods方法

<template>
<!-- 会占领index.html中<div id="app"></div>的位置 -->
  <div>
    <h1>App.vue组件-- {{ username }}</h1>
    <p>aaa</p>
    <p>bbb</p>
    <button @click="changeName">修改用户名</button>
  </div>
</template>

<script>
export default {
  // .vue中的data不能像之前一样指向对象
  // setup() {
  //   data: {
  //   username: 'zs'
  // }
  // },
  //组件中的data必须是一个函数
  data() {
    // return{}:可以定义数据
   return {
     username: 'zs'
   }
  },
  methods: {
    changeName() {
      console.log(this);
      this.username = 'ls'
    }
  }
}
</script>


<style>
  div {
    background-color: pink;
  }
</style>

结果为:

4)组件之间的父子关系

 

5)使用组件的三个步骤

  1. 使用import语法导入需要的组件
  2. 使用components节点注册组件
  3. 标签形式使用刚才注册的组件

<template>
  <div class="app-container">
    <h1>App 根组件</h1>
    <hr />

    <div class="box">
      <!-- 渲染 Left 组件和 Right 组件 -->
      <!-- 3. 以标签形式使用刚才注册的组件 -->
      <Left></Left>
      <Right></Right>
    </div>
  </div>
</template>

<script>
  // 1.导入需要使用的.vue组件
  import Left from '@/components/Left.vue'
  import Right from '@/components/Right.vue'
  

  export default {
    // 2.使用components节点注册组件
    components: {
      // Left: 'Left'
      Left,
      Right
    }
  }
</script>

<style lang="less">
.app-container {
  padding: 1px 20px 20px;
  background-color: #efefef;
}
.box {
  display: flex;
}
</style>

结果为:

1⃣️通过components注册的是私有子组件

例如:在组件A的components节点下,注册了组件F,则组件F只能用在组件A中,不能被用在组件C中。

如果要在组件C中使用组件F,则应该在components节点下注册组件F。

2⃣️注册全局组件

在vue项目的main.js入口文件中,通过Vue.component()方法,可以注册全局组件。

//导入需要全局注册的组件
import Count from '@/components/Count.vue'

//参数1:字符串格式,表示组件的注册名称  参数2:需要被全局注册的那个组件
Vue.component('MyCount', Count)

6)组件的props

props是组件的自定义属性,在封装通用组件的时候,合理地使用props可以极大地提高组件的复用性。

1⃣️结合v-bind使用自定义属性

    <!-- init="6":字符串 -> :init="6":js形式,数字 -->
    <MyCount :init="6"></MyCount>

2⃣️props是只读的

vue规定:组件中封装的自定义属性是只读的,程序员不能直接修改props的值,否则会直接报错。

 想要修改props的值,可以把props的值转存到data中,因为data的值都是可读可写的。

    // props是只读的,因此不能直接修改props
    props: ['init'],
    data() {
        return{
            count: this.init
        }
    }

3⃣️props的default默认值

在声明自定义属性时,可以通过default来定义属性的默认值

   export default {
    //props:自定义属性,允许使用者通过自定义属性为当前组件指定初始值
    // props是只读的,因此不能直接修改props
    // props: ['init'],
    props: {
        init: {
            // default来定义属性的默认值
            // 如果外界使用Count组件的时候,没有传递init属性,则默认值生效
            default: 0
            }
        }
    }

4⃣️props的type值类型

在声明自定义属性时,可以通过type来定义属性的值类型。

export default {
    //props:自定义属性,允许使用者通过自定义属性为当前组件指定初始值
    // props是只读的,因此不能直接修改props
    // props: ['init'],
    props: {
        init: {
            // default来定义属性的默认值
            // 如果外界使用Count组件的时候,没有传递init属性,则默认值生效
            default: 0,
            // type来定义属性的值类型
            // 如果传递过来的值不符合此类型,则会在终端报错
            type: Number
        }
    }
}

5⃣️props的required必填项

在声明自定义属性时,可以通过required选项,将属性设置为必填项,强制用户必须传递属性的值。

export default {
    //props:自定义属性,允许使用者通过自定义属性为当前组件指定初始值
    // props是只读的,因此不能直接修改props
    // props: ['init'],
    props: {
        init: {
            // default来定义属性的默认值
            // 如果外界使用Count组件的时候,没有传递init属性,则默认值生效
            default: 0,
            // type来定义属性的值类型
            // 如果传递过来的值不符合此类型,则会在终端报错
            type: Number,
            // 必选项校验
            required: true
        }
    }
}

7) 组件之间的样式冲突问题

 默认情况下,写在.vue组件中的样式会全局生效,因此很容易造成多个组件之间的样式冲突问题。

导致组件之间样式冲突的根本原因是:

  1. 单页面应用程序中,所有组件的DOM结构,都是基于唯一的index.html页面进行呈现的
  2. 每个组件的样式,都会影响整个index.html页面中的DOM元素

1⃣️解决样式冲突 -> scoped属性

  • 给当前组件内的元素都加上data-v-0*属性,不同组件的元素不一样,这样就可以解决样式冲突。
  • 给style加上scoped属性:用来自动为每个组件分配唯一的自定义属性,并自动为当前组件的DOM标签和style样式应用这个自定义属性,防止组件的样式冲突问题
<style lang="less" scoped>

 

2⃣️/deep/样式穿透

如果当前组件的style节点添加了scoped属性,则当前组件的样式对其子组件是不生效的。如果想让某些样式对子组件生效,可以使用/deep/深度选择器

<style lang="less" scoped>
 h3 {
  color: red;
}

// 不使用:h5[data-v-3c83f0b7]
// 使用之后变成:[data-v-3c83f0b7] h5
// 当使用第三方组件库的时候,如果要修改第三方组件库的默认样式,则需要用到/deep/
// h5是Count.vue组件库的
/deep/ h5 {
  color: pink;
}
</style>

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值