Vue-Api 细分理解
------------------------------------问题部分-----------------------------------------------
常见问题:
- 自递归+for循环:渲染菜单
// 注意通过 prop 传入的参数能终止递归
<template>
<div class="ball" v-if="ball.children">
<div>{{ball.v}}</div>
// 递归嵌套位置
<ball-vue :ball="ball.children"></ball-vue>
</div>
</template>
<script>
export default {
name: 'ballVue',
props:['ball'] }
<el-tabs v-model="activeName" type="card" @tab-click="handleClick">
<el-tab-pane label="用户管理" name="first">用户管理</el-tab-pane>
<el-tab-pane label="配置管理" name="second">配置管理</el-tab-pane>
// include 不能为空。为空则匹配所有,写一个不可能有的name即可
<keep-alive include='组件name属性' exclude>
<router-view></router-view>
</keep-alive>
</el-tabs>
-
全局API及部分全局配置
-
Vue.config.optionMergeStrategies.要合并的属性
Vue.config.optionMergeStrategies.data = (parent,child)=>{ //这里是vue中的data属性会受到合并策略的影响 console.log('调用',parent,child); if (!parent) { return child } if (!child) { return parent } return Object.assign(parent,child) };
-
mixins:实质上除App.vue外的每个组件都会有mixin,只不过初始值都是undefine
export default { name: "HelloWorld", mixins:[hello], //这里parent:helloworld中的data函数,child是mixin中hello的data函数 };
实际上借助上面optionMergeStrategies中的打印函数,我们看到了不止1次打印
一:mixins自己也有mixin(undefine,mixin)、二:组件内部正常打印(mixin,组件内data函数)、三:每个组件有默认的mixins(即使没写出来,也会打印undefine,自己的data函数)
-
使用Vue.extend(已使用Vue.component)
Cannot create property '_Ctor' on string 'xxx'
更改Vue.extend产生的组件构造函数的函数名即可
Vue.extend产生构造函数,调用后产生一个组件--直接挂载即可,不能放在vue的components(里面的是对象未经过编译)属性中
-
Vue.nextTick( [callback, context]):vue中DOM操作是异步的,可能在同步代码中得到undefine
Vue.set( target, propertyName/index, value ):给响应式新增一个属性(响应式的,直接添加不是响应式的)
Vue.delete( target, propertyName/index ):与上面相反
this.msg = 'msg' //要操作DOM(即使用到DOM的api),不是操作vue组件中的属性 this.$nextTick(()=>{ //放里面能获取到 this.msg1 = this.$refs.msgDiv.innerHTML }) //放外面获取不到 this.msg2 = this.msg1 this.$set(this.obj,'num',100) // 不能在 data 上设置根级数据
把后面依赖异步的代码放到nextTick中的回调函数中执行
-
Vue.directive(id,[definition]):自定义指令
// 全局定义 import Vue from 'vue'; Vue.directive('focus',{ inserted:function(el){ el.focus() } }) // 局部定义 export default { data(){return{}} directives:{ focus : { inserted : function(el){el.focus()}} } filters:{ //自定义过滤器 upper: function(val){return val.toUpperCase()}, addol: function(val){return val+'ol'} } }
id:指令名(使用时以v-开头)、第二个参数:对象(多个生命周期钩子函数)
-
Vue.filter( id, [definition] ):自定义过滤器
过滤器函数名,局部/全局使用方式同directive
下面展示2种使用方法
// 双花括号使用{{}} <div>{{obj.name | upper | addol}}</div> // v-bind,这个可以在父组件向子组件传参时使用 <api v-bind:id="apiId | upper"></api> props:['id'],
-
Vue.component( id, [definition] ):注册或获取全局组件。注册还会自动使用给定的 id 设置组件的名称
Vue.component返回的是一个构造器函数
构造器函数(同Vue.extend)执行-> 编译后 -> render -> VNode -> $mounts : vue实例
// 注册组件,传入一个扩展过的构造器 Vue.component('my-component', Vue.extend({ /* ... */ })) // 注册组件,传入一个选项对象 (自动调用 Vue.extend) Vue.component('my-component', { /* ... */ }) // 获取注册的组件 (始终返回构造器) var MyComponent = Vue.component('my-component') // -------------------实际使用------------------------- Vue.component('com',{ mounted() { }, }) var MyComponent = Vue.component('com') export default { components:{ com } //这里给的构造函数 //----或者------- components:{ com: { // 这里给的对象 ,与平时import子组件一样 mounted:function() { alert('开始ile')}} }};
Vue.use( plugin ):{Object | Function} plugin
如果插件是一个对象,必须提供 install 方法。如果插件是一个函数,它会被作为 install 方法。install 方法调用时,会将 Vue 作为参数传入。 该方法需要在调用 new Vue() 之前被调用。
当 install 方法被同一个插件多次调用,插件将只会被安装一次。
Vue.compile( template ):{string} template,将一个模板字符串编译成 render 函数。只在完整版时可用
如果插件是一个对象,必须提供 install 方法。如果插件是一个函数,它会被作为 install 方法。install 方法调用时,会将 Vue 作为参数传入。 该方法需要在调用 new Vue() 之前被调用。
当 install 方法被同一个插件多次调用,插件将只会被安装一次。
Vue.observable(object):让一个普通对象可相应
返回的对象可以直接用于渲染函数和计算属性内,并且会在发生变更时触发相应的更新。也可以作为最小化的跨组件状态存储器,用于简单的场景
Vue2中返回的对象和源对象是同一个对象,Vue3中是返回一个新的对象
const state = Vue.observable({ count: 0 }) const Demo = { render(h) { return h('button', { on: { click: () => { state.count++ }} }, `count is: ${state.count}`) } }
Vue.version:返回一个版本号
var res = Vue.compile('<div><span>{{ msg }}</span></div>') new Vue({ data: { msg: 'hello' }, render: res.render, staticRenderFns: res.staticRenderFns })
-
-
Vue内的选项
-
选项-数据
-
data:Object | Function
Vue会递归将data的property(不包含原型链上)转换为getter/setter(通过Object.defineProperty)->变为响应式的数据
无法在根数据对象上添加响应式property:推荐在创建实例之前,就声明所有的根级响应式property
data() { return { name: 'lhx', age : 12, // obj是data中的根级数据,obj.name不是。根级数据是不能新增/删除,所以提前设置好需要的,后期不再变更 obj:{ name: '二级数据' }, // 由于Vue实例的代理,this.name == this.$data.name $gg :'jj' }}, methods: { change(){ this.$set(this.data,'num',13) // _/$开头可能与内置Api/Property冲突,不能以代理方式访问 console.log(this.$data.$gg); }}
实例创建之后,通过 vm.$data.name / vm.name(Vue实例代理( proxy )data 对象所有的 property) 访问原始数据对象,
以 _ 或 $ 开头的 property 不会被代理,通过 vm.$data._property 访问
data之所以被声明为函数,函数返回一个对象,对象都会指向创建它的vue实例,所以可通过this.$data访问
深拷贝data中的属性:JSON.parse(JSON.stringify(...))
-
props: Array(string) | Object
type:String、Number、Boolean、Array、Object、Date、Function、Symbol,会检查是否是这个类型
default:any(默认值,如果该 prop 没有被传入,则换做用这个值, 另外数组、对象的值必须用函数返回)
required : 是否必须传入
validator : 验证器函数
props:{ objdata:{ type : Object, default : ()=>{}, require : true, validator : function(value){ return Object.keys(value).length>0 } } };
-
-
选项-DOM
-
el:string | Element
只在用 new 创建实例时生效(其它情况写的el是无效)
实例化时存在这个选项,实例将立即进入编译过程,否则,需要显式调用 vm.$mount() 手动开启编译
如果不是在new情况下,this.$el会指向 template 中的DOM元素
-
template : string
加到挂载点的DOM模板,挂载点:el / 页面中的xxx-vue
模板会替换挂载点及原有DOM,可以通过 slot插槽 保留
模板会替换挂载点及原有DOM,可以通过 slot插槽 保留
//模板方式1 <template> <div></div> </template> //方式2 优先级低于1 template:'<div>字符串模板</div>' // 方式3 x-template ,在.vue文件无法使用,异步的渲染函数无法渲染同步的 template 中的‘#’选择器 <script type="x-template" id="mytem"> <div>我是x-template生成的模板</div> </script>
-
render : (createElement: () => VNode) => VNode
render的优先级比template高,即render和template产生相同,render也渲染模板
影响render在与createElement参数
main.js中render中的 h 只是一个形参,最终会将createElement作为实参传进去
import Vue from 'vue'; var vnVue = Vue.component('vn',{ render:function(createElement){ // return createElement('h1','render') return createElement(参数1,2,3) // 参数1 : {String | Object | Function} html标签名/组件名 必选 // 2 : {Object} 与模板中 attribute 对应的数据对象 可选(主要是一些属性) // 3 : {String | Array} 子级虚拟节点 (VNodes) } }) export default { components:{ vnVue } };
-
选项-生命周期钩子
-
beforeCreate
此阶段vue实例的基本结构已有
-
created阶段~beforeMount阶段
.vue文件中的template标签 > render(createElement) > vue组件内部的template
如果上述都没有,会从outerHtml中获取(可以在html文件中测试)
-
-
选项-资源
-
directives: 包含 Vue 实例可用指令的哈希表。
自定义指令
-
filter: 包含 Vue 实例可用过滤器的哈希表
自定义过滤器
-
components: 包含 Vue 实例可用组件的哈希表
Vue.component(/*全局注册,后面注册的组件及其子组件都可访问*/)
component:{ /*局部注册*/ }
-
-
选项--组合(交互,将组件联系起来)
-
parent : 类型:Vue instance
this.$parent/$children 可以访问父组件(应急方法,优先使用props、emit)
-
extends : 注意并非 Vue.extend
var com = { data(){ return { msg : 'com' }}} // 使用类似 mixin ,在外面定义一个对象,然后在组件中添加一项 extends:com
-
provide / inject :
provide:Object | () => Object
inject:Array
| { [key: string]: string | Symbol | Object }
</li> </ul> </li> </ul> </li> </ul> </li> <li class="instance"> <p>Vue 实例属性</p> <ul> <li id="InstanceProperties"> <p>Vue实例--属性</p> <ul> <li> <p>vm.$<strong style="font-size: 20px;">data</strong>:Vue 实例代理data对象里面的property的访问</p> </li> <li> <p>vm.$<strong style="font-size: 20px;">props</strong>:Vue 实例代理了对其 props 对象 property 的访问</p> </li> <li> <p>vm.$<strong style="font-size: 20px;">el</strong>:Vue 实例使用的根 DOM 元素,</p> </li> <li> <p>vm.$<strong style="font-size: 20px;">options</strong>:用于当前 Vue 实例的初始化选项,一个Vue 实例最初的一个框架,不包含挂载之后的东西</p> </li> <li> <p>vm.$<strong style="font-size: 20px;">refs</strong>:一个对象,持有注册过 ref attribute 的所有 DOM 元素和组件实例</p> </li> <li> <p>vm.$<strong style="font-size: 20px;">attrs</strong>:包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定。可以通过 v-bind="$attrs" 传入内部组件</p> </li> <li> <p>vm.$<strong style="font-size: 20px;">listeners</strong>:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。通过 v-on="$listeners" 传入内部组件</p> </li> </ul> </li> <li id="InstanceFunData"> <p>Vue实例--与数据有关的方法</p> <div>vm.$watch / vm.$set / vm.$delete</div> </li> <li id="InstanceFunEvent"> <p>Vue实例--与事件有关的方法</p> <div>vm.$on / vm.$once / vm.$off:移除事件 / vm.$emit</div> </li> <li id="InstanceFunLife"> <p>Vue实例--与生命周期有关的方法</p> <div>vm.$mount / vm.$nextTick / vm.$destroy</div> <div>vm.$forceUpdate:迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件</div> </li> <li id="dircts"> <p>Vue实例--指令集</p> <div>v-html / v-show / v-if / v-else / v-else-if / v-for / v-on / v-bind / v-model / v-slot / v-once</div> <div>v-pre :不会再编译里面的东西,直接以字符串输出,提高编译速度`<span v-pre>{{ this will not be compiled }}</span>` </div> <div>v-cloak:保持元素关联直至替换实例准备完毕</div> </li> <li id="spcAttrs"> <p>Vue实例--特殊指令集</p> <div>key / ref / is :用于动态组件渲染</div> <div>v-pre :不会再编译里面的东西,直接以字符串输出,提高编译速度`<span v-pre>{{ this will not be compiled }}</span>` </div> <div>v-cloak:保持元素关联直至替换实例准备完毕</div> </li> </ul> </li> </ol> </body>// 父组件,其中一项 provide : { foo: 'bar' } // 子组件,类似 prop inject: ['foo'],
-
-
-