-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
前端基础知识之Vue篇 #21
Comments
[前端进阶]Vue 篇vue 为什么要求组件模板只能有一个根元素(实质上是技术限制)
你了解 vue 的 diff 算法吗
在.vue 文件中 style 是必须的吗?那 script 是必须的吗?为什么在 .vue 文件中,template 是必须的,而 script 与 style 都不是必须的。都不写的话,就是一个静态页面,也是可以的。如果是普通组件那么只能是一个静态 html,如果是函数式组件, 那么可以直接使用 props 等函数式组件属性。 自己实现一个双向绑定的微型框架,你该怎么做呢
let obj = {
singer: "周杰伦"
};
let value = "青花瓷";
Object.defineProperty(obj, "music", {
// value: '七里香', // 设置属性的值 下面设置了get set函数 所以这里不能设置
configurable: false, // 是否可以删除属性 默认不能删除
// writable: true, // 是否可以修改对象 下面设置了get set函数 所以这里不能设置
enumerable: true, // music是否可以被枚举 默认是不能被枚举(遍历)
// ☆ 通过defineProperty设置的属性,默认不能删除,不能遍历
// ☆ get,set设置时不能设置writable和value,要一对一对设置,交叉设置/同时存在 就会报错
get() {
// 获取obj.music的时候就会调用get方法
// let value = "强行设置get的返回值"; // 打开注释 读取属性永远都是‘强行设置get的返回值’
return value;
},
set(val) {
// 将修改的值重新赋给song
value = val;
}
});
console.log(obj.music); // 青花瓷
delete obj.music; // configurable设为false 删除无效
console.log(obj.music); // 青花瓷
obj.music = "听妈妈的话";
console.log(obj.music); // 听妈妈的话
for (let key in obj) {
// 默认情况下通过defineProperty定义的属性是不能被枚举(遍历)的
// 需要设置enumerable为true才可以 否则只能拿到singer 属性
console.log(key); // singer, music
}
myVue.prototype._observer = function(obj) {
var _this = this;
Object.keys(obj).forEach(key => {
// 遍历数据
_this._watcherTpl[key] = {
// 每个数据的订阅池()
_directives: []
};
var value = obj[key]; // 获取属性值
var watcherTpl = _this._watcherTpl[key]; // 数据的订阅池
Object.defineProperty(_this._data, key, {
// 双向绑定最重要的部分 重写数据的set get
configurable: true, // 可以删除
enumerable: true, // 可以遍历
get() {
console.log(`${key}获取值:${value}`);
return value; // 获取值的时候 直接返回
},
set(newVal) {
// 改变值的时候 触发set
console.log(`${key}更新:${newVal}`);
if (value !== newVal) {
value = newVal;
watcherTpl._directives.forEach(item => {
// 遍历订阅池
item.update();
// 遍历所有订阅的地方(v-model+v-bind+{{}}) 触发this._compile()中发布的订阅Watcher 更新视图
});
}
}
});
});
};
myVue.prototype._compile = function(el) {
var _this = this,
nodes = el.children; // 获取app的dom
for (var i = 0, len = nodes.length; i < len; i++) {
// 遍历dom节点
var node = nodes[i];
if (node.children.length) {
_this._compile(node); // 递归深度遍历 dom树
}
// 如果有v-model属性,并且元素是INPUT或者TEXTAREA,我们监听它的input事件
if (
node.hasAttribute("v-model") &&
(node.tagName = "INPUT" || node.tagName == "TEXTAREA")
) {
node.addEventListener(
"input",
(function(key) {
var attVal = node.getAttribute("v-model"); // 获取v-model绑定的值
_this._watcherTpl[attVal]._directives.push(
new Watcher(node, _this, attVal, "value") // 将dom替换成属性的数据并发布订阅 在set的时候更新数据
);
return function() {
_this._data[attVal] = nodes[key].value; // input值改变的时候 将新值赋给数据 触发set=>set触发watch 更新视图
};
})(i)
);
}
if (node.hasAttribute("v-bind")) {
// v-bind指令
var attrVal = node.getAttribute("v-bind"); // 绑定的data
_this._watcherTpl[attrVal]._directives.push(
new Watcher(node, _this, attrVal, "innerHTML") // 将dom替换成属性的数据并发布订阅 在set的时候更新数据
);
}
var reg = /\{\{\s*([^}]+\S)\s*\}\}/g,
txt = node.textContent; // 正则匹配{{}}
if (reg.test(txt)) {
node.textContent = txt.replace(reg, (matched, placeholder) => {
// matched匹配的文本节点包括{{}}, placeholder 是{{}}中间的属性名
var getName = _this._watcherTpl; // 所有绑定watch的数据
getName = getName[placeholder]; // 获取对应watch 数据的值
if (!getName._directives) {
// 没有事件池 创建事件池
getName._directives = [];
}
getName._directives.push(
new Watcher(node, _this, placeholder, "innerHTML") // 将dom替换成属性的数据并发布订阅 在set的时候更新数据
);
return placeholder.split(".").reduce((val, key) => {
return _this._data[key]; // 获取数据的值 触发get 返回当前值
}, _this.$el);
});
}
}
};
// new Watcher() 为this._compile()发布订阅+ 在this._observer()中set(赋值)的时候更新视图
function Watcher(el, vm, val, attr) {
this.el = el; // 指令对应的DOM元素
this.vm = vm; // myVue实例
this.val = val; // 指令对应的值
this.attr = attr; // dom获取值,如value获取input的值 / innerHTML获取dom的值
this.update(); // 更新视图
}
Watcher.prototype.update = function() {
this.el[this.attr] = this.vm._data[this.val]; // 获取data的最新值 赋值给dom 更新视图
}; vue 生命周期的原理是什么
vue 3.0计划
vue2.0不再支持v-html中使用过滤器了怎么办
// 使用
v-html="htmlFilter(htmlString)"
// 全局方法
Vue.prototype.htmlFilter= function (msg) {
return msg.replace("\n", "<br>")
};
// computed
computed: {
htmlFilter(msg){
return msg.replace("\n","<br>")
}
}
// $options.filters
v-html="$options.filters.htmlFilter(msg)"
filters:{
htmlFilter:function(msg){
return msg.replace(/\n/g,"<br>")
}
} v-if和v-show(1)关于条件渲染 (2)区别 v-if 当切换v-if模块时,Vue.js 有一个局部编译/卸载过程,因为 v-if 之中的模板也可能包括数据绑定或子组件。v-if 是真实的条件渲染,因为它会确保条件块在切换当中合适地销毁与重建条件块内的事件监听器和子组件。 v-if 是惰性的,如果为false,则什么也不错-不编译,不渲染。 当第一次条件为真时,才开始局部编译(编译会被缓存起来)。 (3)建议 而 v-if 比较适合不太频繁的切换状态的组件。所以项目设计的时候,不要对复杂的业务设计模块太频繁的视图切换。尽量将静态内容和动态内容分离到不同的模块中。 一般来说,v-if 有更高的切换消耗而 v-show 有更高的初始渲染消耗。因此,如果需要频繁切换 v-show 较好,如果在运行时条件不大可能改变 v-if 较好。在v-show中,元素是一直存在的,当v-show为false时,元素display:none只是隐藏了而已。 前端数据驱动模式
vue依赖的软件环境
vue-router
MVVM框架是什么?它和其它框架(jquery)的区别是什么?哪些场景适合?
directives指令
vue双向数据绑定实现原理
vue的生命周期
vuex
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
},
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
})
store.commit('increment')
store.dispatch('increment') // mapState, mapGetters, mapActions 和 mapMutations
store.dispatch('incrementAsync', { amount: 10 }) // 以载荷形式分发
store.dispatch({ type: 'incrementAsync', amount: 10 }) // 以对象形式分发 vue-loader是什么?使用它的用途有哪些?
模块化(AMD,CMD,CommonJS)
|
写 React / Vue 项目时为什么要在列表组件中写 key,其作用是什么
官网推荐使用 key,应该理解为“使用唯一 id 作为 key”。因为 index 作为 key,和不带 key 的效果是一样的。index 作为 key 时,每个列表项的 index 在变更前后也是一样的,都是直接判断为 sameVnode 然后复用。
说到底,key 的作用就是更新组件时判断两个节点是否相同。相同就复用,不相同就删除旧的创建新的。正是因为带唯一 key 时每次更新都不能找到可复用的节点,不但要销毁和创建 vnode,在 DOM 里添加移除节点对性能的影响更大。所以会才说“不带 key 可能性能更好”,没有 key 的情况下可以对节点就
原地复用
,提高性能。node 框架比较:Next、Nuxt 和 Nest,这三个框架都是服务器端渲染
如何选择正确的 Node 框架:Express,Koa 还是 Hapi
nuxtjs
生命周期
Vue 的生命周期全都跑在客户端(浏览器),而 Nuxt 的生命周期有些在服务端(Node)、客户端,甚至两边都在。如图所示:红框内的是 Nuxt 的生命周期(运行在服务端),黄框内同时运行在服务端&&客户端上,绿框内则运行在客户端。
nodejs
The text was updated successfully, but these errors were encountered: