23、$refs是什么东东?

  通过在标签上设置ref属性,然后在Vue实例方法中可以通过$refs拿到这些标签,如:

<input ref="input">
methods: {
focus: function () {
//拿到文本框标签,调用其获取焦点方法
this.$refs.input.focus()
}
}

24、对于多级嵌套组件,后代组件如何拿到父级或祖父级,设置更高级别的组件的数据或方法?

  使用依赖注入

      provide选项允许我们在当前组件指定我们想要提供给后代组件的数据/方法,比如:
provide: function () {
return {
getMap: this.getMap
}
}

  然后在任何后代组件里,我们都可以使用inject 选项来接收指定的我们想要添加在这个实例上的属性:

inject: ['getMap']
  实际上,可以把依赖注入看做是一部分”大范围有效的prop", 但是这个依赖注入祖先组件不需要知道哪些后代组件使用它提供的属性,同时后代组件不需要知道被注入的属性来自哪一级祖先组件。
 
25、对于某些我们创建的对象,如何程序化的清理?
  程序化事件侦听器
  • 通过$on(eventName, eventHandler) 侦听一个事件
  • 通过$once(eventName, eventHandler) 一次性侦听一个事件
  • 通过$off(eventName, eventHandler) 停止侦听一个事件

    先看一个示例:

mounted: function () {
//Pikaday是一个第三方日期选择器的库。这里是将这个日期选择器附加到一个输入框上,最后挂载到DOM上
var picker = new Pikaday({
field: this.$refs.input,
format: 'YYYY-MM-DD'
}) //设置一次性的侦听事件,在组件销毁之前,销毁这个日期选择器
this.$once('hook:beforeDestroy', function () {
picker.destroy()
})
}
  对于多个这种输入框,可以让多个输入框使用不同的Pikady, 每个新的实例都程序化地在后期清理它自己
mounted: function () {
this.attachDatepicker('startDateInput')
this.attachDatepicker('endDateInput')
},
methods: {
attachDatepicker: function (refName) {
var picker = new Pikaday({
field: this.$refs[refName],
format: 'YYYY-MM-DD'
}) this.$once('hook:beforeDestroy', function () {
picker.destroy()
})
}
}

26、如果组件之间出现了互相引用,如何处理?

       先看一个示例:

     组件<tree-foler>的模板是这样的:

<p>
<span>{{ folder.name }}</span>
<tree-folder-contents :children="folder.children"/>
</p>

另外一个组件<tree-folder-contents>的模板是这样的:

<ul>
<li v-for="child in children">
<tree-folder v-if="child.children" :folder="child"/>
<span v-else>{{ child.name }}</span>
</li>
</ul>

  这两个组件互相引用,导致出现了循环引用。这种情况如何去解决呢?

  假设这两个组件<tree-folder>是父组件,<tree-folder-contents>是子组件,则产生问题的是子组件<tree-folder-contents>, 因此我们在生命周期钩子beforeCreate里面去注册子组件

beforeCreate: function () {
this.$options.components.TreeFolderContents = require('./tree-folder-contents.vue').default
}
  或者,在本地注册组件的时候,我们使用webpack的异步import:
components: {
TreeFolderContents: () => import('./tree-folder-contents.vue')
}

  这样问题就解决了。

27、Vue项目编译关于内存溢出的处理

  随着项目中组件的增加,终于到了一个临界点,每次修改页面保存自动编译时,都会报内存溢出导致编译中断:

  FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory

  解决办法,增加increase-memory-limit插件,增加node服务器内存限制,步骤:

  1、在 package.json文件的scripts中增加一行配置:"fix-memory-limit": "cross-env LIMIT=8096 increase-memory-limit"

 "scripts": {
"dev": "cross-env POST_API=dev vue-cli-service serve",
"test": "cross-env POST_API=test vue-cli-service build --mode test",
"pre": "cross-env POST_API=pre vue-cli-service build --mode pre",
"hd": "cross-env POST_API=hd vue-cli-service build --mode hd",
"build": "cross-env POST_API=pro vue-cli-service build --mode pro",
"fix-memory-limit": "cross-env LIMIT=8096 increase-memory-limit"
},

  2、在项目终端输入新增依赖包命令:npm install --save-dev increase-memory-limit

  3、接着执行命令:npm run fix-memory-limit

  4、重新运行项目就ok了

28、为什么要自定义指令?如何自定义指令?

  虽然在Vue2.0中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通DOM元素进行底层操作,这时候就会用到自定义指令。

自定义指令之前,先了解几个钩子函数(均为可选):
  • bind : 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置
  • inserted : 被绑定元素插入父节点时调用(仅保证父节点存在,但不一定被插入文档中)。
  • update : 所在组件的VNode更新时调用,但是可能发生在其子VNode更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新
  • componentUpdated : 指令所在组件的VNode及其子VNode全部更新后调用。
  • unbind : 只调用一次,指令与元素解绑时调用。
 
指令钩子函数会被传入以下参数:
  • 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编译生成的虚拟机节点。
    • oldVnode :上一个虚拟节点,仅在update和componentUpdated钩子中可用
注意:除了el之外,其他参数都应该是只读的,切勿进行修改。如果需要在钩子之间共享数据,建议通过元素的dataset来进行
 使用例子:
<div v-my-custom-directive:foo.a.b="message"></div>
//自定义指令 , 写在new Vue前面
Vue.directive('my-custom-directive', {
bind: function (el, binding, vnode) { console.log(el);
console.log(binding);
console.log(vnode);
console.log(".......end.....") var s = JSON.stringify
el.innerHTML =
'name: ' + s(binding.name) + '<br>' +
'value: ' + s(binding.value) + '<br>' +
'expression: ' + s(binding.expression) + '<br>' +
'arg: ' + s(binding.arg) + '<br>' +
'modifiers: ' + s(binding.modifiers) + '<br>' +
'vnode keys: ' + Object.keys(vnode).join(', ')
}
}) var vm = new Vue({
el: "#app",
data:{
message: "hello",
}
});

  动态指令:指令的参数可以是动态的。例如,在v-mydirective:[argument]="value"中,argument参数可以根据组件实例数据进行更新,举例:

<div id="dynamicexample">
<h3>Scroll down inside this section ↓</h3>
<p v-pin:[direction]="200">I am pinned onto the page at 200px to the left.</p>
</div>
Vue.directive('pin', {
bind: function (el, binding, vnode) {
el.style.position = 'fixed'
var s = (binding.arg == 'left' ? 'left' : 'top')
el.style[s] = binding.value + 'px'
}
}) new Vue({
el: '#dynamicexample',
data: function () {
return {
direction: 'left'
}
}
})

29、什么叫渲染函数?

  Vue推荐在绝大多数情况下使用模板来创建HTML, 然而在一些场景中,我们也需要JavaScript的完全编程的能力。这时需要我们使用渲染函数,这比模板更接近编译器。

  举个例子来对比某种场景下使用模板和渲染函数的区别,先用模板来创建一个带锚点的标题组件,组件编译后的HTML标签大概是这样:

<h1>
<a name="hello-world" href="#hello-world">
Hello world!
</a>
</h1>

对于上面编译后的HTML, 我们决定这样定义组件接口:

<anchored-heading :level="1">Hello world!</anchored-heading>
<script type="text/x-template" id="anchored-heading-template">
<h1 v-if="level === 1">
<slot></slot>
</h1>
<h2 v-else-if="level === 2">
<slot></slot>
</h2>
<h3 v-else-if="level === 3">
<slot></slot>
</h3>
<h4 v-else-if="level === 4">
<slot></slot>
</h4>
<h5 v-else-if="level === 5">
<slot></slot>
</h5>
<h6 v-else-if="level === 6">
<slot></slot>
</h6>
</script>
Vue.component('anchored-heading', {
template: '#anchored-heading-template',
props: {
level: {
type: Number,
required: true
}
}
})

  我们 看到,这里使用模板并不是最好的选择,不但代码冗长,而且在每一级别的标题中书写<slot></slot>, 在要插入的锚点元素时还要再次重复。

  接着我们来尝试使用渲染(render)函数重写上面的例子:

Vue.component('anchored-heading', {
render: function (createElement) {
return createElement(
'h' + this.level, // 标签名称
this.$slots.default // 子节点数组
)
},
props: {
level: {
type: Number,
required: true
}
}
})

  这个就是渲染函数,看起来简单多了。

30、啥叫虚拟DOM ? 

  看看下面这段HTML,说说浏览器是怎么操作它的

<div>
<h1>My title</h1>
Some text content
<!-- TODO: Add tagline -->
</div>

  当浏览器读到这些代码时,它会建立一个”DOM节点“树来保持追踪所有内容,如同你会画一张家谱树来追踪家庭成员的发展一样。

 每个元素都是一个节点,每段文字也是一个节点。甚至注释也都是节点。一个节点就是页面的一个部分。就是家谱树一样,每个节点都可以由孩子节点(也就是说每个部分可以包含其他的一些部分)。

  高效的更新所有节点会是比较困难的,不过所幸你不必手动完成这个工作,你只需要告诉Vue你希望页面上的HTML是什么,这可以是在一个模板里:

<h1>{{ blogTitle }}</h1>

  或者一个渲染函数里:

render: function (createElement) {
return createElement('h1', this.blogTitle)
}

  在这两种情况下,Vue都会自动保持页面的更新,即便blogTitle发生了改变。

  Vue怎么做到这些的呢?这就出现”虚拟DOM“这个概念了!Vue通过建立一个虚拟DOM来追踪自己要如何改变真实DOM, 请仔细看这行代码:

return createElement('h1', this.blogTitle)

  createElement到底返回什么呢?其实不是一个实际的DOM元素,它更准确的名字可能是createNodeDescription, 因为它所包含的信息会告诉Vue页面上需要渲染什么样的节点,包括及其子节点的描述信息。我们把这样的节点描述为”虚拟节点(Virtual node)", 也常简写它为“VNode" 。”虚拟DOM" 是我们对Vue组件树建立起来的这个VNode树的称呼。

  

  接下来我们对createElement函数进行研究一下,它需要传递哪些参数?如何使用?先看看它的参数定义:

// @returns {VNode}  createElement返回一个虚拟DOM
createElement(
'div', //第一个参数(必填),可以是HTML标签名(String)、组件选项对象(Object)、async函数(Function) { /* ... */ }, //第二个参数(可选),一个与模板中属性对应的数据对象(Object) //第三个参数(可选),子级虚拟节点(VNodes), 由‘createElement()’构建而成,也可以使用字符串来生成”文本虚拟节点“
[
'先写一些文字',
createElement('h1', '一则头条'),
createElement(MyComponent, {
props: {
someProp: 'foobar'
}
})
]
)

  对createElement函数的参数了解了后,我们来看一个完整的示例:

Vue.component('anchored-heading', {
render: function (createElement) { console.log("this.$slots.default: ", this.$slots.default);
/* this.$slots.default, 插槽里每加一个标签,this.$slots.default里面就多一个undefined的VNode,
比如上面anchored-heading的slot里面直接子节点3个(div、span、h3), 则this.$slots.default数组里面的VNode为5个(3个+2个undefined VNode)
[
{ tag: 'div', children: Array(5) },
{ tag: undefined, children: undefined },
{ tag: 'span', children: Array(1) },
{ tag: undefined, children: undefined },
{ tag: 'h3', children: Array(1)}
]
*/
// 创建 kebab-case 风格的 ID
var childrenStr = getChildrenTextContent(this.$slots.default);
var headingId = childrenStr
.toLowerCase()
.replace(/\W+/g, '-') //非字母、数字、下划线字符,全部替换成“-”,比如中文/标点符号全部换成“-”
.replace(/(^-|-$)/g, '') //以“-”开头或结尾,替换为空 console.log("orialStr: ", childrenStr);
console.log("headingId: ", headingId); var myVnode = createElement(
'h' + this.level,
[
//这里有对三个参数使用的例子
createElement('a', {
attrs: {
name: headingId,
href: '#' + headingId,
id: 'tantan'
},
// style: { //与`v-bind:style`的API相同,接受一个字符串、对象,或对象组成的数组
// color: 'red', fontSize: '16px', borderTop: '1px dashed black', textDecoration: 'underline'
// },
// domProps: { //设置DOM属性
// innerHTML: '<div class="sub-div">nihao</div>',
// // innerText: '王大锤',
// },
// on: { //渲染函数事件
// click: function(){
// console.log("点我啦了。, 。。 ")
// alert("ni8你好")
// },
// focus: function(){
// console.log("....获取焦点。。。")
// },
// blur: function(){
// console.log(".....失去焦点。。。")
// },
// }
}, this.$slots.default)
]
) console.log(".............最后createElement返回的数据是......")
console.log(myVnode)
console.log("............ok end.................") return myVnode;
},
props: {
level: {
type: Number,
required: true
}
}
})

  注意:组件树中的所有VNode必须是唯一的。这意味着,下面的渲染是不合法的:

render: function (createElement) {
var myParagraphVNode = createElement('p', 'hi')
return createElement('div', [
// 错误 - 重复的 VNode
myParagraphVNode, myParagraphVNode
])
}

  如果真的需要重复很多次的元素/组件, 可以使用工厂函数来实现。例如,下面这渲染函数用完全合法的方式渲染了20个相同的段落:

render: function (createElement) {
return createElement('div',
Array.apply(null, { length: 20 }).map(function () {
return createElement('p', 'hi')
})
)
}

Vue官方文档笔记(二)的更多相关文章

  1. Vue官方文档笔记

    1.如何创建一个Vue实例对象? var vm = new Vue({ el: "#app", //标签id 或 标签类名 data:{ //双向绑定的数据 message: &q ...

  2. 转:ArcGIS API For JavaScript官方文档(二十)之图形和要素图层——①Graphics概述

    原文地址:ArcGIS API For JavaScript官方文档(二十)之图形和要素图层——①Graphics概述 ArcGIS JavaScript API允许在地图上绘制graphic(图形) ...

  3. OKHttp 官方文档【二】

    OkHttp 是这几年比较流行的 Http 客户端实现方案,其支持HTTP/2.支持同一Host 连接池复用.支持Http缓存.支持自动重定向 等等,有太多的优点. 一直想找时间了解一下 OkHttp ...

  4. Gora官方文档之二:Gora对Map-Reduce的支持

    参考官方文档:http://gora.apache.org/current/tutorial.html 项目代码见:https://code.csdn.net/jediael_lu/mygoradem ...

  5. Gora官方文档之二:Gora对Map-Reduce的支持 分类: C_OHTERS 2015-01-31 11:27 232人阅读 评论(0) 收藏

    参考官方文档:http://gora.apache.org/current/tutorial.html 项目代码见:https://code.csdn.net/jediael_lu/mygoradem ...

  6. Vue官方文档Vue.extend、Vue.component、createElement、$attrs/$listeners、插槽的深入理解

    一.Vue.extend({}). 看官网文档介绍,Vue.extend({})返回一个Vue的子类,那么这个Vue子类是啥玩意儿呢?我直观感觉它就是创建出一个组件而已啊,那么它又和Vue.compo ...

  7. 【cocos2d-js官方文档】二十五、Cocos2d-JS v3.0中的单例对象

    为何将单例模式移除 在Cocos2d-JS v3.0之前.全部API差点儿都是从Cocos2d-x中移植过来的,这是Cocos2d生态圈统一性的重要一环.可惜的是,这样的统一性也在非常大程度上限制了C ...

  8. docker官方文档笔记

    Docker在 CentOS7.X上运行.Docker可能在其他EL7的兼容版本中成功安装,但是官方并未进行测试,因此也不提供任何支持. 系统环境要求 docker必须运行在64-bit的系统上,对于 ...

  9. 【cocos2d-js官方文档】二、资源管理器Assets Manager

    这篇文档将介绍Cocos2d-JS 3.0的一个重量级新特性:资源管理器(仅支持JSB).资源管理器是为游戏运行时的资源热更新而设计的,这里的资源可以是图片,音频甚至游戏脚本本身.使用资源管理器,你将 ...

随机推荐

  1. DateTimeComparer

    public int Compare(string x,string y) { DateTime xDate = DateTime.ParseExact(x, "MMMM", ne ...

  2. DataTable 转List

    忘了出处   ,这个是转别人的 public class DataToList<T> where T : new() { /// <summary> /// 利用反射和泛型 / ...

  3. The underlying connection was closed: An unexpected error occurred on a send

    操作系统是Windows Server 2003 x64 SP2,使用Framework 4.0,在使用WebClient访问某些特定的HTTPS站点时,会引发异常: Unhandled Except ...

  4. Vue-cli3脚手架工具快速创建一个项目

    1.首先全局安装一下vue-cli3 npm install -g @vue/cli 或 yarn global add @vue/cli vue -V查看版本(这里注意V是大写哦) 2.vue cr ...

  5. LeetCode——Rank Scores

    Write a SQL query to rank scores. If there is a tie between two scores, both should have the same ra ...

  6. 对于不返回任何键列信息的 SelectCommand,不支持 DeleteCommand 的动态 SQL 生成

    VS新增操作数据库出现如下报错. 原因是数据库表未添加主键 MySQL: CREATE TABLE Customer (SID integer, Last_Name ), First_Name ), ...

  7. postgreSQL 自动递增序号

    创建表格 CREATE TABLE test ( id serial, name ) not null ); 查询当前创建好的表格 插入数据 BEGIN TRANSACTION; INSERT INT ...

  8. 阅读高翔的RGBD-SLAM博文笔记

    目录 高翔的RGBD-SLAM笔记 前端VO: 后端优化 高翔的RGBD-SLAM笔记 RGBD相机的特点: 使用RGBD相机中的深度这一维信息,以及相机的针孔成像模型,相机的内参,可以将二维点恢复成 ...

  9. Jenkins连接Git仓库时候报错Permission denied, please try again.

    一.连接GIT仓库报错 Failed to connect to repository : Command : stdout: stderr: Permission denied, please tr ...

  10. devops 下测试组织管理面临的挑战及应对

    导读 先从引发的5个问题讲起,再简单回顾一下devops 简介和兴起背景 ,再从itest 测试管理团队的视角提出应对办法 DevOps后,测试面临的挑战        敏捷开发必然是迭代开发管理模式 ...