_nghost-lli-c18
или _ngcontent-rja-c18
a[_ngcontent-rja-c18] {
color: red;
}
Стоит ли начинать писать сразу с помощью Typescript?
el.addEventListener('click', (evt) => {
console.log(evt)
})
el.addEventListener('click', function (evt) {
console.log(evt)
})
function mySuperFunc(evt) {
// еще десяток строк
console.log(evt)
}
const mySuperFunc = (evt) => {
// еще десяток строк
console.log(evt)
}
const mySuperFunc = (evt) => evt.target;
function mySuperFunc(evt) {
return evt.target;
}
Мне нужно, чтобы при самом первом запросе это поле не участвовало в запросе я этого добился тем, что убрал значение по дефолту в этом поле.
getCerts(): Observable<any> {
// ...
return new Observable(observer => {
chrome.runtime.sendMessage(editorExtensionId, message, res=> {
// ...
observer.next(result);
observer.complete();
})
}
})
return function(x) {
.function decorator(func) {
let cache = new Map();
return function decoratedFunc(x) {
if (cache.has(x)) {
return cache.get(x);
};
let result = func.call(this, x);
cache.set(x, result);
return result
}
}
obj.fac = decorator(obj.fac); // obj.fac === decoratedFunc
export const CHROME = new InjectionToken('CHROME');
providers: [
...
{
provide: CHROME,
useValue: window.chrome,
}
...
]
constructor(
@Inject(CHROME) private chrome: chrome,
)
Судя по данному PR в typescript можно использовать this в стрелочных функциях
This formulation is OK because lambda (=>) doesn't bind this, so this comes from the class instead of from the implementing function.
export interface DbConfig {
/** prefix for indexed db name */
name: string;
/** keyPath in indexed db */
keyPath?: string;
/** keyPath of indexed db */
objectName: string;
}
@Injectable()
export class DbService<T = any> {
private version = 1;
private db$: Observable<IDBDatabase> = this.createDb(this.config.name, this.version);
constructor(
@Inject(DB_CONFIG) private config: DbConfig,
) { }
private createDb(name: string, version?: number): Observable<IDBDatabase> {
const openRequest: IDBOpenDBRequest = indexedDB.open(name, version);
openRequest.onupgradeneeded = (evt: IDBVersionChangeEvent) => this.onUpgradeNeeded(openRequest);
return this.fromIDBRequest(openRequest).pipe(
shareReplay(1),
);
}
private onUpgradeNeeded(openRequest: IDBOpenDBRequest): void {
const db = openRequest.result;
if (db.objectStoreNames.contains(this.config.objectName)) {
return;
}
db.createObjectStore(this.config.objectName, { keyPath: this.config.keyPath });
}
public save(value: T, key?: IDBValidKey): Observable<IDBValidKey> {
return this.db$.pipe(
mergeMap((db: IDBDatabase) => this.fromIDBRequest(
this.createIDBObjectStore(db, 'readwrite').put(value, key)
)),
);
}
public saveAll(values: T[]): Observable<IDBValidKey[]> {
return from(values).pipe(
mergeMap((value: T, index: number) => this.save(value, index)),
toArray(),
);
}
public delete(key: string): Observable<undefined> {
return this.db$.pipe(
mergeMap(db => this.fromIDBRequest(
this.createIDBObjectStore(db, 'readwrite').delete(key),
))
);
}
public clear() {
return this.db$.pipe(
mergeMap(db => this.fromIDBRequest(
this.createIDBObjectStore(db, 'readwrite').clear(),
))
);
}
public retreive(key: string): Observable<T> {
return this.db$.pipe(
mergeMap(db => this.fromIDBRequest(
this.createIDBObjectStore(db, 'readonly').get(key)
)),
);
}
public retreiveAll(): Observable<T[]> {
return this.db$.pipe(
mergeMap(db => this.fromIDBRequest(
this.createIDBObjectStore(db, 'readonly').getAll()
)),
);
}
private createIDBObjectStore(db: IDBDatabase, mode: IDBTransactionMode): IDBObjectStore {
const transaction: IDBTransaction = db.transaction(this.config.objectName, mode);
return transaction.objectStore(this.config.objectName);
}
private fromIDBRequest<R>(idbRequest: IDBRequest<R>): Observable<R> {
return new Observable<R>(observer => {
idbRequest.onsuccess = (evt: Event) => {
observer.next(idbRequest.result);
observer.complete();
evt.stopPropagation();
};
idbRequest.onerror = (evt: Event) => {
observer.error(idbRequest.error);
evt.stopPropagation();
};
});
}
public selectDb() {
return this.db$;
}
}
Note: It's recommended to use the Web Storage API (setItem, getItem, removeItem, key, length) to prevent the pitfalls associated with using plain objects as key-value stores.
const path = require('path');
module.exports = {
entry: './src/index.ts',
devtool: 'inline-source-map',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
webpack --mode=production
webpack-dev-server --mode development --inline --hot
"devDependencies": {
"css-loader": "^3.0.0",
"ts-loader": "^6.0.4",
"tslint": "^5.18.0",
"tslint-config-airbnb": "^5.11.1",
"typescript": "^3.5.2",
"webpack": "^4.35.0",
"webpack-cli": "^3.3.5",
"webpack-dev-server": "^3.7.2"
}
{
"compilerOptions": {
"allowJs": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"incremental": true,
"module": "es6",
"noImplicitAny": false,
"outDir": "./dist/",
"sourceMap": true,
"target": "es2016"
}
}
{
"extends": "tslint-config-airbnb",
"rules": {}
}
<script src="dist/bundle.js"></script>
- если запрос длится более 500 мс, то показываем лоадер
- если лоадер уже показан, то отображать его не менее 300 мс