1 原理
v3.0 2020.09.19发布
vue2--vuex 3.x--vue-router 3.x--vue-cli 3.x
vue3--vuex 4.x--vue-router 4.x--vue-cli 4.5
Model:数据源
View:页面渲染的DOM结构
ViewModel:vue的实例
2 配置选项
1) data/methods
el:'#app',//选择器模板,等价于vm.$mount('#app')
data(){//内部数据;data必须写成函数:避免组件被复用时,数据存在引用关系。
return{}
},
methods:{//this:(组件中)组件实例对象vc vs vue实例对象vm(new Vue) --el配置
},
2) props
只读,如果想改变,可转存到data中。提高组件复用性
//传递数据:数值
<MyCount :msg="6"></MyCount>
//数组形式
props:['属性A','属性B','属性C'],
//对象形式
props:{
initCount:{
default:0,
type:[Number,String],//多种类型
required:true,//和默认值没有关系
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
3) watch
watch:针对数据执行操作。侧重于监听单个数据变化,执行操作。可执行异步操作。
computed:监听多个值变化,最终计算返回一个值。两者都可用的时候,computed简单。
watch:{
//函数形式
username(newVal,oldVal){}//监视的值作为函数名
//对象形式
username:{
handler(newVal,oldVal){},
immediate:true,//开始立即调用
deep:true,//监听的数据是一个对象,用deep开启深度监听
}
'info.username'(newVal){}//监听对象子属性变化,包裹单引号
}
4) computed
本质是函数,监听data中数据变化,return一个计算后的新值。会缓存计算结果,依赖值变化才会重新求值。
methods计算结果无法被缓存,性能低。
computed:{
rgb(){ return `rgb(${this.r},${this.g},${this.b})` }
}
computed: {
double1() {
return this.num * 2
},
double2: {
get() {
return this.num * 2
},
set(val) {
this.num = val/2
}
}
}
5) components
关于组件名:
一个单词组成:
第一种写法(首字母小写):school
第二种写法(首字母大写):School
多个单词组成:
第一种写法(kebab-case命名):my-school
第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)
1.一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
2.为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。
//定义组件
//const school = Vue.extend(options) 可简写为:const school = options
//school组件本质是一个名为VueComponent的构造函数。每次调用Vue.extend,返回的都是一个全新的VueComponent
//Vue解析时会帮我们创建school组件的实例对象
const s = Vue.extend({
name:'atguigu',
template:`
<div>
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
`,
data(){
return {
name:'尚硅谷',
address:'北京'
}
}
})
//局部组件
components:{Left}
components: {//动态组件:大文件
'my-component': () => import('./my-async-component')
}
//全局组件:在main.js中注册
Vue.component('MyCount',Count)
6) filters
用于文本格式化,本质是函数,一定要有返回值。形参中获取原始值。
私有和全局冲突时,采用就近原则。
// 私有过滤器
filters:{
capi(val){
return newVal
}
}
// 全局过滤器
Vue.filter('capi,(val,arg1,arg2)=>{
return newVal
})
7) directives
//局部自定义指令
//对象形式
directives:{
color:{
bind(el,binding){//由指令v-color第一次绑定到元素上触发;el指的是当前指令绑定的DOM元素
el.style.color=binding.value;//v-color="colorStr"
}
update(el,binding){//每次DOM更新时调用
el.style.color=binding.value;
}
}
}
directives:{//vue3
focus:{
mounted(el,binding){
el.focus();
}
}
}
//函数形式(简写)
directives:{
color(el,binding){
el.style.color=binding.value;
}
}
//全局自定义指令
Vue.directive('color',function(el,binding){
el.style.color=binding.value;
})
Vue.directive('color',{//vue3
mounted(el,binding){//绑定的元素插入到DOM中触发
el.focus();
}
updated(el,binding){//DOM更新时触发
el.focus();
}
})
8) mixins
vue中的混入_史学娇的博客-CSDN博客_vue里面的混入
//全局混入
Vue.mixin(myMixin)
9)template/render
/*
该文件是整个项目的入口文件
*/
import Vue from 'vue'
import App from './App.vue'
//关闭vue的生产提示
Vue.config.productionTip = false
/*
关于不同版本的Vue:
1.vue.js与vue.runtime.xxx.js的区别:
(1).vue.js是完整版的Vue,包含:核心功能+模板解析器。
(2).vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。
2.因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用
render函数接收到的createElement函数去指定具体内容。
*/
//创建Vue实例对象---vm
new Vue({
el:'#app',
//render函数完成了这个功能:将App组件放入容器中
render: h => h(App),
// template:`<h1>你好啊</h1>`,
// components:{App},
})
3 样式
3.1 scoped
问题:.vue文件的样式会全局生效,造成多个组件样式冲突
原因:单页应用的DOM结构,基于index.html呈现,每个组件的样式都会对其产生影响
解决:scoped,并自动使用属性选择器(h5[data-v-xxx]{})
3.2 deep
加了scoped属性,当前组件样式对其子组件不生效。这时,可使用/deep/深度选择器。vue3.x 中使用:deep()
使用场景:父组件中改变子组件样式,如使用第三方组件库,修改默认样式。
/deep/ h5{
color:pink;//[data-v-xxx] h5
}
4 ref特性
ref获取DOM
ref="xxx"
this.$refs.xxx:获取DOM
注意:会引发拿不到DOM的问题,用$nextTick解决
ref引用组件实例
this.$refs.comName:父组件调用子组件方法
5 内置组件
5.1 component
<component :is="componentName"></component>
5.2 keep-alive
<keep-alive>
包裹动态组件时,会缓存不活动的组件实例。常用于tab切换,无需重复渲染。
include
和 exclude,
匹配首先检查组件自身的 name
选项。activated钩子在被 keep-alive 缓存的组件激活时调用。deactivated钩子在被 keep-alive 缓存的组件停用时调用。
<keep-alive include="a,b">
<component :is="view"></component>
</keep-alive>
5.3 transition
若有多个元素需要过度,则需要使用:```<transition-group>```,且每个元素都要指定```key```值。
可通过npm中 animate.css 来配置更多样式。
<template>
<div>
<button @click="isShow = !isShow">显示/隐藏</button>
<transition-group name="hello" appear>
<h1 v-show="!isShow" key="1">你好啊!</h1>
<h1 v-show="isShow" key="2">尚硅谷!</h1>
</transition-group>
</div>
</template>
<script>
export default {
name:'Test',
data() {
return {
isShow:true
}
},
}
</script>
<style scoped>
h1{
background-color: orange;
}
/* 进入的起点、离开的终点 */
.hello-enter,.hello-leave-to{
transform: translateX(-100%);
}
.hello-enter-active,.hello-leave-active{
transition: 0.5s linear;
}
/* 进入的终点、离开的起点 */
.hello-enter-to,.hello-leave{
transform: translateX(0);
}
</style>
4 生命周期
生命周期是指一个组件从创建-运行-销毁的整个阶段。
4.0 示意图
4.1 创建 (一次)
beforeCreate:有事件、生命周期函数;无data/props/methods
created:组件在内存中创建完毕调用。有data/props/methods,可发Ajax请求;无组件的模板结构,无法获取DOM。
beforeMount:基于数据和模板编译html结构;无DOM和$el
mounted:组件渲染到页面上调用。html结构替换el属性指定的DOM元素,操作DOM
4.2 运行(多次)
beforeUpdate:数据是新的,DOM是旧的
updated:组件重新渲染完毕调用。都是新的
4.3 销毁(一次)
beforeDestroy:组件将要销毁。解绑事件;关闭定时器。
destroyed/unmounted:组件被销毁后(内存和页面)调用
4.4父子组件生命周期执行顺序
- 父组件 before create
- 父组件 created@
- 父组件 before mount
- 子组件 before create
- 子组件 created@
- 子组件 before mount
- 子组件 mounted@
- 父组件 mounted@
- 父组件 before update
- 子组件 before update
- 子组件 updated
- 父组件 updated
- 父组件 before destroy
- 子组件 before destroy
- 子组件 destroyed
- 父组件 destroyed
5 使用插件
main.js
import Vue from 'vue'
import App from './App.vue'
//引入插件
import plugins from './plugins'
Vue.config.productionTip = false
//应用(使用)插件
Vue.use(plugins,1,2,3)
//创建vm
new Vue({
el:'#app',
render: h => h(App)
})
plugin.js
export default {
install(Vue,x,y,z){//vue自己调用了install方法
console.log(x,y,z)//接收use中传递的参数
//全局过滤器
Vue.filter('mySlice',function(value){
return value.slice(0,4)
})
//定义全局指令
Vue.directive('fbind',{
//指令与元素成功绑定时(一上来)
bind(element,binding){
element.value = binding.value
},
//指令所在元素被插入页面时
inserted(element,binding){
element.focus()
},
//指令所在的模板被重新解析时
update(element,binding){
element.value = binding.value
}
})
//定义混入
Vue.mixin({
data() {
return {
x:100,
y:200
}
},
})
//给Vue原型上添加一个方法(vm和vc就都能用了)
Vue.prototype.hello = ()=>{alert('你好啊')}
}
}