Day03_Vue基础入门

Day03_Vue基础入门

今日学习内容:

  • 侦听器
  • 计算属性
  • vue-cli
  • vue组件

1、watch侦听器

1.1、什么是侦听器

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

​ 声明格式如下:

const vm = new Vue({
	el:"#app",    //此处的#app可以看做是css中选择器的命名方式,如果为p则vue会渲染第一个p元素
	data:{
		message:"hello vue.js",
		info:"title info"
	},
	watch:{
		//监听info数据的变化
		//newVal是变化后的新值,oldVal是变化前的新值
		info(newVal,oldVal){
			console.log(newVal,oldVal)
		}
	}

})

​ 用处实例:可以使用watch检测用户名是否可用

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

watch: {
    // 监听 username 值的变化
    async username(newVal) {
        if (newVal === '') return
        // 使用 axios 发起请求,判断用户名是否可用
        const { data: res } = await axios.get('https://www.escook.cn/api/finduser/' + newVal)
        console.log(res)
		return res
    } 
}

1.2、immediate选项

​ 默认情况下,组件会在初次加载完毕后不会调用watch侦听器,如果想让watch侦听器立刻被调用,则需要使用immediate选项。

watch:{
	username:{
		//handler是固定写法,表示当前username的值变化是,自动调用handler处理函数
		handler:async function(newVal){
			if(newVal === "") return
			const{data:res}= await axios.get('https://www.escook.cn/api/finduser/' + newVal)
			console.log(res)
		},
		//表示页面初次渲染好之后,就立即触发当前watch侦听器
		immediate:true
	}
}

1.3、deep选项???

​ 如果watch侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用deep选项。

watch:{
	username:{
		//handler是固定写法,表示当前username的值变化是,自动调用handler处理函数
		handler:async function(newVal){
			if(newVal === "") return
			const{data:res}= await axios.get('https://www.escook.cn/api/finduser/' + newVal)
			console.log(res)
		},
		//表示页面初次渲染好之后,就立即触发当前watch侦听器
		deep:true
	}
}

1.4、监听对象单个属性的变化

​ 适用于监听对象中单个属性的变化。

const vm = new Vue({
	el:"#app",    //此处的#app可以看做是css中选择器的命名方式,如果为p则vue会渲染第一个p元素
	data:{
		message:"hello vue.js",
		info:"title info"
	},
	watch:{
		//监听info数据的变化
		//newVal是变化后的新值,oldVal是变化前的新值
		'info.username':{
			handler(newVal,oldVal){
				console.log(newVal);
			}
		}
	}

})

2、计算属性

2.1、什么是计算属性

​ 计算属性是指通过一系列运算之后,最终得到一个属性值。

这个动态计算出来的属性可以被模板结构或methods方法使用。

var vm = new Vue({
    el:"#app",
    data:{
        r:0
    },
    computed:{
        rs(){
            return this.r++;
        }
    },
    methods:{
        rsmethod(){
            this.r++;
        }
    }
})

2.2、计算属性的特点

  • 虽然计算属性在声明的时候会被定义成方法,但是计算属性的本质是一个属性
  • 计算属性会缓存计算结果,只有计算属性依赖的数据变化时,才会重新进行运算
    • 缓存计算结果是指,当再次调用计算属性的结果时,可以直接调用结果,而不用进行再次计算。

计算属性、方法、监听的区别

  • 计算属性(computed):一定要返回一个值,属性的结果会被缓存,除非依赖的数据属性变化才会重新计算,主要当做属性来使用,适合计算的逻辑
  • 方法(methods):表示一个具体的操作,主要书写业务逻辑
  • 监听(watch):一个对象,键是需要观察的数据属性名,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;可以看做 computed 和 methods 的结合体
    总结:watch用的相对来说比较少,重点放到计算属性和方法上

3、vue-cli的使用

3.1、什么是单页面应用程序?

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

3.2、什么是vue-cli?

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

​ 使用此工具程序员可以专注在专业应用上,而不必花好几天去纠结webpack配置的问题。

3.3、vue项目的创建与使用

​ 在运行vue项目之前需要先创建一个vue项目,在命令行通过vue create XXX可以创建一个XXX项目。

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

其中:

  • App.vue用来编写待渲染的模板结构
  • index.html中需要预留一个el区域
  • main.js把App.vue渲染到index.html所预留的区域中。

vue项目的目录结构

  • node_modules
  • public
    • favicon.ico
    • index.html(build后产生一个.js文件,此文件可调用)
  • src
    • assest:存放项目中静态的资源文件
    • components:程序员封装的可复用自建都放在这里
    • main.js :项目的入口文件,所有项目优先执行的项目
    • App.vue:项目的根组件
  • babel.config.js
  • package.json
  • package-lock.json
  • README.md

main.js

image-20220225103856320

4、vue组件

4.1、什么是组件化开发?

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

4.2、vue中的组件化开发

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

​ vue中规定:组件的后缀名是==.vue==。之前接触到的App.vue文件实质上就是一个vue组件。

​ 每个.vue组件分为三个组成部分:

  • template:组件的 模板结构
  • script:组件的 JavaScript行为
  • style:组件的 样式

其中,template是每个组件都必须要包含的内容,js行为和css样式是可选的部分。

template

​ vue规定:每个组件对应的模板结构,都要定义到template中。

<template>
	当前组件的DOM结构,需要定义到template标签内部
</template>

注意:

  • template是vue提供的容器标签,只起到包裹性质的作用,不会被渲染成真正的DOM元素。
  • template中只能包含唯一的root节点。

script

​ vue规定:开发者可以在

<script>
	//组件相关的data数据、methods方法等都要定义到export default中,只有向外暴露了此js逻辑,代码才能够被其他代码调用。
    export default {}
</script>

​ 注意:

  • vue规定:.vue组件中的data必须是函数,不能直接指向一个数据对象

    应为如果data作为一个函数,返回一个对象,那么每个template实例可以维护一份返回的对象的独立拷贝,如果返回的是一个数据对象,则会影响所有的data数据。

    //错误案例,会导致多个组件实例共用一份数据
    data:{
    	count:0
    }
    
    //正确案例
    data(){
    	return {
    		count:0,
    	}
    }
    
    

style

​ vue 规定:组件内的<style>节点是可选的开发者可以在其中编写样式美化当前组件的UI结构。将style的lang属性设置为"less",就可以使用less语法编写组件。

<style>
    h1{
        font-weight:normal
    }
</style>

4.3、组件间的父子关系

​ 当组件被封装好之后,彼此之间是相互独立的,不存在父子关系。如下:

image-20220224191844320

​ 在使用组件的时候,根据彼此嵌套关系,形成了父子关系、兄弟关系。如下:

image-20220224191948188

使用组件的三个步骤

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

<script>

//导入组件
import Left from "./components/Left.vue"
    
    //使用components节点注册组件
    export default {
        components:{
            //完成的注册形式为:Left:Left,
            Left  //由于组件名和导入的组件名重名所以可以简写成这样
        }
    }
</script>




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

例如:

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

​ 因为若是 组件A布局注册了组件F那么组件F只能作为组件A的一部分存在,也就是template F 只能作为 template A中的一个<F>。

注册全局组件

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

//arg1表示将要注册的组件名
//arg2表示需要全局祖册的那个组件

Vue.component("MyCount",Count)


4.4、组件的 props

​ props是组件的 自定义属性在封装通用组件的时候,合理地使用props可以大大提高组件的复用性。当一个值被传递给prop 属性是,他就变成了那个组件实例的一个属性。

​ 当我们申请注册一个全局component时,可以为其做声明:


//组件的使用
<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>


//声明组件
Vue.compoent('blog-post',{
	props:['title'],
template:'<h3>{{title}}</h3>'
})

​ 在更常见的应用中,我们往往见到的是一个props数组对象

//使用
<blog-post
  v-for="post in posts"
  v-bind:key="post.id"
  v-bind:title="post.title"
></blog-post>


//组件声明
var vm =new Vue({
  el: '#blog-post-demo',
  data: {
    posts: [
      { id: 1, title: 'My journey with Vue' },
      { id: 2, title: 'Blogging with Vue' },
      { id: 3, title: 'Why Vue is so fun' }
    ]
  }
})

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

​ 如果想要修改props的值,需要把props的值传到data中,因为data中的数据都是可读可写的。

export default {
	name:"",
	props:['init']
	data(){
		return {
			count:this.init;
		}
	}
}

Prop的大小写(camelCase vs kebab-case)

HTML 中的attribute名大小写是不敏感的,所以浏览器会把所有大写字符解释为小写字符,这意味着所有的驼峰命名法都可以通过短横线分隔命名:

<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>

//在js中的camelCase(驼峰命名法)
Vue.component('blog-post', {
  // 在 JavaScript 中是 camelCase 的
  props: ['postTitle'],
  template: '<h3>{{ postTitle }}</h3>'
})
props常用的方式

以字符串列出prop

props: ['title', 'likes', 'isPublished', 'commentIds', 'author']

指定传递的prop类型

props: {
  title: String,
  likes: Number,
  isPublished: Boolean,
  commentIds: Array,
  author: Object,
  callback: Function,
  contactsPromise: Promise // or any other constructor
}

prop动态赋值

<!-- 动态赋予一个变量的值 -->
<blog-post v-bind:title="post.title"></blog-post>

<!-- 动态赋予一个复杂表达式的值 -->
<blog-post
  v-bind:title="post.title + ' by ' + post.author.name"
></blog-post>

Prop验证***

Vue.component('my-component', {
  props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA: Number,
    propB: [String, Number],  // 多个可能的类型
    propC: {
      type: String,
      required: true  // 必填的字符串
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

4.5、组件之间的样式冲突问题

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

​ 导致组件之间样式冲突的根本问题是:

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

两种解决方式

  • 为每个组件分配唯一的自定义属性,在编写组件样式时,通过属性选择器来控制样式的作用域,
  • 为了提高开发效率和开发体验,vue 为 style 节点提供了 scoped 属性,从而防止组件之间的样式冲突问题。

第二种代码演示

<template>
	<div class="container">
        <h3>
            轮播图组件
    </h3>
    </div>
</template>


<style scoped>
    .container{
        border:1px solid red;
    }
</style>

如果给当前组件的 style 节点添加了 scoped 属性,则当前组件的样式对其子组件是不生效的。如果想让某些样

式对子组件生效,可以使用 /deep/ 深度选择器。

<style scoped>
    .container{
        border:1px solid red;
    }
    /deep/ .container{
        border:1px solid red;
    }
</style>

5、axios

​ axios是前端圈最火的、专注于数据请求的库。

5.1、基础使用


//axios请求返回的是Promise对象
axios({
	method:"请求的方式",
	url:"请求的地址",
	data:{} //URL中的请求体参数,POST时用到的请求
	params:{}//URL的查询参数,GET 用到的数据
})

请求过程:

image-20220225095835731

注意:如果调用摸个方法的返回值是Promise实例,前面可以添加await! awati只能用在async修饰的方法中

axios方法的调用一般步骤

  1. 调用axios后使用async/await进行简化
  2. 使用解构后,从axios封装的大对象中把data属性解构出来
  3. 把解构的数据进行重命名

常见的方法调用方式

async getInfo(){
	const  {data:res} =await axios({		//此处用到了数据的解构
		method:"GET",
		url:'http://www.liulongbin.to:3006/api/post'
		data:{
			name:'zs',
			age:20
		}
	})
}

axios的简化使用

axios.get("url地址",{
	params:{
		数据体
	}
})
axios.post("url地址",{
	数据体
})

求的地址",
data:{} //URL中的请求体参数,POST时用到的请求
params:{}//URL的查询参数,GET 用到的数据
})


请求过程:

[外链图片转存中...(img-Qv555z8A-1645812500951)]

**注意:如果调用摸个方法的返回值是Promise实例,前面可以添加await! awati只能用在async修饰的方法中**



axios方法的调用一般步骤

1. 调用axios后使用async/await进行简化
2. 使用解构后,从axios封装的大对象中把data属性解构出来
3. 把解构的数据进行重命名

常见的方法调用方式

```vue
async getInfo(){
	const  {data:res} =await axios({		//此处用到了数据的解构
		method:"GET",
		url:'http://www.liulongbin.to:3006/api/post'
		data:{
			name:'zs',
			age:20
		}
	})
}

axios的简化使用

axios.get("url地址",{
	params:{
		数据体
	}
})
axios.post("url地址",{
	数据体
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值