Vue核心基础(中)
一、vue选项computed&watch
1.计算属性 computed
1.什么是计算属性
1.1计算属性指的是通过一系列运算之后,最终得到一个属性值。
1.2.这个动态计算出来的属性值可以被模板结构或 methods 方法使用。
1.3.定义:在computed里面声明一些函数, 函数必须要有’return’值
<!-- HTML部分 -->
<div id="app部分">
<h1>{{msg}}</h1>
<button @click="onTest()">按钮</button>
<h2>{{sum}}</h2>
</div>
<!-- js部分 -->
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
msg: '',
a: 10,
b: 20,
},
methods: {
onTest() {
alert('test' + this.sum)
},
},
computed: {
//定义多个计算属性
// 1. 定义一个名为counter的计算属性,计算属性内一定要有return返回值
// 2. 跟响应式数据用法一样,
// 3. 根据计算属性方法内响应式数据变化重新计算
sum() {
return this.a + this.b
},
},
})
</script>
2.计算属性的特点
1️ 虽然计算属性在声明的时候被定义为方法,但是计算属性的本质是一个属性;
2️ 计算属性会缓存计算的结果,只有计算属性依赖的数据变化时,才会重新进行运算
2.watch
1.定义
侦听Vue 实例上data中的数据和一些非DOM元素改变可以获取数据改变前的值和改变后的值
2.immediate 选项
默认情况下,组件在初次加载完毕后不会调用 watch 侦听器。如果想让 watch 侦听器立即被调用,则需要使用 immediate 选项。
<div id="app">
<h2>侦听属性watch</h2>
<!-- {{message}} -->
</div>
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el:'#app',
data:{
username:'jack',
book:{
name:'vue编程',
price:89,
num:1
}
},
watch:{
//侦听username数据
//newvalue侦听到的数据的值,oldvalue是原来值
// username(newvalue,oldvalue){
// console.log('newvalue :',newvalue, ' oldvalue :',oldvalue);
// }
username:{
handler(newvalue,oldvalue){
console.log('newvalue :',newvalue, ' oldvalue :',oldvalue);
},
immediate:true //立即侦听响应式数据变化
},
// book:{
// handler(value){
// console.log('>>>> ',value.name);
// },
// deep:true //深度侦听 如果 watch 侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用 deep 选项。
// },
'book.num':{ //侦听对象单个属性也可以
handler(value){
console.log('>>>> ',value);
}
}
},
})
</script>
3.deep 选项
如果 watch 侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用 deep 选项
list:{
handler(){
//监听list对象内内容发生变化时,输出对象
console.log(this.list)
},
deep:true
}
4.监听对象单个属性的变化
watch:{
// watch侦听name属性
name(){
console.log(this.name)
}
},
二、vue的生命周期
1.生命周期
vue实例从创建->运行->销毁 所经过的一系列过程统称为生命周期!强调的是一个时间段
2.生命周期函数
是由 vue 框架提供的内置函数,会伴随着生命周期,自动按次序执行
注: 生命周期强调的是时间段,生命周期函数强调的是时间点
3.生命周期函数的分类
1.创建期间的生命周期钩子函数
1.1beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
1.2**created**:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板
1.3beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中
1.4**mounted**:此时,已经将编译好的模板,挂载到了页面指定的容器中显示
2.运行期间的生命周期函数
2.1beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
2.2 updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了
3.销毁期间的生命周期函数
3.1 beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
3.2 destroyed :Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
4.生命周期函数图示
三、vue操作dom
1.原生js操作dom
- 可以使用querySlector系列
- 可以使用getElement系列
2.vue官方方法:ref属性
-
给标签添加ref属性
<div ref="d1"></div>
-
使用语法this.$refs.属性名获取
this.$refs.d1
四、api介绍
五、组件
1.vue框架特点
-
数据驱动
-
双向绑定,响应式
-
组件化
-
组件化:封装的思想,将UI结构与行为封装起来
-
组件定义:组件是可复用的 Vue 实例,且带有一个名字:我们可以把组件作为自定义元素来使用
-
自定义组件中,data响应式数值是函数,返回响应式数据
-
为什么在vue组件中data要写成函数而不是对象?
- 原因:因为我们能抽离出来的组件,是可以复用的vue实例,在项目中会存在多个实例。如果data属性值是一个对象时,那么它所有的实例都会共享这些数据,而函数具有独立作用域块的特点,外部是无法访问其内部的变量,如果我们组件中的data属性是一个函数,他的每个实例就会有自己的作用域空间,也就是独立的数据,每个实例之间不会相互影响。所以,组件中的data属性必须是一个函数
-
2.组件化和模块化的区别
- 组件化
是从UI界面的角度进行划分的 ,根据封装的思想,把页面上可重用的 UI结构封装为组件,从而方便项目的开发和维护。 - 模块化
是从代码的逻辑角度去划分的 方便代码分层开发保证每个功能模块的职能单一
3.创建组件
-
创建一个vue组件
Vue.component("button-counter", { template: ' <button @click="count++">You clicked me {{ count }} times.</button>', data: function () { return { }, });
-
在html中创建新标签***button-counter***,
<div id="app"> <button-counter>点击</button-counter> </div>
-
创建根组件
const vm = new Vue({ el: "#app", data: { counter: 0, }, });
4.组件通讯
4.1父传子 props
-
区分父组件和子组件
-
在子组件标签上添加属性参数,属性值为父组件要传的参数
-
在子组件中定义props选项,值是一个数组可以接收多个参数
4.2子传父$emit+v-on
-
在子组件中绑定一个自定义事件,如下的on-total是事件名,this.totalPrice是传的参数
this.$emit('on-total',this.totalPrice)
-
在子组件html标签中调用该事件:@on-total,特别注意的是在触发父组件事件时不要在事件后面加()
<product-list :book="newBook" @on-total="getTotalPrice"></product-list>
-
在父组件中设置一个事件接收数据,其中形参接是接收传的数据的
getTotalPrice(totalPrice){
this.total = totalPrice
}
4.3兄弟间传值 Event Bus
1.新建一个vueutil.js文件,在里面创建一个共用实例,并将其暴露
vueutil.js
import Vue from 'vue'
export const vm = new Vue()
2.在每个兄弟组件中引用该实例
例:
brother1.vue
<template>
<div>
<h2>兄弟组件1</h2>
<p>接收值: {{message}}</p>
<button @click="getMessage">获取数据</button>
</div>
</template>
<script>
import {vm} from '../utils/vueutil' //引用该实例
export default {
data:function(){
return{
message:''
}
},
created(){
//在vue生命周期的created阶段去监听brother2组件中的on-send事件,一旦事件被触发立马获取信息
vm.$on('on-send',(content)=>{
this.message = content
})
},
}
</script>
brother2.vue
<template>
<div>
<h2>兄弟组件2</h2>
<input type="text" placeholder="请输入内容" v-model="content">
<button @click="onSend">发送信息</button>
</div>
</template>
<script>
import {vm} from '../utils/vueutil' //引用该实例
export default {
data:function(){
return{
content:''
}
},
methods:{
onSend(){
// 触发自定义事件
vm.$emit('on-send',this.content) //在这个地方调用vm实例,不能用this
}
}
}
</script>
3.在页面中调用组件
app.vue
<template>
<div id="app">
<h2>兄弟组件传参</h2>
<brother-1></brother-1>
<brother-2></brother-2>
</div>
</template>
<script>
import Brother1 from './components/Brother1.vue';
export default {
components: { Brother1 },
name: "App",
};
</script>
4.参考图如下
4.4refs方式
-
在html中子组件的标签上定义ref属性
<son-ele ref="son" ></son-ele>
-
在父元素中调用这个节点,并通过节点对象调用子组件中的属性和方法
getnum(){
let sonObj = this.$refs.son
this.a = sonObj.num
}
}
六、单文件组件
1.引入
1.1使用 Vue.component
来定义全局组件的缺点
- 全局定义 (Global definitions) 强制要求每个 component 中的命名不得重复
- 字符串模板 (String templates) 缺乏语法高亮,在 HTML 有多行的时候,需要用到丑陋的
\
- 不支持 CSS (No CSS support) 意味着当 HTML 和 JavaScript 组件化时,CSS 明显被遗漏
- 没有构建步骤 (No build step) 限制只能使用 HTML 和 ES5 JavaScript,而不能使用预处理器,如 Pug (formerly Jade) 和 Babel
1.2引入
文件扩展名为 .vue
的 single-file components (单文件组件) 为以上所有问题提供了解决方法,并且还可以使用 webpack 或 Browserify 等构建工具。
2.组成
在一个文件扩展名为 .vue
单文件组件中应当包含以下几个部分:
2.1模板html代码结构
<template>
<p>{{message}}</p>
</template>
2.2模板 js代码逻辑
module.exports = {
data:function(){
return {
message:'hello'
}
}
}
2.3样式css
<style scoped>
p{
font-size: 18px;
color: red;
}
</style>
七.webpack构建工具
1.安装webpack
npm i webpack webpack-cli@4.9.2
npm i webpack webpack-cli@4.9.2 -g
2.项目目录
根文件名
-dist
-src
-|js
-|index.js
-package.json
-webpack.config.js // webpack配置文件
3.webpack执行
// package.json文件中配置
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack --mode development"
},
4.安装 vue-loader
npm install vue-loader@15.9.8
npm install vue-template-compiler
=====================================
npm install vue-loader@15.9.8 vue-template-compiler
5.webpack.config.js配置loader和插件
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
module: {
rules: [
// ... 其它规则
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
// 请确保引入这个插件!
new VueLoaderPlugin()
]
}
八、vue-cli 脚手架工具
对vue项目做了封装,直接使用vue-cli创建项目,常用配置,自动帮你完成,不用自己像使用webpack一样配置
1.安装
npm i vue // 项目化开发中,使用import导入vue 而不用script引入
npm i @vue/cli // vue-cli脚手架工具
使用下面语句可以合并安装
npm install vue @vue/cli -g
2.创建vue项目
appdemo为自定义文件名
vue create appdemo
3.运行项目
cd appdemo //进入项目目录
npm run serve //运行项目
4. 项目目录结构
5.vue-cli创建项目配置
- 第一步,选择预设配置, 第三个为手动配置
- 第二步, 选择第三个进入
- 第三步, vue版本2.x - 第四步, 生成独立配置文件
- 第五步, 选择npm包管理
- 配置完成,执行安装
6.[可选]关闭错误提醒
在vue.config.js文件中添加这行代码
module.exports = {
lintOnSave: false,
};