小白水平 可能会包含一些错误 或者还没写完... 或者非最佳实践 仅供参考
这个vue的官方api会有介绍javascript
model: { prop: 'checked', event: 'change' }
v-on:change="$emit('change', $event.target.checked)"
子代操做方法二:css
props:{ value:[String,Number], }
handleInput(event) { const value = event.target.value; // 经过这个实现v-model的set this.$emit('input', value); },
<input :value="something" @input="something=$event.target.value" /> <!-- 组件上的简化 --> <custom-input :value="something" @input="something=$event" > </custom-input> <!-- 子组件 --> <input type="text" :value="currentValue" @input="handleInput"> <!-- 1.子组件设置props的value --> props:['value'],//接受父组件传递过来的value值 <!-- 2.向父组件传递改变的值 --> methods:{ handleInput(event){ let value =event.target.value; this.$emit('input',value);//触发input事件,并传入新的值 }, setCurrentValue(value) { this.currentValue = value; }, } <!-- 3.重要:经过watch父组件的value改变才会更新子组件 这里以前就会出现父级value改变 子代不改变的bug--> watch: { value(val, oldValue) { this.setCurrentValue(val); } },
// 例子 <input type="checkbox" ref='switch' @click="handleClick"/> handleClick(evt) { this.$emit('click', evt); } // 例子 <input type="checkbox" ref='switch' @focus="handleFocus"/> handleFocus(event) { this.focused = true; this.$emit('focus', event); },
/* 父组件 */ <Example :width=40></Example> /* 子组件 */ <span class="el-switch__core" ref="core" :style="{ 'width': width + 'px' }">
// 第一步,注册组件 import Switch from './src/component'; Switch.install = function(Vue) { // name="TuiSwitch" Vue.component(Switch.name, Switch); }; export default Switch; // 第二步,安装组件(main.js) import Switch from 'install文件'; Vue.use(Switch); // 第三步,在组件中直接使用便可 <tui-switch></tui-switch>
axios.defaults.timeout = 30000; // 开发时只关心接口名称便可 axios.defaults.baseURL = "http://10.0.1.1:8080"; // 配置axios的拦截器,能够用来配置token axios.interceptors.request.use( config => { if (localStorage.getItem("token")) { config.headers.Authorization = localStorage.getItem("token"); } return config }, error => { return Promise.reject(error) } );
axios.post(url, params, { headers: { "Content-Type": "application/json;charset=UTF-8" } }).then(res=>{})
JSON.stringify({sdkParams: JSON.stringify(this.params)}); <!-- 这样子后面的字符串中的引号就会有转义字符 -->
git remote -v
显示origin表明的远程地址Node将在node_modules中搜索element-ui目录,Node会假设element-ui为一个包并试图找到包定义文件package.json。若是element-ui目录里没有包含package.json文件,Node会假设默认主文件为index.js,即会加载index.js。若是index.js也不存在,那么加载将失败。 package.json: { "license": "MIT", "main": "lib/element-ui.common.js", "name": "element-ui", } node将会返回element-ui.common.js模块
websocket(prodId) { this.ws = new WebSocket('ws://..........'); this.ws.onopen = function () { console.log("ws connected!"); }; this.ws.onmessage = e => { }; this.ws.onclose = function () { // 关闭 websocket后的回调函数 console.log("ws closed"); }; // 组件销毁时调用,主动关闭websocket链接 this.over = () => { ws.close(); }; }, beforeDestroy() { if (this.over) { this.over(); } send(msg){ if(this.ws){ this.ws.send(msg) } }
<!-- 这是文件扩展名为 .vue 的 single-file components(单文件组件) 相比传统new Vue({ el: '#container '})要好不少 --> <template> <div>This will be pre-compiled</div> </template> <script src="./my-component.js"></script> <style src="./my-component.css"></style> <!-- 开发时也会常用这种的格式 -->
flex是flex-grow flex-shrink flex-basis的缩写html
在有固定高的容器中实现标题在上面,内容在剩余高度居中:前端
display: flex; flex-direction: row; flex-wrap: wrap;
flex:1
来实现占满一行align-self: flex-start||baseline;
均可以实现,(测试元素是一个img)var EventUtil={ /*检测绑定事件*/ addHandler:function(element,type,handler){ if(element.addEventListener){ element.addEventListener(type,handler,false); } else if(element.attachEvent){ element.attachEvent('on'+type,handler); } else{ element["on"+type]=handler /*直接赋给事件*/ } }, /*经过removeHandler*/ removeHandler:function(element,type,handler) { /*Chrome*/ if (element.removeEventListener) element.removeEventListener(type, handler, false); else if (element.deattachEvent) { /*IE*/ element.deattachEvent('on' + type, handler); } else { element["on" + type] = null; /*直接赋给事件*/ } } };
### 18.多层组件的封装vue
18-9-13 当时的观点有点弱智啊,这个这个直接改变了子组件中的值啊,多是由于对象深度缘由没有报错?java
<!-- 数据单向绑定,不须要使用watch从父组件更新值到子组件,这句话很矛盾啊 --> <template> <div> <div class="product_info_row" v-for='(arr,index) in value' :key="index"> <div class="tag_input"> <lubun-input :cancleable='true' v-for='(v,i) in arr.tags' :key="i" type="text" v-model="v.value" :width=width :tagrow='index' :tagid='v.id' @click='removeTag' /> <!-- 失去焦点也须要保存 --> <lubun-input autofocus v-if='arr.show' type="text" v-model="arr.value" :width=80 @enter='buildTag(arr)' @blur='buildTag(arr)' /> <lubun-button v-else text="+" @click="addTag(arr)" :width=30 /> </div> </div> </div> </template> <script> export default { name: "LubunTaginput", componentName: "LubunTaginput", props: { width: { type: [String, Number], default: 150 }, value: { type: Array, default: function () { return [ { id: 0, show: false, value: "", tags: [] } ] } } }, methods: { addTag(rows) { rows.show = true; rows.value = ""; }, removeTag(obj) { // console.log("传入的rows:",obj); var tags = this.value[obj.tagRow].tags; // console.log("rows中的tags",tags); for (let i = 0; i < tags.length; i++) { // console.log("循环tags:", tags[i]); if (tags[i].id === obj.tagId) { // console.log('find'); tags.splice(i, 1); return; } } }, buildTag(rows) { rows.show = false; // 内容为空不会生成tag if (rows.value !== "") { rows.tags.push({ id: rows.id++, value: rows.value }); rows.value = ""; } } }, }; </script>
white-space:nowrap
这样就能够撑开两个div了beforeDestroy() { //组件销毁前须要解绑事件。不然会出现重复触发事件的问题 bus.$off("Event Name"); },
father{ display: flex; width: 100%; height: 100%; overflow: auto; } child-left{ position: relative; min-width: 800px; height: 100%; flex: 1; } child-right{ position: relative; min-width: 420px; height: 100%; }
<label style="width:80%" class='btn' for="uploadPic">上传文件</label> <input id="uploadPic" type="file" @change='uploadPic' style="display:none">
<span class="button" onclick="sel_local_images()" id="add_img" title="Add new file from local disk">加载图片</span> <input type="file" id="invisible_file_input" name="files[]" style="display:none"> //js中再给input加change事件便可 //这个也能够在vue中使用,给input加@change,而后手动触发这个input 的click()就能够弹出上传文件的界面了
var invisible_file_input = document.getElementById("invisible_file_input"); function sel_local_images() { if (invisible_file_input) { invisible_file_input.setAttribute('multiple', 'multiple'); invisible_file_input.accept = '.jpg,.jpeg,.png,.bmp'; invisible_file_input.onchange = (e)=>{ // 得到第一张图片 var img = e.target.files[0]; }; invisible_file_input.click(); } }
//reader有几个读取文件的方法用于读取成不一样格式,还有几个钩子函数用于不一样阶段执行一些功能 // var img =xxxxxxxxxxxx // 将图片的base64格式显示在页面上,图片可使用input上传 let reader = new FileReader(); reader.onload = (theFile)=>{ that.imgLoaded = e.target.result; // 2018-10-24 图片尚未加载完成,不是DOM的问题,使用onload才能正确得到原始宽高 var i = new Image(); i.src = e.target.result; i.onload = () => { img_loaded_width = i.width; img_loaded_height = i.height; }} // 这个貌似会执行上面的onload reader.readAsDataURL(img);
var blob = new Blob([JSON.stringify(data, null, 2)],{type : 'application/json'}); var aTag = document.getElementById('download_img'); aTag.setAttribute('href', URL.createObjectURL(blob)); aTag.setAttribute('download', that.imgLoadedName.split('.')[0]+'.json'); aTag.click();
第一种能够实现对拍照界面的重写,IPhone环境11开始兼容; 第二种方式其实是调用input[type='file'],会弹出一个选择框让用户选择是调用相机仍是调用相册, 第二种兼容优于第一种,很差的地方就是这种方法没法控制拍照,想要在移动端实现只能拍照不能选择照片或者在拍照界面添加引导遮罩层的方法是行不通了。
<video width="640" height="480" id="myVideo"></video> <canvas width="640" height="480" id="myCanvas"></canvas> <button id="myButton">截图</button> <button id="myButton2">预览</button> <button id="myButton3"> <a download="video.png">另存为</a> </button>
var cobj = document.getElementById('myCanvas').getContext('2d'); var vobj = document.getElementById('myVideo'); getUserMedia({video: true}, function (stream) { vobj.src = stream; vobj.play(); }, function () { }); document.getElementById('myButton').addEventListener('click', function () { cobj.drawImage(vobj, 0, 0, 640, 480); document.getElementById('myButton3').children[0].href = cobj.canvas.toDataURL("image/png"); }, false); document.getElementById('myButton2').addEventListener('click', function () { window.open(cobj.canvas.toDataURL("image/png"), '_blank'); }, false); function getUserMedia(obj, success, error) { if (navigator.getUserMedia) { getUserMedia = function (obj, success, error) { navigator.getUserMedia(obj, function (stream) { success(stream); }, error); } } else if (navigator.webkitGetUserMedia) { getUserMedia = function (obj, success, error) { navigator.webkitGetUserMedia(obj, function (stream) { var _URL = window.URL || window.webkitURL; success(_URL.createObjectURL(stream)); }, error); } } else if (navigator.mozGetUserMedia) { getUserMedia = function (obj, success, error) { navigator.mozGetUserMedia(obj, function (stream) { success(window.URL.createObjectURL(stream)); }, error); } } else { return false; } return getUserMedia(obj, success, error); }
有时候后端传过来的字符串中\\n转成字符对象时会成为\n可是在vue中渲染到页面中不会出现换行,而是显示为\n (compose.environment[key]).replace(/\\n/g,'\n') 而后就能够实现前端换行了 很奇怪 不知道为何
//{men:{name:'Kik',age:11},place:['A','B','C']} ArrayList<String> place = (ArrayList<String>) jsonObject.getObject("place", List.class);
String algorithmList = "["a","b","c"]" List<String> apacMainIdList = JSONObject.parseObject(algorithmList, List.class);
<!--使用absolute和top,left,right,bottom来完成div填充剩余部分--> <div style="position:absolute;background:#ccc;top:0;left:0;right:0;bottom:0;overflow:hidden"> <div style="position:absolute;width:140px;background:#C00;top:0;left:0;bottom:0"> </div> <div style="position:absolute;left:140px;background:#0C0;top:0;right:0;bottom:0;"> </div> </div>
// 读取为二进制 function createXHR(){ return window.XMLHttpRequest? new XMLHttpRequest(): new ActiveXObject("Microsoft.XMLHTTP"); } function getData(url){ let request = createXHR(); request.open("GET",url,false); request.responseType = 'blob'; request.onload = function () { var reader = new FileReader(); reader.readAsArrayBuffer(request.response); reader.onload = function (e) { var DAT_data = e.target.result; console.log("DAT_data:" + DAT_data); }; }; request.send(); }