简介
本文将为您介绍开发vue2.x相关常用知识。没了就这么简单粗暴!
-未推编辑完全(因作者也还在整理,所以此文章会陆陆续续补全。后面会加上源码解析)
-有时间会再度发布vue3.x开发相关知识(包括vite)
-此文章类似笔记,是作者开发vue项目整理的知识点,做个分享
项目搭建
- 运行指令 -
1.npm install webpack -g ---安装webpack环境 - 使用vueCli需要webpack-dev-server的支持
2.npm i -g vue-cli ---安装vue的脚手架 (⚠️用了vue3需要npm install -g @vue/cli-init桥接工具)
3.vue init webpack xxxx ---构建vue项目
- 项目构建解释 -
// Project name (xxxx): ---项目名称,直接回车,按照括号中默认名字(起名用小写)
// Project description (A Vue.js project): ---项目描述,也可直接点击回车,使用默认名字
// Author ---作者
// Vue build ---vue的构建 - 第一个是运行+编译器 - 第二个是仅限运行时
// Install vue-router? (Y/n) ---是否安装vue-router(yes/no)
// Use ESLint to lint your code? (Y/n) ---是否使用ESLint管理代码(yes/no)
// Pick an ESLint preset (Use arrow keys) ---代码风格(百度他选择的名字或者括号的地址)
// Setup unit tests with Karma + Mocha? (Y/n) ---是否安装单元测试(yes/no)
// Pick a test runner ---选择单元测试工具
// Setup e2e tests with Nightwatch(Y/n)? ---是否安装e2e测试(yes/no)
// Should we run `npm install` for you after the project has been created? (recommended) --想通过npm下载还是
谷歌插件
- vue的谷歌插件 -
// vue自推荐git地址(去把项目弄下来) vue插件git地址
// 进到该项目跑 yarn install
// 环境安装完全后就进行打包 yarn run build
// 打包完后谷歌打开/-开发者模式-/然后进到/-拓展程序-/点击/-加载已解压的拓展程序-/
// 按该路径选取文件 vue-devtools/packages/shell-chrome/
// 最后一步确认即可
- 题外-sass -
1.先npm安装stylus和stylus-loader。
2.sass依赖包 配置环境下
- npm install --save-dev sass-loader
- npm install --save-dev node-sass
3.配置条件 在build文件夹下的webpack.base.conf.js
- module: {
- rules: [
- {
- test: /\.sass$/,
- loaders: ['style', 'css', 'sass']
- }
- ]
- }
4.修改vue组件中的style标签/添加
- <style lang="scss">
内部指令
<template>
<div>
<!-- 1.v-if - 判断是否将该元素插入dom树 -->
<div v-if="!vIf">页面插入及显示该元素 - 此页面显示该条元素</div>
<div v-if="vIf">页面将不会有该div元素 - 此页面不显示该条元素</div>
<!-- 2.v-else-if - 判断是否将该元素插入dom树 -->
<div v-else-if="!(!vIf)">页面将不会有该div元素 - 此页面不显示该条元素</div>
<!-- 3.v-eles - 与if(){}else if(){}else{}同理 -->
<div v-else>需要上一个兄弟元素绑定v-if/v-else-if - 此页面显示该条元素</div>
<!-- 4.v-show - 页面会挂载该节点元素 -->
<div v-show="vShow">不管是否为真都会将该元素插入页面,只是控制了显示与隐藏(display) - 此页面显示该条元素</div>
<!-- 5.v-model - 双向绑定 - 让视图与控制数据互通 -->
<input type="text" v-model="vModel">
<!-- 6.v-once - 只显示第一次渲染的值 - 后面更改不会更换html -->
<div v-once>{{vModel}}</div>
<!-- 7.v-on - 时间监听 - 可简化为@ - 如 @click=“xxxxx” -->
<div v-on:click="vOn">点我触发查看双向绑定的值</div>
<!-- 8.v-bind - 将“冒号内的值”提升为变量 - 可简化为: - 如 :class=“xxxxx” -->
<div v-bind:class="vBind"> </div>
<!-- 9.v-for - 循环 - item是当前循环体,index是当前循环下标 - VFor是循环数据 -->
<div v-for="(item, index) in VFor" :key="index">{{item.name}}</div>
<!-- 10.v-text - 用来显/打印示文本/变量内容 - 123将被替换 -->
<div v-text="vText">123</div>
<!-- 11.v-html - 用来直接把html结构code直接存进数据库。再调出使用 -->
<div v-html="vHtmls"></div>
<!-- 12.v-cloak - 防止页面挂载内容还未处理完成显示{{}}大括号,等代码加载完出来再显示 -->
<div v-cloak>{{vBind}}</div>
<!-- 13.v-pre - 不编译vue方法 - 上面所提到的都失效,包括大括号 -->
<div v-pre v-text="vText">{{123}}</div>
</div>
</template>
<script>
export default {
name: 'Bao',
data () {
return {
vIf: false,
vShow: true,
vModel: '',
vBind: 'className',
vText: '我有一只小毛驴,我从来都不骑~',
vHtmls: `<div>12${1 + 2}<span style="color:red">567</span></div>`, // ``是字符串模版
VFor: [{name: '值1'}, {name: '值2'}]
}
},
methods: {
vOn () {
console.log('监听触发-双向绑定的输入值为:' + this.vModel)
}
}
}
</script>
自定指令
<template>
<div>
<div v-baobao="backFunc"></div>
</div>
</template>
<script>
export default {
name: 'Bao',
data () { return { } },
methods: {
backFunc (data) {
console.log('触发监听回调:' + data)
}
},
// 自定义挂载属性 - 当组件挂载时候执行
directives: {
baobao: {
// bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
// inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
// update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
// componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
// unbind:只调用一次,指令与元素解绑时调用。
inserted (el, binding, vnode) {
el.innerHTML = '不念过去,不惧将来,不思未来'
// 接收的值请看下面讲解
// 除了 el 之外,其它参数都应该是只读的
el.addEventListener('click', () => {
binding.value && binding.value('传值啦啦啦啦啦啦啦')
})
}
// 来源-百度
// el:指令所绑定的元素,可以用来直接操作 DOM 。
// binding:一个对象,包含以下属性:
// - name:指令名,不包括 v- 前缀。
// - value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
// - oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
// - expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
// - arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
// - modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
// vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
// oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
// ---------- 分割线 ----- 也可以在main.js在new Vue,创建并挂载自定义函数如下 -----
// Vue.directive('baobao', {
// inserted (el, binding) {
// el.addEventListener('click', () => {
// binding.value && binding.value()
// })
// }
// })
}
}
}
</script>
生命周期
<template>
<div ref="div" v-text="msg" />
</template>
<script>
export default {
name: 'Bao',
data () {
return {
msg: '1秒后即将触发'
}
},
/* 创建前 - 进场 */
beforeCreate () {
// 在实例初始化之后,数据观测和事件配置之前被调用(-new Vue)
// el与data并未初始化,因此无法访问methods\data\computed等上的方法和数据
console.log('beforeCreate,此时拿不到data内的数据!', this.msg)
},
/* 创建后 - 构建data数据后 */
created () {
// 在observData(-开始监控data)和InitEvents(-vue内部初始化事件)后执行的第一个钩子
// 已经配置数据观测(-watch)与属性(-event)与方法(-methods),data数据也已初始完成
// 未有el
console.log('created,此时Dom数还没渲染挂载!', this.msg)
},
/* 挂载前 - 即将挂载dom树 */
beforeMount () {
// 在页面编译模版(-把data内的数据或模版生成html)后执行的钩子
console.log('beforeMount,此时Dom数还是没有渲染挂载~')
},
/* 挂载后 - dom树挂载完成后 */
mounted () {
// 用上面已经编译好的编译模版替换el属性指向的dom树对象或者选择对应的html标签里面的内容
let tiem = setTimeout(() => {
this.msg = '我将要改变数据'
console.log('mounted,此时dom树已挂载好,可获取页面节点内容', this.$refs.div.innerHTML)
this.$nextTick(() => { console.log('nextTick,相当于在页面设置了个回调,等dom树更新后在触发', this.$refs.div.innerHTML) })
clearTimeout(tiem)
}, 1000)
},
/* 更新前 - 准备更新dom树 */
beforeUpdate () {
// 发生在虚拟DOM重新渲染和打补丁之前,可以再此拦截默认渲染数据,不会触发附加地重渲染过程
console.log('beforeUpdate,即将更新页面数据', this.msg)
this.msg = '嘿嘿嘿嘿嘿'
},
/* 更新后 - 页面已经被刷新 */
updated () {
// 页面更新后的回调钩子
console.log('beforeUpdate,页面已经进项更新', this.msg)
},
/* 销毁前 - 即将销毁离开 */
beforeDestroy () {
console.log('销毁前')
},
/* 销毁后 - 已经销毁离开 */
destroyed () {
console.log('销毁后')
}
}
</script>
常见属性
<template>
<div >
<h1 v-text="showTitle" />
<button @click="bao" v-text="'点我'" />
<div>
<p>输入1到10</p>
<input type="text" v-model="num">
<!-- num是过滤的参数 - |是过滤符号 - baoxixi是过滤方法 -->
<h3 >{{ num | baoxixi(baoAttr) }}</h3>
</div>
</div>
</template>
<script>
export default {
name: 'Bao',
data () {
return {
oldTitle: '变动前',
num: '1',
baoAttr: [
{ num: 1, title: '啦啦啦1' },
{ num: 2, title: '啦啦啦2' },
{ num: 3, title: '啦啦啦3' },
{ num: 4, title: '啦啦啦4' },
{ num: 5, title: '啦啦啦5' },
{ num: 6, title: '啦啦啦6' },
{ num: 7, title: '啦啦啦7' },
{ num: 8, title: '啦啦啦8' },
{ num: 9, title: '啦啦啦9' },
{ num: 10, title: '啦啦啦10' }
]
}
},
// 计算属性 - 监听 - 当该函数里当依赖值变动时触发并返回
computed: {
// computer当页面中有某些数据依赖其他数据进行变动的时候,可以使用计算属性。
// 需要注意的是,就算在data中没有直接声明出要计算的变量,也可以直接在computed中写入。
showTitle () {
let data = this.oldTitle + ',嘻嘻'
return data
}
},
// 属性监听 - 及监听data里面或props值的变动 - 可监听数组_链式表达
watch: {
// watch和computed很相似,watch用于观察和监听页面上的vue实例,当然在大部分情况下我们都会使用computed,但如果要在数据变化的同时进行异步操作或者是比较大的开销,那么watch为最佳选择。watch为一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。
// 如果在data中没有相应的属性的话,是不能watch的,这点和computed不一样。
'oldTitle': function (newVal, oldVal) {
console.log(newVal, oldVal)
}
},
// 过滤器
filters: {
// 过滤可用于类似值集显示
baoxixi (num, attr) {
let data = attr.filter(item => { return item.num === +num })
let title = data.length ? data[0].title : '未过滤出来,不过宝还是帅'
return title
}
},
// 自定义函数体 - vue页面中存放方法的地方
methods: {
// methods方法,跟前面的都不一样,我们通常在这里面写入方法,只要调用就会重新执行一次,相应的有一些触发条件,在某些时候methods和computed看不出来具体的差别,但是一旦在运算量比较复杂的页面中,就会体现出不一样。
// 需要注意的是,computed是具有缓存的,这就意味着只要计算属性的依赖没有进行相应的数据更新,那么computed会直接从缓存中获取值,多次访问都会返回之前的计算结果。
bao () {
this.oldTitle = '变动后'
},
backshows () {
console.log('directives也可以回调方法')
}
},
// 自定义挂载属性 - 当组件挂载时候执行
directives: {
// 自定义挂载属性本章上部分已讲
},
// v-model接收 - 下面传父子交互会讲
model: {
// v-model值的操作
},
}
</script>
父子交互
<!-- 父组件 -->
<template>
<div>
<p>父-双向绑定的值:<span v-text="baoModel" /></p>
<!-- childBao - 组件已全局挂载 - 在main.js - Vue.component('childBao', childBao) -->
<childBao v-model="baoModel" :baoData="baoData" @childBaoBackClick="baoClick" :disabled='false' />
</div>
</template>
<script>
export default {
name: 'Bao',
data () {
return {
// 父组件绑定的值
baoModel: '18',
// 给子组件提供的数据
baoData: [
{ name: '小朋友', key: 18 },
{ name: '宝宝', key: 28 },
{ name: '宝贝', key: 38 }
]
}
},
watch: {
// 监听值变动
baoModel () { console.log('监听触发了变动') }
},
methods: {
// 子组件触发并emit返回触发
baoClick (title, data) {
alert(`这里是父组件方法-括号内输出子组件传回来内容( ${title + data} )`)
}
}
}
</script>
<!-- 子组件 -->
<template>
<div>
<select v-model="childBaoModel">
<option
v-for="(item,index) in baoData"
:key="index"
:value="item.key"
v-text="item.name"
:disabled="disabled"
/>
</select>
</div>
</template>
<script>
export default {
name: 'childBao',
data () {
return {
// 子组件绑定的值
childBaoModel: this.baoModel
}
},
// v-model接收
model: {
// prop - 使用b-model传来的值 - 需要在props声明接收
prop: 'baoModel',
// event - 你将要更新来源的值 - $emit反回去
event: 'upBaoModel'
},
// 父传子接收声明
props: {
// 父v-model值
baoModel: {
type: [String, Number], // type接受值的类型
default: '' // 如果没有传 - default就为默认值
},
// 下拉数据
baoData: {
type: Array,
default: () => {
return [] // 数组与对象需要return
}
},
// 是否禁用
disabled: {
type: Boolean,
default: false
}
},
watch: {
// 监听父传子的v-model值的变动
baoModel (value) {
this.childBaoModel = value
},
// 监听子绑定值的变动
childBaoModel (value) {
// 更新父v-model的值
this.$emit('upBaoModel', value)
// emit返回触发父组件定义好的方法
this.$emit('childBaoBackClick', '我是子组件往父组件传的值:', value)
}
}
}
</script>
ref与slot
动态路由
结束话语
[- 结束话语 -](#bao10)